moved over some BM1397 driver code from bitskipc, renamed main c file

This commit is contained in:
Skot Croshere 2023-05-10 22:40:40 -04:00 committed by johnny9
parent 7e234ce8d5
commit bac80831db
13 changed files with 566 additions and 49 deletions

View File

@ -19,7 +19,9 @@
"led_controller.h": "c",
"*.tcc": "c",
"*.ipp": "c",
"complex": "cpp"
"complex": "cpp",
"uart_struct.h": "c",
"task.h": "c"
},
"idf.flashType": "UART"
}

View File

@ -1,2 +1,23 @@
idf_component_register(SRCS "system.c" "adc.c" "INA260.c" "EMC2101.c" "i2c_simple_main.c" "led_controller.c" "DS4432U.c" "EMC2101.c" "INA260.c" "adc.c" "oled.c" "fonts.c" "system.c"
INCLUDE_DIRS ".")
idf_component_register(SRCS
"pretty.c"
"crc.c"
"serial.c"
"system.c"
"adc.c"
"INA260.c"
"EMC2101.c"
"bitaxe.c"
"led_controller.c"
"DS4432U.c"
"EMC2101.c"
"INA260.c"
"adc.c"
"oled.c"
"fonts.c"
"system.c"
"bm1397.c"
"serial"
"bm1397.c"
"crc.c"
"pretty.c"
INCLUDE_DIRS ".")

24
main/bitaxe.c Executable file
View File

@ -0,0 +1,24 @@
#include <stdio.h>
#include <string.h>
#include "esp_log.h"
#include "driver/i2c.h"
#include "driver/gpio.h"
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include "system.h"
#include "serial.h"
static const char *TAG = "main";
TaskHandle_t sysTaskHandle = NULL;
TaskHandle_t serialTaskHandle = NULL;
void app_main(void) {
ESP_LOGI(TAG, "Welcome to the bitaxe!");
xTaskCreate(SysTask, "System_Task", 4096, NULL, 10, &sysTaskHandle);
xTaskCreate(SerialTask, "serial_test", 4096, NULL, 10, &serialTaskHandle);
}

211
main/bm1397.c Normal file
View File

@ -0,0 +1,211 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "serial.h"
#include "pretty.h"
#include "bm1397.h"
#include "crc.h"
#define SLEEP_TIME 20
static const char *TAG = "bm1397";
//reset the BM1397 via the RTS line
void reset_BM1397(void) {
gpio_set_level(BM1397_RST_PIN, 0);
//delay for 100ms
vTaskDelay(100 / portTICK_RATE_MS);
//set the gpio pin high
gpio_set_level(BM1397_RST_PIN, 1);
//delay for 100ms
vTaskDelay(100 / portTICK_RATE_MS);
}
void init_BM1397(void) {
ESP_LOGI(TAG, "Initializing BM1397");
gpio_pad_select_gpio(BM1397_RST_PIN);
gpio_set_direction(BM1397_RST_PIN, GPIO_MODE_OUTPUT);
}
//parse job/nonce response
void parse_job_response(unsigned char *buf, int len) {
struct nonce_response * nonce;
//get the response into the nonce struct
//memcpy((void *)&nonce, buf, len);
nonce = (struct nonce_response *)buf;
printf("nonce: %08X @ %02X\n", flip32(nonce->nonce), nonce->job_id);
}
void parse_cmd_packet(unsigned char *buf, int len) {
printf("cmd packet\n");
}
//split the response packet into individual packets
void split_response(unsigned char *buf, int len) {
int i;
int packet_len;
int packet_start = 0;
//split the response into individual packets
for (i = 1; i < len; i++) {
if ((buf[i] == 0xAA) && (buf[i+1] == 0x55)) {
packet_len = i - packet_start;
parse_packet(buf+packet_start, packet_len);
packet_start = i;
}
}
//parse the last packet
packet_len = i - packet_start;
parse_packet(buf+packet_start, packet_len);
}
//parse incoming packets
void parse_packet(unsigned char *buf, int len) {
response_type_t response_type;
//debug the packet
printf("<-");
prettyHex(buf, len);
printf("\n");
//determine response type
if (buf[len-1] & RESPONSE_JOB) {
response_type = JOB_RESP;
parse_job_response(buf, len);
} else {
response_type = CMD_RESP;
parse_cmd_packet(buf, len);
}
}
/// @brief
/// @param ftdi
/// @param header
/// @param data
/// @param len
void send_BM1397(uint8_t header, uint8_t * data, uint8_t data_len) {
packet_type_t packet_type = (header & TYPE_JOB) ? JOB_PACKET : CMD_PACKET;
uint8_t total_length = (packet_type == JOB_PACKET) ? (data_len+6) : (data_len+5);
//allocate memory for buffer
unsigned char *buf = malloc(total_length);
//add the preamble
buf[0] = 0x55;
buf[1] = 0xAA;
//add the header field
buf[2] = header;
//add the length field
buf[3] = (packet_type == JOB_PACKET) ? (data_len+4) : (data_len+3);
//add the data
memcpy(buf+4, data, data_len);
//add the correct crc type
if (packet_type == JOB_PACKET) {
uint16_t crc16_total = crc16_false(buf+2, data_len+2);
buf[4+data_len] = (crc16_total >> 8) & 0xFF;
buf[5+data_len] = crc16_total & 0xFF;
} else {
buf[4+data_len] = crc5(buf+2, data_len+2);
}
//send serial data
send_serial(buf, total_length);
free(buf);
}
void send_read_address(void) {
unsigned char read_address[2] = {0x00, 0x00};
//send serial data
send_BM1397((TYPE_CMD | GROUP_ALL | CMD_READ), read_address, 2);
}
void send_chain_inactive(void) {
unsigned char read_address[2] = {0x00, 0x00};
//send serial data
send_BM1397((TYPE_CMD | GROUP_ALL | CMD_INACTIVE), read_address, 2);
}
void set_chip_address(uint8_t chipAddr) {
unsigned char read_address[2] = {chipAddr, 0x00};
//send serial data
send_BM1397((TYPE_CMD | GROUP_SINGLE | CMD_SETADDRESS), read_address, 2);
}
void send_init(void) {
//send serial data
vTaskDelay(SLEEP_TIME / portTICK_RATE_MS);
send_chain_inactive();
set_chip_address(0x00);
unsigned char init[6] = {0x00, 0x80, 0x00, 0x00, 0x00, 0x00}; //init1 - clock_order_control0
send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), init, 6);
unsigned char init2[6] = {0x00, 0x84, 0x00, 0x00, 0x00, 0x00}; //init2 - clock_order_control1
send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), init2, 6);
unsigned char init3[9] = {0x00, 0x20, 0x00, 0x00, 0x00, 0x01}; //init3 - ordered_clock_enable
send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), init3, 6);
unsigned char init4[9] = {0x00, 0x3C, 0x80, 0x00, 0x80, 0x74}; //init4 - init_4_?
send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), init4, 6);
unsigned char set_ticket[9] = {0x00, 0x14, 0x00, 0x00, 0x00, 0x00}; //set_ticket - ticket_mask
send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), set_ticket, 6);
unsigned char init5[9] = {0x00, 0x68, 0xC0, 0x70, 0x01, 0x11}; //init5 - pll3_parameter
send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), init5, 6);
unsigned char init5_2[9] = {0x00, 0x68, 0xC0, 0x70, 0x01, 0x11}; //init5_2 - pll3_parameter
send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), init5_2, 6);
unsigned char init6[9] = {0x00, 0x28, 0x06, 0x00, 0x00, 0x0F}; //init6 - fast_uart_configuration
send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), init6, 6);
unsigned char baudrate[9] = {0x00, 0x18, 0x00, 0x00, 0x7A, 0x31}; //baudrate - misc_control
send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), baudrate, 6);
unsigned char prefreq1[9] = {0x00, 0x70, 0x0F, 0x0F, 0x0F, 0x00}; //prefreq - pll0_divider
send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), prefreq1, 6);
unsigned char freqbuf[9] = {0x00, 0x08, 0x40, 0xA0, 0x02, 0x25}; //freqbuf - pll0_parameter
send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), freqbuf, 6);
}
void send_work(struct job_packet *job) {
send_BM1397((TYPE_JOB | GROUP_SINGLE | CMD_WRITE), (uint8_t*)job, sizeof(struct job_packet));
}

64
main/bm1397.h Normal file
View File

@ -0,0 +1,64 @@
#ifndef BM1397_H_
#define BM1397_H_
#include "driver/gpio.h"
#define BM1397_RST_PIN GPIO_NUM_1
#define TYPE_JOB 0x20
#define TYPE_CMD 0x40
#define GROUP_SINGLE 0x00
#define GROUP_ALL 0x10
#define CMD_JOB 0x01
#define CMD_SETADDRESS 0x00
#define CMD_WRITE 0x01
#define CMD_READ 0x02
#define CMD_INACTIVE 0x03
#define RESPONSE_CMD 0x00
#define RESPONSE_JOB 0x80
#define CRC5_MASK 0x1F
typedef enum {
JOB_PACKET = 0,
CMD_PACKET = 1,
} packet_type_t;
typedef enum {
JOB_RESP = 0,
CMD_RESP = 1,
} response_type_t;
struct __attribute__((__packed__)) job_packet {
uint8_t job_id;
uint8_t num_midstates;
uint8_t starting_nonce[4];
uint8_t nbits[4];
uint8_t ntime[4];
uint8_t merkle4[4];
uint8_t midstates[4][32];
};
struct __attribute__((__packed__)) nonce_response {
uint8_t preamble[2];
uint32_t nonce;
uint8_t midstate_num;
uint8_t job_id;
uint8_t crc;
};
void send_read_address(void);
void send_init(void);
void send_work(struct job_packet *job);
void parse_packet(unsigned char *buf, int len);
void split_response(unsigned char *buf, int len);
void reset_BM1397(void);
void init_BM1397(void);
#endif /* BM1397_H_ */

106
main/crc.c Normal file
View File

@ -0,0 +1,106 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "bm1397.h"
/* compute crc5 over given number of bytes */
//adapted from https://mightydevices.com/index.php/2018/02/reverse-engineering-antminer-s1/
uint8_t crc5(uint8_t * data, uint8_t len) {
uint8_t i, j, k, index = 0;
uint8_t crc = CRC5_MASK;
/* registers */
uint8_t crcin[5] = {1, 1, 1, 1, 1};
uint8_t crcout[5] = {1, 1, 1, 1, 1};
uint8_t din = 0;
len *= 8;
/* push data bits */
for (j = 0x80, k = 0, i = 0; i < len; i++) {
/* input bit */
din = (data[index] & j) != 0;
/* shift register */
crcout[0] = crcin[4] ^ din;
crcout[1] = crcin[0];
crcout[2] = crcin[1] ^ crcin[4] ^ din;
crcout[3] = crcin[2];
crcout[4] = crcin[3];
/* next bit */
j >>= 1, k++;
/* next byte */
if (k == 8)
j = 0x80, k = 0, index++;
/* apply new shift register value */
memcpy(crcin, crcout, 5);
//crcin = crcout[0];
}
crc = 0;
/* extract bitmask from register */
if (crcin[4]) crc |= 0x10;
if (crcin[3]) crc |= 0x08;
if (crcin[2]) crc |= 0x04;
if (crcin[1]) crc |= 0x02;
if (crcin[0]) crc |= 0x01;
return crc;
}
//kindly provided by cgminer
unsigned int crc16_table[256] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
};
/* CRC-16/CCITT */
uint16_t crc16(uint8_t *buffer, uint16_t len) {
uint16_t crc;
crc = 0;
while(len-- > 0)
crc = crc16_table[((crc >> 8) ^ (*buffer++)) & 0xFF] ^ (crc << 8);
return crc;
}
/* CRC-16/CCITT-FALSE */
uint16_t crc16_false(uint8_t *buffer, uint16_t len) {
uint16_t crc;
crc = 0xffff;
while(len-- > 0)
crc = crc16_table[((crc >> 8) ^ (*buffer++)) & 0xFF] ^ (crc << 8);
return crc;
}

8
main/crc.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef CRC_H_
#define CRC_H_
uint8_t crc5(uint8_t * data, uint8_t len);
unsigned short crc16(const unsigned char *buffer, int len);
unsigned short crc16_false(const unsigned char *buffer, int len);
#endif // PRETTY_H_

View File

@ -1,38 +0,0 @@
/* i2c - Simple example
Simple I2C example that shows how to initialize I2C
as well as reading and writing from and to registers for a sensor connected over I2C.
For other examples please check:
https://github.com/espressif/esp-idf/tree/master/examples
See README.md file to get detailed usage of this example.
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <string.h>
#include "esp_log.h"
#include "driver/i2c.h"
#include "driver/gpio.h"
// Include FreeRTOS for delay
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include "system.h"
static const char *TAG = "main";
TaskHandle_t sysTaskHandle = NULL;
void app_main(void) {
ESP_LOGI(TAG, "Welcome to The bitaxe!");
xTaskCreate(SysTask, "System_Task", 4096, NULL, 10, &sysTaskHandle);
}

27
main/pretty.c Normal file
View File

@ -0,0 +1,27 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <time.h>
#include <errno.h>
#include "pretty.h"
void prettyHex(unsigned char * buf, int len) {
int i;
for (i = 0; i < len; i++) {
if ((i > 0) && (buf[i] == 0xAA) && (buf[i+1] == 0x55))
printf("\n");
printf("%02X ", buf[i]);
}
}
//flip byte order of a 32 bit integer
uint32_t flip32(uint32_t val) {
uint32_t ret = 0;
ret |= (val & 0xFF) << 24;
ret |= (val & 0xFF00) << 8;
ret |= (val & 0xFF0000) >> 8;
ret |= (val & 0xFF000000) >> 24;
return ret;
}

9
main/pretty.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef PRETTY_H_
#define PRETTY_H_
#include <stdint.h>
void prettyHex(unsigned char * buf, int len);
uint32_t flip32(uint32_t val);
#endif // PRETTY_H_

72
main/serial.c Normal file
View File

@ -0,0 +1,72 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/uart.h"
#include "esp_log.h"
#include "soc/uart_struct.h"
#include "pretty.h"
#include "bm1397.h"
#define ECHO_TEST_TXD (17)
#define ECHO_TEST_RXD (18)
#define BUF_SIZE (1024)
static const char *TAG = "serial";
void init_serial(void) {
ESP_LOGI(TAG, "Initializing serial");
//Configure UART1 parameters
uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.rx_flow_ctrl_thresh = 122,
};
//Configure UART1 parameters
uart_param_config(UART_NUM_1, &uart_config);
//Set UART1 pins(TX: IO17, RX: I018)
uart_set_pin(UART_NUM_1, ECHO_TEST_TXD, ECHO_TEST_RXD, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
//Install UART driver (we don't need an event queue here)
//In this example we don't even use a buffer for sending data.
uart_driver_install(UART_NUM_1, BUF_SIZE * 2, 0, 0, NULL, 0);
}
int send_serial(uint8_t *data, int len) {
printf("->");
prettyHex((unsigned char*)data, len);
printf("\n");
return uart_write_bytes(UART_NUM_1, (const char *) data, len);
}
void SerialTask(void *arg) {
unsigned char data[BUF_SIZE];
init_serial();
init_BM1397();
//reset the bm1397
reset_BM1397();
while(1) {
//Read data from UART
int len = uart_read_bytes(UART_NUM_1, data, BUF_SIZE, 20 / portTICK_RATE_MS);
if (len > 0) {
data[len] = 0;
printf("Read %d bytes: ", len);
prettyHex(data, len);
printf("\n");
}
}
}

7
main/serial.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef SERIAL_H_
#define SERIAL_H_
void SerialTask(void *arg);
int send_serial(uint8_t *, int);
#endif /* SERIAL_H_ */

View File

@ -42,6 +42,10 @@ void init_system(void) {
//oled
if (!OLED_init()) {
ESP_LOGI(TAG, "OLED init failed!");
} else {
ESP_LOGI(TAG, "OLED init success!");
//clear the oled screen
OLED_fill(0);
}
}
@ -55,16 +59,16 @@ void get_stats(void) {
float power = INA260_read_power();
uint16_t vcore = ADC_get_vcore();
ESP_LOGI(TAG, "Fan Speed: %d RPM", fan_speed);
ESP_LOGI(TAG, "Chip Temp: %.2f C", chip_temp);
// ESP_LOGI(TAG, "Fan Speed: %d RPM", fan_speed);
// ESP_LOGI(TAG, "Chip Temp: %.2f C", chip_temp);
//Current Sensor tests
ESP_LOGI(TAG, "Current: %.2f mA", current);
ESP_LOGI(TAG, "Voltage: %.2f mV", voltage);
ESP_LOGI(TAG, "Power: %.2f mW", power);
// //Current Sensor tests
// ESP_LOGI(TAG, "Current: %.2f mA", current);
// ESP_LOGI(TAG, "Voltage: %.2f mV", voltage);
// ESP_LOGI(TAG, "Power: %.2f mW", power);
//ESP32 ADC tests
ESP_LOGI(TAG, "Vcore: %d mV\n", vcore);
// //ESP32 ADC tests
// ESP_LOGI(TAG, "Vcore: %d mV\n", vcore);
if (OLED_status()) {
memset(oled_buf, 0, 20);