mirror of
https://github.com/skot/ESP-Miner.git
synced 2025-03-17 13:22:53 +01:00
reformat entire c project
This commit is contained in:
parent
199c151c0f
commit
79430f6d3a
components
bm1397
connect
stratum
main
DS4432U.cEMC2101.cEMC2101.hINA260.cINA260.hadc.cfonts.cglobal_state.h
http_server
led_controller.cmain.cnvs_config.cnvs_config.holed.coled.hsystem.csystem.htasks
asic_result_task.casic_result_task.hasic_task.casic_task.hcreate_jobs_task.ccreate_jobs_task.hpower_management_task.hstratum_task.cstratum_task.huser_input_task.cuser_input_task.h
work_queue.cwork_queue.htest/main
File diff suppressed because it is too large
Load Diff
@ -15,8 +15,7 @@
|
||||
#include "mining.h"
|
||||
#include "global_state.h"
|
||||
|
||||
#define BM1397_RST_PIN GPIO_NUM_1
|
||||
|
||||
#define BM1397_RST_PIN GPIO_NUM_1
|
||||
|
||||
#define TYPE_JOB 0x20
|
||||
#define TYPE_CMD 0x40
|
||||
@ -34,7 +33,6 @@
|
||||
#define RESPONSE_CMD 0x00
|
||||
#define RESPONSE_JOB 0x80
|
||||
|
||||
|
||||
#define SLEEP_TIME 20
|
||||
#define FREQ_MULT 25.0
|
||||
|
||||
@ -47,7 +45,8 @@
|
||||
#define TICKET_MASK 0x14
|
||||
#define MISC_CONTROL 0x18
|
||||
|
||||
typedef struct __attribute__((__packed__)) {
|
||||
typedef struct __attribute__((__packed__))
|
||||
{
|
||||
uint8_t preamble[2];
|
||||
uint32_t nonce;
|
||||
uint8_t midstate_num;
|
||||
@ -66,155 +65,177 @@ static task_result result;
|
||||
/// @param header
|
||||
/// @param data
|
||||
/// @param len
|
||||
static void _send_BM1397(uint8_t header, uint8_t * data, uint8_t data_len, bool debug) {
|
||||
static void _send_BM1397(uint8_t header, uint8_t *data, uint8_t data_len, bool debug)
|
||||
{
|
||||
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);
|
||||
uint8_t total_length = (packet_type == JOB_PACKET) ? (data_len + 6) : (data_len + 5);
|
||||
|
||||
//allocate memory for buffer
|
||||
// allocate memory for buffer
|
||||
unsigned char *buf = malloc(total_length);
|
||||
|
||||
//add the preamble
|
||||
// add the preamble
|
||||
buf[0] = 0x55;
|
||||
buf[1] = 0xAA;
|
||||
|
||||
//add the header field
|
||||
// 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 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 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);
|
||||
// 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 data
|
||||
SERIAL_send(buf, total_length, debug);
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
||||
static void _send_chain_inactive(void) {
|
||||
static void _send_chain_inactive(void)
|
||||
{
|
||||
|
||||
unsigned char read_address[2] = {0x00, 0x00};
|
||||
//send serial data
|
||||
// send serial data
|
||||
_send_BM1397((TYPE_CMD | GROUP_ALL | CMD_INACTIVE), read_address, 2, false);
|
||||
}
|
||||
|
||||
static void _set_chip_address(uint8_t chipAddr) {
|
||||
static void _set_chip_address(uint8_t chipAddr)
|
||||
{
|
||||
|
||||
unsigned char read_address[2] = {chipAddr, 0x00};
|
||||
//send serial data
|
||||
// send serial data
|
||||
_send_BM1397((TYPE_CMD | GROUP_SINGLE | CMD_SETADDRESS), read_address, 2, false);
|
||||
}
|
||||
|
||||
|
||||
// borrowed from cgminer driver-gekko.c calc_gsf_freq()
|
||||
void BM1397_send_hash_frequency(float frequency) {
|
||||
void BM1397_send_hash_frequency(float frequency)
|
||||
{
|
||||
|
||||
unsigned char prefreq1[9] = {0x00, 0x70, 0x0F, 0x0F, 0x0F, 0x00}; //prefreq - pll0_divider
|
||||
unsigned char prefreq1[9] = {0x00, 0x70, 0x0F, 0x0F, 0x0F, 0x00}; // prefreq - pll0_divider
|
||||
|
||||
// default 200Mhz if it fails
|
||||
unsigned char freqbuf[9] = {0x00, 0x08, 0x40, 0xA0, 0x02, 0x25}; //freqbuf - pll0_parameter
|
||||
// default 200Mhz if it fails
|
||||
unsigned char freqbuf[9] = {0x00, 0x08, 0x40, 0xA0, 0x02, 0x25}; // freqbuf - pll0_parameter
|
||||
|
||||
float deffreq = 200.0;
|
||||
float deffreq = 200.0;
|
||||
|
||||
float fa, fb, fc1, fc2, newf;
|
||||
float f1, basef, famax = 0xf0, famin = 0x10;
|
||||
int i;
|
||||
float fa, fb, fc1, fc2, newf;
|
||||
float f1, basef, famax = 0xf0, famin = 0x10;
|
||||
int i;
|
||||
|
||||
//bound the frequency setting
|
||||
// You can go as low as 13 but it doesn't really scale or
|
||||
// produce any nonces
|
||||
if (frequency < 50) {
|
||||
// bound the frequency setting
|
||||
// You can go as low as 13 but it doesn't really scale or
|
||||
// produce any nonces
|
||||
if (frequency < 50)
|
||||
{
|
||||
f1 = 50;
|
||||
} else if (frequency > 500) {
|
||||
}
|
||||
else if (frequency > 500)
|
||||
{
|
||||
f1 = 500;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
f1 = frequency;
|
||||
}
|
||||
|
||||
fb = 2;
|
||||
fc1 = 1;
|
||||
fc2 = 5; // initial multiplier of 10
|
||||
if (f1 >= 500)
|
||||
{
|
||||
// halve down to '250-400'
|
||||
fb = 1;
|
||||
}
|
||||
else if (f1 <= 150)
|
||||
{
|
||||
// triple up to '300-450'
|
||||
fc1 = 3;
|
||||
}
|
||||
else if (f1 <= 250)
|
||||
{
|
||||
// double up to '300-500'
|
||||
fc1 = 2;
|
||||
}
|
||||
// else f1 is 250-500
|
||||
|
||||
fb = 2; fc1 = 1; fc2 = 5; // initial multiplier of 10
|
||||
if (f1 >= 500) {
|
||||
// halve down to '250-400'
|
||||
fb = 1;
|
||||
} else if (f1 <= 150) {
|
||||
// triple up to '300-450'
|
||||
fc1 = 3;
|
||||
} else if (f1 <= 250) {
|
||||
// double up to '300-500'
|
||||
fc1 = 2;
|
||||
}
|
||||
// else f1 is 250-500
|
||||
// f1 * fb * fc1 * fc2 is between 2500 and 5000
|
||||
// - so round up to the next 25 (freq_mult)
|
||||
basef = FREQ_MULT * ceil(f1 * fb * fc1 * fc2 / FREQ_MULT);
|
||||
|
||||
// f1 * fb * fc1 * fc2 is between 2500 and 5000
|
||||
// - so round up to the next 25 (freq_mult)
|
||||
basef = FREQ_MULT * ceil(f1 * fb * fc1 * fc2 / FREQ_MULT);
|
||||
// fa should be between 100 (0x64) and 200 (0xC8)
|
||||
fa = basef / FREQ_MULT;
|
||||
|
||||
// fa should be between 100 (0x64) and 200 (0xC8)
|
||||
fa = basef / FREQ_MULT;
|
||||
// code failure ... basef isn't 400 to 6000
|
||||
if (fa < famin || fa > famax)
|
||||
{
|
||||
newf = deffreq;
|
||||
}
|
||||
else
|
||||
{
|
||||
freqbuf[3] = (int)fa;
|
||||
freqbuf[4] = (int)fb;
|
||||
// fc1, fc2 'should' already be 1..15
|
||||
freqbuf[5] = (((int)fc1 & 0xf) << 4) + ((int)fc2 & 0xf);
|
||||
|
||||
// code failure ... basef isn't 400 to 6000
|
||||
if (fa < famin || fa > famax) {
|
||||
newf = deffreq;
|
||||
} else {
|
||||
freqbuf[3] = (int)fa;
|
||||
freqbuf[4] = (int)fb;
|
||||
// fc1, fc2 'should' already be 1..15
|
||||
freqbuf[5] = (((int)fc1 & 0xf) << 4) + ((int)fc2 & 0xf);
|
||||
|
||||
newf = basef / ((float)fb * (float)fc1 * (float)fc2);
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
_send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), prefreq1, 6, false);
|
||||
}
|
||||
for (i = 0; i < 2; i++) {
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
_send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), freqbuf, 6, false);
|
||||
}
|
||||
newf = basef / ((float)fb * (float)fc1 * (float)fc2);
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
_send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), prefreq1, 6, false);
|
||||
}
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
_send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), freqbuf, 6, false);
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Setting Frequency to %.2fMHz (%.2f)", frequency, newf);
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
|
||||
ESP_LOGI(TAG, "Setting Frequency to %.2fMHz (%.2f)", frequency, newf);
|
||||
}
|
||||
|
||||
static void _send_init(u_int64_t frequency) {
|
||||
static void _send_init(u_int64_t frequency)
|
||||
{
|
||||
|
||||
//send serial data
|
||||
// send serial data
|
||||
vTaskDelay(SLEEP_TIME / portTICK_PERIOD_MS);
|
||||
_send_chain_inactive();
|
||||
|
||||
_set_chip_address(0x00);
|
||||
|
||||
unsigned char init[6] = {0x00, CLOCK_ORDER_CONTROL_0, 0x00, 0x00, 0x00, 0x00}; //init1 - clock_order_control0
|
||||
unsigned char init[6] = {0x00, CLOCK_ORDER_CONTROL_0, 0x00, 0x00, 0x00, 0x00}; // init1 - clock_order_control0
|
||||
_send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), init, 6, false);
|
||||
|
||||
unsigned char init2[6] = {0x00, CLOCK_ORDER_CONTROL_1, 0x00, 0x00, 0x00, 0x00}; //init2 - clock_order_control1
|
||||
unsigned char init2[6] = {0x00, CLOCK_ORDER_CONTROL_1, 0x00, 0x00, 0x00, 0x00}; // init2 - clock_order_control1
|
||||
_send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), init2, 6, false);
|
||||
|
||||
unsigned char init3[9] = {0x00, ORDERED_CLOCK_ENABLE, 0x00, 0x00, 0x00, 0x01}; //init3 - ordered_clock_enable
|
||||
unsigned char init3[9] = {0x00, ORDERED_CLOCK_ENABLE, 0x00, 0x00, 0x00, 0x01}; // init3 - ordered_clock_enable
|
||||
_send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), init3, 6, false);
|
||||
|
||||
unsigned char init4[9] = {0x00, CORE_REGISTER_CONTROL, 0x80, 0x00, 0x80, 0x74}; //init4 - init_4_?
|
||||
unsigned char init4[9] = {0x00, CORE_REGISTER_CONTROL, 0x80, 0x00, 0x80, 0x74}; // init4 - init_4_?
|
||||
_send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), init4, 6, false);
|
||||
|
||||
BM1397_set_job_difficulty_mask(256);
|
||||
|
||||
unsigned char init5[9] = {0x00, PLL3_PARAMETER, 0xC0, 0x70, 0x01, 0x11}; //init5 - pll3_parameter
|
||||
unsigned char init5[9] = {0x00, PLL3_PARAMETER, 0xC0, 0x70, 0x01, 0x11}; // init5 - pll3_parameter
|
||||
_send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), init5, 6, false);
|
||||
|
||||
unsigned char init6[9] = {0x00, FAST_UART_CONFIGURATION, 0x06, 0x00, 0x00, 0x0F}; //init6 - fast_uart_configuration
|
||||
unsigned char init6[9] = {0x00, FAST_UART_CONFIGURATION, 0x06, 0x00, 0x00, 0x0F}; // init6 - fast_uart_configuration
|
||||
_send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), init6, 6, false);
|
||||
|
||||
BM1397_set_default_baud();
|
||||
@ -222,31 +243,31 @@ static void _send_init(u_int64_t frequency) {
|
||||
BM1397_send_hash_frequency(frequency);
|
||||
}
|
||||
|
||||
|
||||
//reset the BM1397 via the RTS line
|
||||
static void _reset(void) {
|
||||
// reset the BM1397 via the RTS line
|
||||
static void _reset(void)
|
||||
{
|
||||
gpio_set_level(BM1397_RST_PIN, 0);
|
||||
|
||||
//delay for 100ms
|
||||
// delay for 100ms
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
|
||||
//set the gpio pin high
|
||||
// set the gpio pin high
|
||||
gpio_set_level(BM1397_RST_PIN, 1);
|
||||
|
||||
//delay for 100ms
|
||||
// delay for 100ms
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
|
||||
static void _send_read_address(void) {
|
||||
static void _send_read_address(void)
|
||||
{
|
||||
|
||||
unsigned char read_address[2] = {0x00, 0x00};
|
||||
//send serial data
|
||||
// send serial data
|
||||
_send_BM1397((TYPE_CMD | GROUP_ALL | CMD_READ), read_address, 2, false);
|
||||
}
|
||||
|
||||
|
||||
void BM1397_init(u_int64_t frequency) {
|
||||
void BM1397_init(u_int64_t frequency)
|
||||
{
|
||||
ESP_LOGI(TAG, "Initializing BM1397");
|
||||
|
||||
memset(asic_response_buffer, 0, sizeof(asic_response_buffer));
|
||||
@ -254,38 +275,37 @@ void BM1397_init(u_int64_t frequency) {
|
||||
esp_rom_gpio_pad_select_gpio(BM1397_RST_PIN);
|
||||
gpio_set_direction(BM1397_RST_PIN, GPIO_MODE_OUTPUT);
|
||||
|
||||
//reset the bm1397
|
||||
// reset the bm1397
|
||||
_reset();
|
||||
|
||||
//send the init command
|
||||
// send the init command
|
||||
_send_read_address();
|
||||
|
||||
_send_init(frequency);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Baud formula = 25M/((denominator+1)*8)
|
||||
// The denominator is 5 bits found in the misc_control (bits 9-13)
|
||||
int BM1397_set_default_baud(void){
|
||||
//default divider of 26 (11010) for 115,749
|
||||
unsigned char baudrate[9] = {0x00, MISC_CONTROL, 0x00, 0x00, 0b01111010, 0b00110001}; //baudrate - misc_control
|
||||
int BM1397_set_default_baud(void)
|
||||
{
|
||||
// default divider of 26 (11010) for 115,749
|
||||
unsigned char baudrate[9] = {0x00, MISC_CONTROL, 0x00, 0x00, 0b01111010, 0b00110001}; // baudrate - misc_control
|
||||
_send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), baudrate, 6, false);
|
||||
return 115749;
|
||||
}
|
||||
|
||||
int BM1397_set_max_baud(void){
|
||||
int BM1397_set_max_baud(void)
|
||||
{
|
||||
// divider of 0 for 3,125,000
|
||||
ESP_LOGI(TAG, "Setting max baud of 3125000");
|
||||
unsigned char baudrate[9] = { 0x00, MISC_CONTROL, 0x00, 0x00, 0b01100000, 0b00110001 };; //baudrate - misc_control
|
||||
unsigned char baudrate[9] = {0x00, MISC_CONTROL, 0x00, 0x00, 0b01100000, 0b00110001};
|
||||
; // baudrate - misc_control
|
||||
_send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), baudrate, 6, false);
|
||||
return 3125000;
|
||||
}
|
||||
|
||||
void BM1397_set_job_difficulty_mask(int difficulty){
|
||||
void BM1397_set_job_difficulty_mask(int difficulty)
|
||||
{
|
||||
|
||||
// Default mask of 256 diff
|
||||
unsigned char job_difficulty_mask[9] = {0x00, TICKET_MASK, 0b00000000, 0b00000000, 0b00000000, 0b11111111};
|
||||
@ -293,16 +313,17 @@ void BM1397_set_job_difficulty_mask(int difficulty){
|
||||
// The mask must be a power of 2 so there are no holes
|
||||
// Correct: {0b00000000, 0b00000000, 0b11111111, 0b11111111}
|
||||
// Incorrect: {0b00000000, 0b00000000, 0b11100111, 0b11111111}
|
||||
difficulty = _largest_power_of_two(difficulty) -1; // (difficulty - 1) if it is a pow 2 then step down to second largest for more hashrate sampling
|
||||
difficulty = _largest_power_of_two(difficulty) - 1; // (difficulty - 1) if it is a pow 2 then step down to second largest for more hashrate sampling
|
||||
|
||||
// convert difficulty into char array
|
||||
// Ex: 256 = {0b00000000, 0b00000000, 0b00000000, 0b11111111}, {0x00, 0x00, 0x00, 0xff}
|
||||
// Ex: 512 = {0b00000000, 0b00000000, 0b00000001, 0b11111111}, {0x00, 0x00, 0x01, 0xff}
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
char value = (difficulty >> (8 * i)) & 0xFF;
|
||||
//The char is read in backwards to the register so we need to reverse them
|
||||
//So a mask of 512 looks like 0b00000000 00000000 00000001 1111111
|
||||
//and not 0b00000000 00000000 10000000 1111111
|
||||
// The char is read in backwards to the register so we need to reverse them
|
||||
// So a mask of 512 looks like 0b00000000 00000000 00000001 1111111
|
||||
// and not 0b00000000 00000000 10000000 1111111
|
||||
|
||||
job_difficulty_mask[5 - i] = _reverse_bits(value);
|
||||
}
|
||||
@ -312,82 +333,83 @@ void BM1397_set_job_difficulty_mask(int difficulty){
|
||||
_send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), job_difficulty_mask, 6, false);
|
||||
}
|
||||
|
||||
|
||||
static uint8_t id = 0;
|
||||
|
||||
void BM1397_send_work(void *pvParameters, bm_job *next_bm_job) {
|
||||
void BM1397_send_work(void *pvParameters, bm_job *next_bm_job)
|
||||
{
|
||||
|
||||
GlobalState *GLOBAL_STATE = (GlobalState*) pvParameters;
|
||||
GlobalState *GLOBAL_STATE = (GlobalState *)pvParameters;
|
||||
|
||||
job_packet job;
|
||||
// max job number is 128
|
||||
// there is still some really weird logic with the job id bits for the asic to sort out
|
||||
// so we have it limited to 128 and it has to increment by 4
|
||||
id = (id + 4) % 128;
|
||||
job_packet job;
|
||||
// max job number is 128
|
||||
// there is still some really weird logic with the job id bits for the asic to sort out
|
||||
// so we have it limited to 128 and it has to increment by 4
|
||||
id = (id + 4) % 128;
|
||||
|
||||
job.job_id = id;
|
||||
job.num_midstates = next_bm_job->num_midstates;
|
||||
memcpy(&job.starting_nonce, &next_bm_job->starting_nonce, 4);
|
||||
memcpy(&job.nbits, &next_bm_job->target, 4);
|
||||
memcpy(&job.ntime, &next_bm_job->ntime, 4);
|
||||
memcpy(&job.merkle4, next_bm_job->merkle_root + 28, 4);
|
||||
memcpy(job.midstate, next_bm_job->midstate, 32);
|
||||
job.job_id = id;
|
||||
job.num_midstates = next_bm_job->num_midstates;
|
||||
memcpy(&job.starting_nonce, &next_bm_job->starting_nonce, 4);
|
||||
memcpy(&job.nbits, &next_bm_job->target, 4);
|
||||
memcpy(&job.ntime, &next_bm_job->ntime, 4);
|
||||
memcpy(&job.merkle4, next_bm_job->merkle_root + 28, 4);
|
||||
memcpy(job.midstate, next_bm_job->midstate, 32);
|
||||
|
||||
if (job.num_midstates == 4)
|
||||
{
|
||||
memcpy(job.midstate1, next_bm_job->midstate1, 32);
|
||||
memcpy(job.midstate2, next_bm_job->midstate2, 32);
|
||||
memcpy(job.midstate3, next_bm_job->midstate3, 32);
|
||||
}
|
||||
|
||||
if (job.num_midstates == 4)
|
||||
{
|
||||
memcpy(job.midstate1, next_bm_job->midstate1, 32);
|
||||
memcpy(job.midstate2, next_bm_job->midstate2, 32);
|
||||
memcpy(job.midstate3, next_bm_job->midstate3, 32);
|
||||
}
|
||||
if (GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job.job_id] != NULL)
|
||||
{
|
||||
free_bm_job(GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job.job_id]);
|
||||
}
|
||||
|
||||
if (GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job.job_id] != NULL) {
|
||||
free_bm_job(GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job.job_id]);
|
||||
}
|
||||
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job.job_id] = next_bm_job;
|
||||
|
||||
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job.job_id] = next_bm_job;
|
||||
pthread_mutex_lock(&GLOBAL_STATE->valid_jobs_lock);
|
||||
GLOBAL_STATE->valid_jobs[job.job_id] = 1;
|
||||
// ESP_LOGI(TAG, "Added Job: %i", job.job_id);
|
||||
pthread_mutex_unlock(&GLOBAL_STATE->valid_jobs_lock);
|
||||
|
||||
pthread_mutex_lock(&GLOBAL_STATE->valid_jobs_lock);
|
||||
GLOBAL_STATE-> valid_jobs[job.job_id] = 1;
|
||||
//ESP_LOGI(TAG, "Added Job: %i", job.job_id);
|
||||
pthread_mutex_unlock(&GLOBAL_STATE->valid_jobs_lock);
|
||||
|
||||
_send_BM1397((TYPE_JOB | GROUP_SINGLE | CMD_WRITE), &job, sizeof(job_packet), false);
|
||||
_send_BM1397((TYPE_JOB | GROUP_SINGLE | CMD_WRITE), &job, sizeof(job_packet), false);
|
||||
}
|
||||
|
||||
asic_result *BM1397_receive_work(void)
|
||||
{
|
||||
|
||||
|
||||
|
||||
asic_result * BM1397_receive_work(void){
|
||||
|
||||
//wait for a response, wait time is pretty arbitrary
|
||||
// wait for a response, wait time is pretty arbitrary
|
||||
int received = SERIAL_rx(asic_response_buffer, 9, 60000);
|
||||
|
||||
if (received < 0) {
|
||||
if (received < 0)
|
||||
{
|
||||
ESP_LOGI(TAG, "Error in serial RX");
|
||||
return NULL;
|
||||
} else if(received == 0){
|
||||
}
|
||||
else if (received == 0)
|
||||
{
|
||||
// Didn't find a solution, restart and try again
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(received != 9 || asic_response_buffer[0] != 0xAA || asic_response_buffer[1] != 0x55){
|
||||
if (received != 9 || asic_response_buffer[0] != 0xAA || asic_response_buffer[1] != 0x55)
|
||||
{
|
||||
ESP_LOGI(TAG, "Serial RX invalid %i", received);
|
||||
ESP_LOG_BUFFER_HEX(TAG, asic_response_buffer, received);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return (asic_result*) asic_response_buffer;
|
||||
return (asic_result *)asic_response_buffer;
|
||||
}
|
||||
|
||||
|
||||
task_result * BM1397_proccess_work(void *pvParameters){
|
||||
task_result *BM1397_proccess_work(void *pvParameters)
|
||||
{
|
||||
|
||||
asic_result *asic_result = BM1397_receive_work();
|
||||
|
||||
if(asic_result == NULL){
|
||||
if (asic_result == NULL)
|
||||
{
|
||||
ESP_LOGI(TAG, "return null");
|
||||
return NULL;
|
||||
}
|
||||
@ -396,44 +418,47 @@ task_result * BM1397_proccess_work(void *pvParameters){
|
||||
uint8_t nonce_found = 0;
|
||||
uint32_t first_nonce = 0;
|
||||
|
||||
|
||||
uint8_t rx_job_id = asic_result->job_id & 0xfc;
|
||||
uint8_t rx_midstate_index = asic_result->job_id & 0x03;
|
||||
|
||||
|
||||
GlobalState *GLOBAL_STATE = (GlobalState*) pvParameters;
|
||||
if (GLOBAL_STATE->valid_jobs[rx_job_id] == 0) {
|
||||
GlobalState *GLOBAL_STATE = (GlobalState *)pvParameters;
|
||||
if (GLOBAL_STATE->valid_jobs[rx_job_id] == 0)
|
||||
{
|
||||
ESP_LOGI(TAG, "Invalid job nonce found, id=%d", rx_job_id);
|
||||
}
|
||||
|
||||
uint32_t rolled_version = GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[rx_job_id]->version;
|
||||
for (int i = 0; i < rx_midstate_index; i++) {
|
||||
for (int i = 0; i < rx_midstate_index; i++)
|
||||
{
|
||||
rolled_version = increment_bitmask(rolled_version, GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[rx_job_id]->version_mask);
|
||||
}
|
||||
|
||||
|
||||
// ASIC may return the same nonce multiple times
|
||||
// or one that was already found
|
||||
// most of the time it behavies however
|
||||
if (nonce_found == 0) {
|
||||
if (nonce_found == 0)
|
||||
{
|
||||
first_nonce = asic_result->nonce;
|
||||
nonce_found = 1;
|
||||
} else if (asic_result->nonce == first_nonce) {
|
||||
}
|
||||
else if (asic_result->nonce == first_nonce)
|
||||
{
|
||||
// stop if we've already seen this nonce
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (asic_result->nonce == prev_nonce) {
|
||||
if (asic_result->nonce == prev_nonce)
|
||||
{
|
||||
return NULL;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
prev_nonce = asic_result->nonce;
|
||||
}
|
||||
|
||||
|
||||
result.job_id = rx_job_id;
|
||||
result.nonce = asic_result->nonce;
|
||||
result.nonce = asic_result->nonce;
|
||||
result.rolled_version = rolled_version;
|
||||
|
||||
return &result;
|
||||
}
|
||||
|
||||
|
@ -5,8 +5,9 @@
|
||||
#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) {
|
||||
// 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 */
|
||||
@ -14,10 +15,11 @@ uint8_t crc5(uint8_t * data, uint8_t len) {
|
||||
uint8_t crcout[5] = {1, 1, 1, 1, 1};
|
||||
uint8_t din = 0;
|
||||
|
||||
len *= 8;
|
||||
len *= 8;
|
||||
|
||||
/* push data bits */
|
||||
for (j = 0x80, k = 0, i = 0; i < len; i++) {
|
||||
for (j = 0x80, k = 0, i = 0; i < len; i++)
|
||||
{
|
||||
/* input bit */
|
||||
din = (data[index] & j) != 0;
|
||||
/* shift register */
|
||||
@ -32,22 +34,27 @@ uint8_t crc5(uint8_t * data, uint8_t len) {
|
||||
if (k == 8)
|
||||
j = 0x80, k = 0, index++;
|
||||
/* apply new shift register value */
|
||||
memcpy(crcin, crcout, 5);
|
||||
//crcin = crcout[0];
|
||||
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;
|
||||
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
|
||||
// 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,
|
||||
@ -80,27 +87,28 @@ unsigned int crc16_table[256] = {
|
||||
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
|
||||
};
|
||||
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0};
|
||||
|
||||
/* CRC-16/CCITT */
|
||||
uint16_t crc16(uint8_t *buffer, uint16_t len) {
|
||||
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);
|
||||
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 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);
|
||||
while (len-- > 0)
|
||||
crc = crc16_table[((crc >> 8) ^ (*buffer++)) & 0xFF] ^ (crc << 8);
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
@ -5,22 +5,22 @@
|
||||
#include "mining.h"
|
||||
#include "common.h"
|
||||
|
||||
|
||||
|
||||
#define CRC5_MASK 0x1F
|
||||
|
||||
static const u_int64_t BM1366_FREQUENCY = CONFIG_ASIC_FREQUENCY;
|
||||
static const u_int64_t BM1366_CORE_COUNT = 672;
|
||||
static const u_int64_t BM1366_HASHRATE_S = BM1366_FREQUENCY * BM1366_CORE_COUNT * 1000000;
|
||||
//2^32
|
||||
//static const u_int64_t NONCE_SPACE = 4294967296;
|
||||
static const double BM1366_FULLSCAN_MS = 2140;
|
||||
// 2^32
|
||||
// static const u_int64_t NONCE_SPACE = 4294967296;
|
||||
static const double BM1366_FULLSCAN_MS = 2140;
|
||||
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
float frequency;
|
||||
} bm1366Module;
|
||||
|
||||
typedef struct __attribute__((__packed__)) {
|
||||
typedef struct __attribute__((__packed__))
|
||||
{
|
||||
uint8_t job_id;
|
||||
uint8_t num_midstates;
|
||||
uint8_t starting_nonce[4];
|
||||
@ -31,8 +31,6 @@ typedef struct __attribute__((__packed__)) {
|
||||
uint8_t version[4];
|
||||
} BM1366_job;
|
||||
|
||||
|
||||
|
||||
void BM1366_init(u_int64_t frequency);
|
||||
|
||||
void BM1366_send_init(void);
|
||||
@ -41,6 +39,6 @@ void BM1366_set_job_difficulty_mask(int);
|
||||
int BM1366_set_max_baud(void);
|
||||
int BM1366_set_default_baud(void);
|
||||
void BM1366_send_hash_frequency(float frequency);
|
||||
task_result * BM1366_proccess_work(void *GLOBAL_STATE);
|
||||
task_result *BM1366_proccess_work(void *GLOBAL_STATE);
|
||||
|
||||
#endif /* BM1366_H_ */
|
@ -7,29 +7,32 @@
|
||||
|
||||
#define CRC5_MASK 0x1F
|
||||
|
||||
|
||||
static const u_int64_t ASIC_FREQUENCY = CONFIG_ASIC_FREQUENCY;
|
||||
static const u_int64_t BM1397_CORE_COUNT = 672;
|
||||
static const u_int64_t BM1397_HASHRATE_S = ASIC_FREQUENCY * BM1397_CORE_COUNT * 1000000;
|
||||
//2^32
|
||||
// 2^32
|
||||
static const u_int64_t NONCE_SPACE = 4294967296;
|
||||
static const double BM1397_FULLSCAN_MS = ((double)NONCE_SPACE / (double)BM1397_HASHRATE_S) * 1000;
|
||||
static const double BM1397_FULLSCAN_MS = ((double)NONCE_SPACE / (double)BM1397_HASHRATE_S) * 1000;
|
||||
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
float frequency;
|
||||
} bm1397Module;
|
||||
|
||||
typedef enum {
|
||||
typedef enum
|
||||
{
|
||||
JOB_PACKET = 0,
|
||||
CMD_PACKET = 1,
|
||||
} packet_type_t;
|
||||
|
||||
typedef enum {
|
||||
typedef enum
|
||||
{
|
||||
JOB_RESP = 0,
|
||||
CMD_RESP = 1,
|
||||
} response_type_t;
|
||||
|
||||
typedef struct __attribute__((__packed__)) {
|
||||
typedef struct __attribute__((__packed__))
|
||||
{
|
||||
uint8_t job_id;
|
||||
uint8_t num_midstates;
|
||||
uint8_t starting_nonce[4];
|
||||
@ -42,10 +45,6 @@ typedef struct __attribute__((__packed__)) {
|
||||
uint8_t midstate3[32];
|
||||
} job_packet;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void BM1397_init(u_int64_t frequency);
|
||||
|
||||
void BM1397_send_work(void *GLOBAL_STATE, bm_job *next_bm_job);
|
||||
@ -53,6 +52,6 @@ void BM1397_set_job_difficulty_mask(int);
|
||||
int BM1397_set_max_baud(void);
|
||||
int BM1397_set_default_baud(void);
|
||||
void BM1397_send_hash_frequency(float frequency);
|
||||
task_result * BM1397_proccess_work(void *GLOBAL_STATE);
|
||||
task_result *BM1397_proccess_work(void *GLOBAL_STATE);
|
||||
|
||||
#endif /* BM1397_H_ */
|
@ -1,29 +1,34 @@
|
||||
#ifndef COMMON_H_
|
||||
#define COMMON_H_
|
||||
|
||||
typedef struct __attribute__((__packed__)) {
|
||||
typedef struct __attribute__((__packed__))
|
||||
{
|
||||
uint8_t job_id;
|
||||
uint32_t nonce;
|
||||
uint32_t rolled_version;
|
||||
} task_result;
|
||||
|
||||
static unsigned char _reverse_bits(unsigned char num) {
|
||||
static unsigned char _reverse_bits(unsigned char num)
|
||||
{
|
||||
unsigned char reversed = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
reversed <<= 1; // Left shift the reversed variable by 1
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
reversed <<= 1; // Left shift the reversed variable by 1
|
||||
reversed |= num & 1; // Use bitwise OR to set the rightmost bit of reversed to the current bit of num
|
||||
num >>= 1; // Right shift num by 1 to get the next bit
|
||||
num >>= 1; // Right shift num by 1 to get the next bit
|
||||
}
|
||||
|
||||
return reversed;
|
||||
}
|
||||
|
||||
static int _largest_power_of_two(int num) {
|
||||
static int _largest_power_of_two(int num)
|
||||
{
|
||||
int power = 0;
|
||||
|
||||
while (num > 1) {
|
||||
while (num > 1)
|
||||
{
|
||||
num = num >> 1;
|
||||
power++;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef CRC_H_
|
||||
#define CRC_H_
|
||||
|
||||
uint8_t crc5(uint8_t * data, uint8_t len);
|
||||
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);
|
||||
|
||||
|
@ -13,15 +13,16 @@
|
||||
#include "serial.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define ECHO_TEST_TXD (17)
|
||||
#define ECHO_TEST_RXD (18)
|
||||
#define BUF_SIZE (1024)
|
||||
#define ECHO_TEST_TXD (17)
|
||||
#define ECHO_TEST_RXD (18)
|
||||
#define BUF_SIZE (1024)
|
||||
|
||||
static const char *TAG = "serial";
|
||||
|
||||
void SERIAL_init(void) {
|
||||
void SERIAL_init(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Initializing serial");
|
||||
//Configure UART1 parameters
|
||||
// Configure UART1 parameters
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = 115200,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
@ -30,37 +31,41 @@ void SERIAL_init(void) {
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.rx_flow_ctrl_thresh = 122,
|
||||
};
|
||||
//Configure UART1 parameters
|
||||
// Configure UART1 parameters
|
||||
uart_param_config(UART_NUM_1, &uart_config);
|
||||
//Set UART1 pins(TX: IO17, RX: I018)
|
||||
// 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)
|
||||
//tx buffer 0 so the tx time doesn't overlap with the job wait time
|
||||
// by returning before the job is written
|
||||
// Install UART driver (we don't need an event queue here)
|
||||
// tx buffer 0 so the tx time doesn't overlap with the job wait time
|
||||
// by returning before the job is written
|
||||
uart_driver_install(UART_NUM_1, BUF_SIZE * 2, BUF_SIZE * 2, 0, NULL, 0);
|
||||
}
|
||||
|
||||
void SERIAL_set_baud(int baud){
|
||||
void SERIAL_set_baud(int baud)
|
||||
{
|
||||
ESP_LOGI(TAG, "Changing UART baud to %i", baud);
|
||||
uart_set_baudrate(UART_NUM_1, baud);
|
||||
}
|
||||
|
||||
int SERIAL_send(uint8_t *data, int len, bool debug) {
|
||||
if (debug) {
|
||||
int SERIAL_send(uint8_t *data, int len, bool debug)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
printf("->");
|
||||
prettyHex((unsigned char*)data, len);
|
||||
prettyHex((unsigned char *)data, len);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return uart_write_bytes(UART_NUM_1, (const char *) data, len);
|
||||
return uart_write_bytes(UART_NUM_1, (const char *)data, len);
|
||||
}
|
||||
|
||||
/// @brief waits for a serial response from the device
|
||||
/// @param buf buffer to read data into
|
||||
/// @param buf number of ms to wait before timing out
|
||||
/// @return number of bytes read, or -1 on error
|
||||
int16_t SERIAL_rx(uint8_t * buf, uint16_t size, uint16_t timeout_ms) {
|
||||
int16_t SERIAL_rx(uint8_t *buf, uint16_t size, uint16_t timeout_ms)
|
||||
{
|
||||
int16_t bytes_read = uart_read_bytes(UART_NUM_1, buf, size, timeout_ms / portTICK_PERIOD_MS);
|
||||
// if (bytes_read > 0) {
|
||||
// printf("rx: ");
|
||||
@ -70,20 +75,22 @@ int16_t SERIAL_rx(uint8_t * buf, uint16_t size, uint16_t timeout_ms) {
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
void SERIAL_debug_rx(void) {
|
||||
void SERIAL_debug_rx(void)
|
||||
{
|
||||
int ret;
|
||||
uint8_t buf[CHUNK_SIZE];
|
||||
|
||||
ret = SERIAL_rx(buf, 100, 20);
|
||||
if (ret < 0) {
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "unable to read data\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memset(buf, 0, 1024);
|
||||
|
||||
}
|
||||
|
||||
void SERIAL_clear_buffer(void) {
|
||||
void SERIAL_clear_buffer(void)
|
||||
{
|
||||
uart_flush(UART_NUM_1);
|
||||
}
|
||||
|
@ -18,23 +18,158 @@ TEST_CASE("Check known working midstate + job command", "[bm1397]")
|
||||
|
||||
// read back response
|
||||
SERIAL_debug_rx();
|
||||
|
||||
}
|
||||
|
||||
uint8_t work1[146] = {
|
||||
0x18, // job id
|
||||
0x04, // number of midstates
|
||||
0x9B, 0x04, 0x4C, 0x0A, // starting nonce
|
||||
0x3A, 0xAE, 0x05, 0x17, // nbits
|
||||
0xA0, 0x84, 0x73, 0x64, // ntime
|
||||
0x50, 0xE3, 0x71, 0x61, // merkle 4
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x7E, 0x02, 0x70, 0x35, 0xB1, 0xAC, 0xBA, 0xF2, 0x3E, 0xA0, 0x1A, 0x52, 0x73, 0x44, 0xFA, 0xF7, 0x6A, 0xB4, 0x76, 0xD3, 0x28, 0x21, 0x61, 0x18, 0xB7, 0x76, 0x0F, 0x7B, 0x1B, 0x22, 0xD2, 0x29,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x9B,
|
||||
0x04,
|
||||
0x4C,
|
||||
0x0A, // starting nonce
|
||||
0x3A,
|
||||
0xAE,
|
||||
0x05,
|
||||
0x17, // nbits
|
||||
0xA0,
|
||||
0x84,
|
||||
0x73,
|
||||
0x64, // ntime
|
||||
0x50,
|
||||
0xE3,
|
||||
0x71,
|
||||
0x61, // merkle 4
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x7E,
|
||||
0x02,
|
||||
0x70,
|
||||
0x35,
|
||||
0xB1,
|
||||
0xAC,
|
||||
0xBA,
|
||||
0xF2,
|
||||
0x3E,
|
||||
0xA0,
|
||||
0x1A,
|
||||
0x52,
|
||||
0x73,
|
||||
0x44,
|
||||
0xFA,
|
||||
0xF7,
|
||||
0x6A,
|
||||
0xB4,
|
||||
0x76,
|
||||
0xD3,
|
||||
0x28,
|
||||
0x21,
|
||||
0x61,
|
||||
0x18,
|
||||
0xB7,
|
||||
0x76,
|
||||
0x0F,
|
||||
0x7B,
|
||||
0x1B,
|
||||
0x22,
|
||||
0xD2,
|
||||
0x29,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
};
|
||||
job_packet test_job;
|
||||
memcpy((uint8_t *) &test_job, work1, 146);
|
||||
memcpy((uint8_t *)&test_job, work1, 146);
|
||||
|
||||
uint8_t buf[1024];
|
||||
memset(buf, 0, 1024);
|
||||
@ -44,14 +179,16 @@ TEST_CASE("Check known working midstate + job command", "[bm1397]")
|
||||
TEST_ASSERT_GREATER_OR_EQUAL_UINT16(sizeof(struct asic_result), received);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < received - 1; i++) {
|
||||
if (buf[i] == 0xAA && buf[i + 1] == 0x55) {
|
||||
for (i = 0; i < received - 1; i++)
|
||||
{
|
||||
if (buf[i] == 0xAA && buf[i + 1] == 0x55)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct asic_result nonce;
|
||||
memcpy((void *) &nonce, buf + i, sizeof(struct asic_result));
|
||||
memcpy((void *)&nonce, buf + i, sizeof(struct asic_result));
|
||||
// expected nonce 9B 04 4C 0A
|
||||
TEST_ASSERT_EQUAL_UINT32(0x0a4c049b, nonce.nonce);
|
||||
TEST_ASSERT_EQUAL_UINT8(0x18, nonce.job_id & 0xfc);
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include "connect.h"
|
||||
#include "main.h"
|
||||
|
||||
|
||||
#if CONFIG_ESP_WPA3_SAE_PWE_HUNT_AND_PECK
|
||||
#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_HUNT_AND_PECK
|
||||
#define EXAMPLE_H2E_IDENTIFIER ""
|
||||
@ -54,34 +53,41 @@ static const char *TAG = "wifi station";
|
||||
|
||||
static int s_retry_num = 0;
|
||||
|
||||
|
||||
static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) {
|
||||
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
|
||||
static void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
|
||||
{
|
||||
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START)
|
||||
{
|
||||
esp_wifi_connect();
|
||||
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||
}
|
||||
else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
|
||||
{
|
||||
|
||||
// Wait a little
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
|
||||
if (s_retry_num < WIFI_MAXIMUM_RETRY) {
|
||||
if (s_retry_num < WIFI_MAXIMUM_RETRY)
|
||||
{
|
||||
esp_wifi_connect();
|
||||
s_retry_num++;
|
||||
ESP_LOGI(TAG, "retry to connect to the AP");
|
||||
MINER_set_wifi_status(WIFI_RETRYING, s_retry_num);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
|
||||
ESP_LOGI(TAG,"connect to the AP fail");
|
||||
ESP_LOGI(TAG, "connect to the AP fail");
|
||||
MINER_set_wifi_status(WIFI_CONNECT_FAILED, 0);
|
||||
}
|
||||
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
||||
ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
|
||||
}
|
||||
else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
|
||||
{
|
||||
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
|
||||
ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
|
||||
s_retry_num = 0;
|
||||
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
esp_netif_t *wifi_init_softap(void)
|
||||
{
|
||||
esp_netif_t *esp_netif_ap = esp_netif_create_default_wifi_ap();
|
||||
@ -104,26 +110,31 @@ esp_netif_t *wifi_init_softap(void)
|
||||
return esp_netif_ap;
|
||||
}
|
||||
|
||||
void toggle_wifi_softap(void){
|
||||
void toggle_wifi_softap(void)
|
||||
{
|
||||
wifi_mode_t mode = WIFI_MODE_NULL;
|
||||
ESP_ERROR_CHECK(esp_wifi_get_mode(&mode));
|
||||
|
||||
if (mode == WIFI_MODE_APSTA) {
|
||||
if (mode == WIFI_MODE_APSTA)
|
||||
{
|
||||
ESP_LOGI(TAG, "ESP_WIFI Access Point Off");
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(TAG, "ESP_WIFI Access Point On");
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_APSTA));
|
||||
}
|
||||
}
|
||||
|
||||
void wifi_softap_off(void){
|
||||
void wifi_softap_off(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "ESP_WIFI Access Point Off");
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||
}
|
||||
|
||||
/* Initialize wifi station */
|
||||
esp_netif_t *wifi_init_sta(const char * wifi_ssid, const char * wifi_pass)
|
||||
esp_netif_t *wifi_init_sta(const char *wifi_ssid, const char *wifi_pass)
|
||||
{
|
||||
esp_netif_t *esp_netif_sta = esp_netif_create_default_wifi_sta();
|
||||
|
||||
@ -139,22 +150,20 @@ esp_netif_t *wifi_init_sta(const char * wifi_ssid, const char * wifi_pass)
|
||||
// .sae_h2e_identifier = EXAMPLE_H2E_IDENTIFIER,
|
||||
},
|
||||
};
|
||||
strncpy((char *) wifi_sta_config.sta.ssid, wifi_ssid, 31);
|
||||
strncpy((char *)wifi_sta_config.sta.ssid, wifi_ssid, 31);
|
||||
wifi_sta_config.sta.ssid[31] = '\0';
|
||||
strncpy((char *) wifi_sta_config.sta.password, wifi_pass, 63);
|
||||
strncpy((char *)wifi_sta_config.sta.password, wifi_pass, 63);
|
||||
wifi_sta_config.sta.password[63] = '\0';
|
||||
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_sta_config) );
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_sta_config));
|
||||
|
||||
ESP_LOGI(TAG, "wifi_init_sta finished.");
|
||||
|
||||
return esp_netif_sta;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void wifi_init(const char * wifi_ssid, const char * wifi_pass) {
|
||||
void wifi_init(const char *wifi_ssid, const char *wifi_pass)
|
||||
{
|
||||
s_wifi_event_group = xEventGroupCreate();
|
||||
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
@ -171,7 +180,7 @@ esp_netif_t *wifi_init_sta(const char * wifi_ssid, const char * wifi_pass)
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_APSTA));
|
||||
|
||||
/* Initialize AP */
|
||||
/* Initialize AP */
|
||||
ESP_LOGI(TAG, "ESP_WIFI Access Point On");
|
||||
esp_netif_t *esp_netif_ap = wifi_init_softap();
|
||||
|
||||
@ -180,21 +189,22 @@ esp_netif_t *wifi_init_sta(const char * wifi_ssid, const char * wifi_pass)
|
||||
esp_netif_t *esp_netif_sta = wifi_init_sta(wifi_ssid, wifi_pass);
|
||||
|
||||
/* Start WiFi */
|
||||
ESP_ERROR_CHECK(esp_wifi_start() );
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
|
||||
ESP_LOGI(TAG, "wifi_init_sta finished.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
EventBits_t wifi_connect(void){
|
||||
/* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
|
||||
EventBits_t wifi_connect(void)
|
||||
{
|
||||
/* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
|
||||
* number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
|
||||
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
|
||||
WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
|
||||
pdFALSE,
|
||||
pdFALSE,
|
||||
portMAX_DELAY);
|
||||
WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
|
||||
pdFALSE,
|
||||
pdFALSE,
|
||||
portMAX_DELAY);
|
||||
|
||||
/* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
|
||||
* happened. */
|
||||
|
@ -6,19 +6,20 @@
|
||||
|
||||
#include "freertos/event_groups.h"
|
||||
|
||||
#define WIFI_SSID CONFIG_ESP_WIFI_SSID
|
||||
#define WIFI_PASS CONFIG_ESP_WIFI_PASSWORD
|
||||
#define WIFI_SSID CONFIG_ESP_WIFI_SSID
|
||||
#define WIFI_PASS CONFIG_ESP_WIFI_PASSWORD
|
||||
|
||||
#define WIFI_MAXIMUM_RETRY CONFIG_ESP_MAXIMUM_RETRY
|
||||
#define WIFI_MAXIMUM_RETRY CONFIG_ESP_MAXIMUM_RETRY
|
||||
|
||||
/* The event group allows multiple bits for each event, but we only care about two events:
|
||||
* - we are connected to the AP with an IP
|
||||
* - we failed to connect after the maximum amount of retries */
|
||||
#define WIFI_CONNECTED_BIT BIT0
|
||||
#define WIFI_FAIL_BIT BIT1
|
||||
#define WIFI_FAIL_BIT BIT1
|
||||
|
||||
//enum of wifi statuses
|
||||
typedef enum {
|
||||
// enum of wifi statuses
|
||||
typedef enum
|
||||
{
|
||||
WIFI_CONNECTED,
|
||||
WIFI_DISCONNECTED,
|
||||
WIFI_CONNECTING,
|
||||
@ -29,5 +30,5 @@ typedef enum {
|
||||
|
||||
void toggle_wifi_softap(void);
|
||||
void wifi_softap_off(void);
|
||||
void wifi_init(const char * wifi_ssid, const char * wifi_pass);
|
||||
void wifi_init(const char *wifi_ssid, const char *wifi_pass);
|
||||
EventBits_t wifi_connect(void);
|
||||
|
@ -3,8 +3,8 @@
|
||||
|
||||
#include "stratum_api.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
uint32_t version;
|
||||
uint32_t version_mask;
|
||||
uint8_t prev_block_hash[32];
|
||||
@ -21,22 +21,22 @@ typedef struct {
|
||||
uint8_t midstate2[32];
|
||||
uint8_t midstate3[32];
|
||||
uint32_t pool_diff;
|
||||
char * jobid;
|
||||
char * extranonce2;
|
||||
char *jobid;
|
||||
char *extranonce2;
|
||||
} bm_job;
|
||||
|
||||
void free_bm_job(bm_job * job);
|
||||
void free_bm_job(bm_job *job);
|
||||
|
||||
char * construct_coinbase_tx(const char * coinbase_1, const char * coinbase_2,
|
||||
const char * extranonce, const char * extranonce_2);
|
||||
char *construct_coinbase_tx(const char *coinbase_1, const char *coinbase_2,
|
||||
const char *extranonce, const char *extranonce_2);
|
||||
|
||||
char * calculate_merkle_root_hash(const char * coinbase_tx, const uint8_t merkle_branches[][32], const int num_merkle_branches);
|
||||
char *calculate_merkle_root_hash(const char *coinbase_tx, const uint8_t merkle_branches[][32], const int num_merkle_branches);
|
||||
|
||||
bm_job construct_bm_job(mining_notify * params, const char * merkle_root, const uint32_t version_mask);
|
||||
bm_job construct_bm_job(mining_notify *params, const char *merkle_root, const uint32_t version_mask);
|
||||
|
||||
double test_nonce_value(const bm_job * job, const uint32_t nonce, const uint32_t rolled_version);
|
||||
double test_nonce_value(const bm_job *job, const uint32_t nonce, const uint32_t rolled_version);
|
||||
|
||||
char * extranonce_2_generate(uint32_t extranonce_2, uint32_t length);
|
||||
char *extranonce_2_generate(uint32_t extranonce_2, uint32_t length);
|
||||
|
||||
uint32_t increment_bitmask(const uint32_t value, const uint32_t mask);
|
||||
|
||||
|
@ -10,8 +10,8 @@
|
||||
#define COINBASE_SIZE 100
|
||||
#define COINBASE2_SIZE 128
|
||||
|
||||
|
||||
typedef enum {
|
||||
typedef enum
|
||||
{
|
||||
STRATUM_UNKNOWN,
|
||||
MINING_NOTIFY,
|
||||
MINING_SET_DIFFICULTY,
|
||||
@ -20,12 +20,13 @@ typedef enum {
|
||||
STRATUM_RESULT_VERSION_MASK
|
||||
} stratum_method;
|
||||
|
||||
typedef struct {
|
||||
char * job_id;
|
||||
char * prev_block_hash;
|
||||
char * coinbase_1;
|
||||
char * coinbase_2;
|
||||
uint8_t * merkle_branches;
|
||||
typedef struct
|
||||
{
|
||||
char *job_id;
|
||||
char *prev_block_hash;
|
||||
char *coinbase_1;
|
||||
char *coinbase_2;
|
||||
uint8_t *merkle_branches;
|
||||
size_t n_merkle_branches;
|
||||
uint32_t version;
|
||||
uint32_t version_mask;
|
||||
@ -34,45 +35,42 @@ typedef struct {
|
||||
uint32_t difficulty;
|
||||
} mining_notify;
|
||||
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
|
||||
int16_t message_id;
|
||||
//Indicates the type of request the message represents.
|
||||
// Indicates the type of request the message represents.
|
||||
stratum_method method;
|
||||
|
||||
//mining.notify
|
||||
// mining.notify
|
||||
int should_abandon_work;
|
||||
mining_notify * mining_notification;
|
||||
//mining.set_difficulty
|
||||
mining_notify *mining_notification;
|
||||
// mining.set_difficulty
|
||||
uint32_t new_difficulty;
|
||||
//mining.set_version_mask
|
||||
// mining.set_version_mask
|
||||
uint32_t version_mask;
|
||||
//result
|
||||
// result
|
||||
bool response_success;
|
||||
} StratumApiV1Message;
|
||||
|
||||
|
||||
void STRATUM_V1_initialize_buffer();
|
||||
|
||||
char * STRATUM_V1_receive_jsonrpc_line(int sockfd);
|
||||
char *STRATUM_V1_receive_jsonrpc_line(int sockfd);
|
||||
|
||||
int STRATUM_V1_subscribe(int socket, char ** extranonce, int * extranonce2_len);
|
||||
int STRATUM_V1_subscribe(int socket, char **extranonce, int *extranonce2_len);
|
||||
|
||||
void STRATUM_V1_parse(StratumApiV1Message* message, const char * stratum_json);
|
||||
void STRATUM_V1_parse(StratumApiV1Message *message, const char *stratum_json);
|
||||
|
||||
void STRATUM_V1_free_mining_notify(mining_notify *params);
|
||||
|
||||
void STRATUM_V1_free_mining_notify(mining_notify * params);
|
||||
|
||||
|
||||
int STRATUM_V1_authenticate(int socket, const char * username);
|
||||
int STRATUM_V1_authenticate(int socket, const char *username);
|
||||
|
||||
void STRATUM_V1_configure_version_rolling(int socket);
|
||||
|
||||
int STRATUM_V1_suggest_difficulty(int socket, uint32_t difficulty);
|
||||
|
||||
void STRATUM_V1_submit_share(int socket, const char * username, const char * jobid,
|
||||
const char * extranonce_2, const uint32_t ntime, const uint32_t nonce,
|
||||
void STRATUM_V1_submit_share(int socket, const char *username, const char *jobid,
|
||||
const char *extranonce_2, const uint32_t ntime, const uint32_t nonce,
|
||||
const uint32_t version);
|
||||
|
||||
|
||||
#endif // STRATUM_API_H
|
@ -4,33 +4,33 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
int hex2char(uint8_t x, char * c);
|
||||
int hex2char(uint8_t x, char *c);
|
||||
|
||||
size_t bin2hex(const uint8_t * buf, size_t buflen, char * hex, size_t hexlen);
|
||||
size_t bin2hex(const uint8_t *buf, size_t buflen, char *hex, size_t hexlen);
|
||||
|
||||
uint8_t hex2val(char c);
|
||||
void flip80bytes(void *dest_p, const void *src_p);
|
||||
void flip32bytes(void *dest_p, const void *src_p);
|
||||
|
||||
size_t hex2bin(const char * hex, uint8_t * bin, size_t bin_len);
|
||||
size_t hex2bin(const char *hex, uint8_t *bin, size_t bin_len);
|
||||
|
||||
void print_hex(const uint8_t * b, size_t len,
|
||||
const size_t in_line, const char * prefix);
|
||||
void print_hex(const uint8_t *b, size_t len,
|
||||
const size_t in_line, const char *prefix);
|
||||
|
||||
char * double_sha256(const char * hex_string);
|
||||
char *double_sha256(const char *hex_string);
|
||||
|
||||
uint8_t * double_sha256_bin(const uint8_t * data, const size_t data_len);
|
||||
uint8_t *double_sha256_bin(const uint8_t *data, const size_t data_len);
|
||||
|
||||
void single_sha256_bin(const uint8_t * data, const size_t data_len, uint8_t * dest);
|
||||
void midstate_sha256_bin( const uint8_t * data, const size_t data_len, uint8_t * dest);
|
||||
void single_sha256_bin(const uint8_t *data, const size_t data_len, uint8_t *dest);
|
||||
void midstate_sha256_bin(const uint8_t *data, const size_t data_len, uint8_t *dest);
|
||||
|
||||
void swap_endian_words(const char * hex, uint8_t * output);
|
||||
void swap_endian_words(const char *hex, uint8_t *output);
|
||||
|
||||
void reverse_bytes(uint8_t * data, size_t len);
|
||||
void reverse_bytes(uint8_t *data, size_t len);
|
||||
|
||||
double le256todouble(const void *target);
|
||||
|
||||
void prettyHex(unsigned char * buf, int len);
|
||||
void prettyHex(unsigned char *buf, int len);
|
||||
|
||||
uint32_t flip32(uint32_t val);
|
||||
|
||||
|
@ -5,20 +5,19 @@
|
||||
#include "utils.h"
|
||||
#include "mbedtls/sha256.h"
|
||||
|
||||
void free_bm_job(bm_job * job)
|
||||
void free_bm_job(bm_job *job)
|
||||
{
|
||||
free(job->jobid);
|
||||
free(job->extranonce2);
|
||||
free(job);
|
||||
}
|
||||
|
||||
char * construct_coinbase_tx(const char * coinbase_1, const char * coinbase_2,
|
||||
const char * extranonce, const char * extranonce_2)
|
||||
char *construct_coinbase_tx(const char *coinbase_1, const char *coinbase_2,
|
||||
const char *extranonce, const char *extranonce_2)
|
||||
{
|
||||
int coinbase_tx_len = strlen(coinbase_1) + strlen(coinbase_2)
|
||||
+ strlen(extranonce) + strlen(extranonce_2) + 1;
|
||||
int coinbase_tx_len = strlen(coinbase_1) + strlen(coinbase_2) + strlen(extranonce) + strlen(extranonce_2) + 1;
|
||||
|
||||
char * coinbase_tx = malloc(coinbase_tx_len);
|
||||
char *coinbase_tx = malloc(coinbase_tx_len);
|
||||
strcpy(coinbase_tx, coinbase_1);
|
||||
strcat(coinbase_tx, extranonce);
|
||||
strcat(coinbase_tx, extranonce_2);
|
||||
@ -28,32 +27,33 @@ char * construct_coinbase_tx(const char * coinbase_1, const char * coinbase_2,
|
||||
return coinbase_tx;
|
||||
}
|
||||
|
||||
char * calculate_merkle_root_hash(const char * coinbase_tx, const uint8_t merkle_branches[][32], const int num_merkle_branches)
|
||||
char *calculate_merkle_root_hash(const char *coinbase_tx, const uint8_t merkle_branches[][32], const int num_merkle_branches)
|
||||
{
|
||||
size_t coinbase_tx_bin_len = strlen(coinbase_tx) / 2;
|
||||
uint8_t * coinbase_tx_bin = malloc(coinbase_tx_bin_len);
|
||||
uint8_t *coinbase_tx_bin = malloc(coinbase_tx_bin_len);
|
||||
hex2bin(coinbase_tx, coinbase_tx_bin, coinbase_tx_bin_len);
|
||||
|
||||
uint8_t both_merkles[64];
|
||||
uint8_t * new_root = double_sha256_bin(coinbase_tx_bin, coinbase_tx_bin_len);
|
||||
uint8_t *new_root = double_sha256_bin(coinbase_tx_bin, coinbase_tx_bin_len);
|
||||
free(coinbase_tx_bin);
|
||||
memcpy(both_merkles, new_root, 32);
|
||||
free(new_root);
|
||||
for (int i = 0; i < num_merkle_branches; i++)
|
||||
{
|
||||
memcpy(both_merkles + 32, merkle_branches[i], 32);
|
||||
uint8_t * new_root = double_sha256_bin(both_merkles, 64);
|
||||
uint8_t *new_root = double_sha256_bin(both_merkles, 64);
|
||||
memcpy(both_merkles, new_root, 32);
|
||||
free(new_root);
|
||||
}
|
||||
|
||||
char * merkle_root_hash = malloc(65);
|
||||
char *merkle_root_hash = malloc(65);
|
||||
bin2hex(both_merkles, 32, merkle_root_hash, 65);
|
||||
return merkle_root_hash;
|
||||
}
|
||||
|
||||
//take a mining_notify struct with ascii hex strings and convert it to a bm_job struct
|
||||
bm_job construct_bm_job(mining_notify * params, const char * merkle_root, const uint32_t version_mask) {
|
||||
// take a mining_notify struct with ascii hex strings and convert it to a bm_job struct
|
||||
bm_job construct_bm_job(mining_notify *params, const char *merkle_root, const uint32_t version_mask)
|
||||
{
|
||||
bm_job new_job;
|
||||
|
||||
new_job.version = params->version;
|
||||
@ -64,7 +64,7 @@ bm_job construct_bm_job(mining_notify * params, const char * merkle_root, const
|
||||
|
||||
hex2bin(merkle_root, new_job.merkle_root, 32);
|
||||
|
||||
//hex2bin(merkle_root, new_job.merkle_root_be, 32);
|
||||
// hex2bin(merkle_root, new_job.merkle_root_be, 32);
|
||||
swap_endian_words(merkle_root, new_job.merkle_root_be);
|
||||
reverse_bytes(new_job.merkle_root_be, 32);
|
||||
|
||||
@ -76,15 +76,16 @@ bm_job construct_bm_job(mining_notify * params, const char * merkle_root, const
|
||||
////make the midstate hash
|
||||
uint8_t midstate_data[64];
|
||||
|
||||
//copy 68 bytes header data into midstate (and deal with endianess)
|
||||
memcpy(midstate_data, &new_job.version, 4); //copy version
|
||||
memcpy(midstate_data + 4, new_job.prev_block_hash, 32); //copy prev_block_hash
|
||||
memcpy(midstate_data + 36, new_job.merkle_root, 28); //copy merkle_root
|
||||
// copy 68 bytes header data into midstate (and deal with endianess)
|
||||
memcpy(midstate_data, &new_job.version, 4); // copy version
|
||||
memcpy(midstate_data + 4, new_job.prev_block_hash, 32); // copy prev_block_hash
|
||||
memcpy(midstate_data + 36, new_job.merkle_root, 28); // copy merkle_root
|
||||
|
||||
midstate_sha256_bin(midstate_data, 64, new_job.midstate); //make the midstate hash
|
||||
reverse_bytes(new_job.midstate, 32); //reverse the midstate bytes for the BM job packet
|
||||
midstate_sha256_bin(midstate_data, 64, new_job.midstate); // make the midstate hash
|
||||
reverse_bytes(new_job.midstate, 32); // reverse the midstate bytes for the BM job packet
|
||||
|
||||
if (version_mask != 0) {
|
||||
if (version_mask != 0)
|
||||
{
|
||||
uint32_t rolled_version = increment_bitmask(new_job.version, version_mask);
|
||||
memcpy(midstate_data, &rolled_version, 4);
|
||||
midstate_sha256_bin(midstate_data, 64, new_job.midstate1);
|
||||
@ -100,20 +101,23 @@ bm_job construct_bm_job(mining_notify * params, const char * merkle_root, const
|
||||
midstate_sha256_bin(midstate_data, 64, new_job.midstate3);
|
||||
reverse_bytes(new_job.midstate3, 32);
|
||||
new_job.num_midstates = 4;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
new_job.num_midstates = 1;
|
||||
}
|
||||
|
||||
return new_job;
|
||||
}
|
||||
|
||||
char * extranonce_2_generate(uint32_t extranonce_2, uint32_t length)
|
||||
char *extranonce_2_generate(uint32_t extranonce_2, uint32_t length)
|
||||
{
|
||||
char * extranonce_2_str = malloc(length * 2 + 1);
|
||||
char *extranonce_2_str = malloc(length * 2 + 1);
|
||||
memset(extranonce_2_str, '0', length * 2);
|
||||
extranonce_2_str[length * 2] = '\0';
|
||||
bin2hex((uint8_t *) &extranonce_2, sizeof(extranonce_2), extranonce_2_str, length * 2 + 1);
|
||||
if (length > 4) {
|
||||
bin2hex((uint8_t *)&extranonce_2, sizeof(extranonce_2), extranonce_2_str, length * 2 + 1);
|
||||
if (length > 4)
|
||||
{
|
||||
extranonce_2_str[8] = '0';
|
||||
}
|
||||
return extranonce_2_str;
|
||||
@ -121,12 +125,13 @@ char * extranonce_2_generate(uint32_t extranonce_2, uint32_t length)
|
||||
|
||||
///////cgminer nonce testing
|
||||
/* truediffone == 0x00000000FFFF0000000000000000000000000000000000000000000000000000
|
||||
*/
|
||||
*/
|
||||
static const double truediffone = 26959535291011309493156476344723991336010898738574164086137773096960.0;
|
||||
|
||||
/* testing a nonce and return the diff - 0 means invalid */
|
||||
double test_nonce_value(const bm_job * job, const uint32_t nonce, const uint32_t rolled_version) {
|
||||
double d64, s64, ds;
|
||||
double test_nonce_value(const bm_job *job, const uint32_t nonce, const uint32_t rolled_version)
|
||||
{
|
||||
double d64, s64, ds;
|
||||
unsigned char header[80];
|
||||
|
||||
// // TODO: use the midstate hash instead of hashing the whole header
|
||||
@ -143,31 +148,34 @@ double test_nonce_value(const bm_job * job, const uint32_t nonce, const uint32_t
|
||||
memcpy(header + 72, &job->target, 4);
|
||||
memcpy(header + 76, &nonce, 4);
|
||||
|
||||
unsigned char hash_buffer[32];
|
||||
unsigned char hash_buffer[32];
|
||||
unsigned char hash_result[32];
|
||||
|
||||
//double hash the header
|
||||
mbedtls_sha256(header, 80, hash_buffer, 0);
|
||||
mbedtls_sha256(hash_buffer, 32, hash_result, 0);
|
||||
// double hash the header
|
||||
mbedtls_sha256(header, 80, hash_buffer, 0);
|
||||
mbedtls_sha256(hash_buffer, 32, hash_result, 0);
|
||||
|
||||
d64 = truediffone;
|
||||
s64 = le256todouble(hash_result);
|
||||
ds = d64 / s64;
|
||||
d64 = truediffone;
|
||||
s64 = le256todouble(hash_result);
|
||||
ds = d64 / s64;
|
||||
|
||||
return ds;
|
||||
return ds;
|
||||
}
|
||||
|
||||
uint32_t increment_bitmask(const uint32_t value, const uint32_t mask) {
|
||||
uint32_t increment_bitmask(const uint32_t value, const uint32_t mask)
|
||||
{
|
||||
// if mask is zero, just return the original value
|
||||
if (mask == 0) return value;
|
||||
if (mask == 0)
|
||||
return value;
|
||||
|
||||
uint32_t carry = (value & mask) + (mask & -mask); // increment the least significant bit of the mask
|
||||
uint32_t overflow = carry & ~mask; // find overflowed bits that are not in the mask
|
||||
uint32_t carry = (value & mask) + (mask & -mask); // increment the least significant bit of the mask
|
||||
uint32_t overflow = carry & ~mask; // find overflowed bits that are not in the mask
|
||||
uint32_t new_value = (value & ~mask) | (carry & mask); // set bits according to the mask
|
||||
|
||||
// Handle carry propagation
|
||||
if (overflow > 0) {
|
||||
uint32_t carry_mask = (overflow << 1); // shift left to get the mask where carry should be propagated
|
||||
if (overflow > 0)
|
||||
{
|
||||
uint32_t carry_mask = (overflow << 1); // shift left to get the mask where carry should be propagated
|
||||
new_value = increment_bitmask(new_value, carry_mask); // recursively handle carry propagation
|
||||
}
|
||||
|
||||
|
@ -12,14 +12,13 @@
|
||||
#include "lwip/sockets.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
#define BUFFER_SIZE 1024
|
||||
static const char *TAG = "stratum_api";
|
||||
|
||||
static char *json_rpc_buffer = NULL;
|
||||
static size_t json_rpc_buffer_size = 0;
|
||||
|
||||
// A message ID that must be unique per request that expects a response.
|
||||
// A message ID that must be unique per request that expects a response.
|
||||
// For requests not expecting a response (called notifications), this is null.
|
||||
static int send_uid = 1;
|
||||
|
||||
@ -55,7 +54,7 @@ static void realloc_json_buffer(size_t len)
|
||||
}
|
||||
|
||||
new = new + (BUFFER_SIZE - (new % BUFFER_SIZE));
|
||||
void * new_sockbuf = realloc(json_rpc_buffer, new);
|
||||
void *new_sockbuf = realloc(json_rpc_buffer, new);
|
||||
|
||||
if (new_sockbuf == NULL)
|
||||
{
|
||||
@ -68,9 +67,10 @@ static void realloc_json_buffer(size_t len)
|
||||
json_rpc_buffer_size = new;
|
||||
}
|
||||
|
||||
char * STRATUM_V1_receive_jsonrpc_line(int sockfd)
|
||||
char *STRATUM_V1_receive_jsonrpc_line(int sockfd)
|
||||
{
|
||||
if (json_rpc_buffer == NULL) {
|
||||
if (json_rpc_buffer == NULL)
|
||||
{
|
||||
STRATUM_V1_initialize_buffer();
|
||||
}
|
||||
char *line, *tok = NULL;
|
||||
@ -105,45 +105,57 @@ char * STRATUM_V1_receive_jsonrpc_line(int sockfd)
|
||||
return line;
|
||||
}
|
||||
|
||||
|
||||
void STRATUM_V1_parse(StratumApiV1Message* message, const char * stratum_json)
|
||||
void STRATUM_V1_parse(StratumApiV1Message *message, const char *stratum_json)
|
||||
{
|
||||
cJSON * json = cJSON_Parse(stratum_json);
|
||||
cJSON *json = cJSON_Parse(stratum_json);
|
||||
|
||||
cJSON * id_json = cJSON_GetObjectItem(json, "id");
|
||||
cJSON *id_json = cJSON_GetObjectItem(json, "id");
|
||||
int16_t parsed_id = -1;
|
||||
if (id_json != NULL && cJSON_IsNumber(id_json)) {
|
||||
if (id_json != NULL && cJSON_IsNumber(id_json))
|
||||
{
|
||||
parsed_id = id_json->valueint;
|
||||
}
|
||||
message->message_id = parsed_id;
|
||||
|
||||
|
||||
cJSON * method_json = cJSON_GetObjectItem(json, "method");
|
||||
cJSON *method_json = cJSON_GetObjectItem(json, "method");
|
||||
stratum_method result = STRATUM_UNKNOWN;
|
||||
if (method_json != NULL && cJSON_IsString(method_json)) {
|
||||
if (strcmp("mining.notify", method_json->valuestring) == 0) {
|
||||
if (method_json != NULL && cJSON_IsString(method_json))
|
||||
{
|
||||
if (strcmp("mining.notify", method_json->valuestring) == 0)
|
||||
{
|
||||
result = MINING_NOTIFY;
|
||||
} else if (strcmp("mining.set_difficulty", method_json->valuestring) == 0) {
|
||||
}
|
||||
else if (strcmp("mining.set_difficulty", method_json->valuestring) == 0)
|
||||
{
|
||||
result = MINING_SET_DIFFICULTY;
|
||||
} else if (strcmp("mining.set_version_mask", method_json->valuestring) == 0) {
|
||||
}
|
||||
else if (strcmp("mining.set_version_mask", method_json->valuestring) == 0)
|
||||
{
|
||||
result = MINING_SET_VERSION_MASK;
|
||||
}
|
||||
} else {
|
||||
//parse results
|
||||
cJSON * result_json = cJSON_GetObjectItem(json, "result");
|
||||
if (result_json != NULL && cJSON_IsBool(result_json)) {
|
||||
}
|
||||
else
|
||||
{
|
||||
// parse results
|
||||
cJSON *result_json = cJSON_GetObjectItem(json, "result");
|
||||
if (result_json != NULL && cJSON_IsBool(result_json))
|
||||
{
|
||||
|
||||
result = STRATUM_RESULT;
|
||||
|
||||
bool response_success = false;
|
||||
if (result_json != NULL && cJSON_IsTrue(result_json)) {
|
||||
if (result_json != NULL && cJSON_IsTrue(result_json))
|
||||
{
|
||||
response_success = true;
|
||||
}
|
||||
|
||||
message->response_success = response_success;
|
||||
} else {
|
||||
cJSON * mask = cJSON_GetObjectItem(result_json, "version-rolling.mask");
|
||||
if (mask != NULL) {
|
||||
}
|
||||
else
|
||||
{
|
||||
cJSON *mask = cJSON_GetObjectItem(result_json, "version-rolling.mask");
|
||||
if (mask != NULL)
|
||||
{
|
||||
result = STRATUM_RESULT_VERSION_MASK;
|
||||
message->version_mask = strtoul(mask->valuestring, NULL, 16);
|
||||
}
|
||||
@ -152,24 +164,27 @@ void STRATUM_V1_parse(StratumApiV1Message* message, const char * stratum_json)
|
||||
|
||||
message->method = result;
|
||||
|
||||
if (message->method == MINING_NOTIFY) {
|
||||
if (message->method == MINING_NOTIFY)
|
||||
{
|
||||
|
||||
mining_notify * new_work = malloc(sizeof(mining_notify));
|
||||
//new_work->difficulty = difficulty;
|
||||
cJSON * params = cJSON_GetObjectItem(json, "params");
|
||||
mining_notify *new_work = malloc(sizeof(mining_notify));
|
||||
// new_work->difficulty = difficulty;
|
||||
cJSON *params = cJSON_GetObjectItem(json, "params");
|
||||
new_work->job_id = strdup(cJSON_GetArrayItem(params, 0)->valuestring);
|
||||
new_work->prev_block_hash = strdup(cJSON_GetArrayItem(params, 1)->valuestring);
|
||||
new_work->coinbase_1 = strdup(cJSON_GetArrayItem(params, 2)->valuestring);
|
||||
new_work->coinbase_2 = strdup(cJSON_GetArrayItem(params, 3)->valuestring);
|
||||
|
||||
cJSON * merkle_branch = cJSON_GetArrayItem(params, 4);
|
||||
cJSON *merkle_branch = cJSON_GetArrayItem(params, 4);
|
||||
new_work->n_merkle_branches = cJSON_GetArraySize(merkle_branch);
|
||||
if (new_work->n_merkle_branches > MAX_MERKLE_BRANCHES) {
|
||||
if (new_work->n_merkle_branches > MAX_MERKLE_BRANCHES)
|
||||
{
|
||||
printf("Too many Merkle branches.\n");
|
||||
abort();
|
||||
}
|
||||
new_work->merkle_branches = malloc(HASH_SIZE * new_work->n_merkle_branches);
|
||||
for (size_t i = 0; i < new_work->n_merkle_branches; i++) {
|
||||
for (size_t i = 0; i < new_work->n_merkle_branches; i++)
|
||||
{
|
||||
hex2bin(cJSON_GetArrayItem(merkle_branch, i)->valuestring, new_work->merkle_branches + HASH_SIZE * i, HASH_SIZE * 2);
|
||||
}
|
||||
|
||||
@ -179,33 +194,30 @@ void STRATUM_V1_parse(StratumApiV1Message* message, const char * stratum_json)
|
||||
|
||||
message->mining_notification = new_work;
|
||||
|
||||
|
||||
// params can be varible length
|
||||
int paramsLength = cJSON_GetArraySize(params);
|
||||
int value = cJSON_IsTrue(cJSON_GetArrayItem(params, paramsLength - 1));
|
||||
message->should_abandon_work = value;
|
||||
|
||||
|
||||
}else if (message->method == MINING_SET_DIFFICULTY) {
|
||||
cJSON * params = cJSON_GetObjectItem(json, "params");
|
||||
}
|
||||
else if (message->method == MINING_SET_DIFFICULTY)
|
||||
{
|
||||
cJSON *params = cJSON_GetObjectItem(json, "params");
|
||||
uint32_t difficulty = cJSON_GetArrayItem(params, 0)->valueint;
|
||||
|
||||
message->new_difficulty = difficulty;
|
||||
} else if (message->method == MINING_SET_VERSION_MASK) {
|
||||
}
|
||||
else if (message->method == MINING_SET_VERSION_MASK)
|
||||
{
|
||||
|
||||
cJSON * params = cJSON_GetObjectItem(json, "params");
|
||||
cJSON *params = cJSON_GetObjectItem(json, "params");
|
||||
uint32_t version_mask = strtoul(cJSON_GetArrayItem(params, 0)->valuestring, NULL, 16);
|
||||
message->version_mask = version_mask;
|
||||
|
||||
}
|
||||
|
||||
cJSON_Delete(json);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void STRATUM_V1_free_mining_notify(mining_notify * params)
|
||||
void STRATUM_V1_free_mining_notify(mining_notify *params)
|
||||
{
|
||||
free(params->job_id);
|
||||
free(params->prev_block_hash);
|
||||
@ -215,32 +227,36 @@ void STRATUM_V1_free_mining_notify(mining_notify * params)
|
||||
free(params);
|
||||
}
|
||||
|
||||
int _parse_stratum_subscribe_result_message(const char * result_json_str,
|
||||
char ** extranonce,
|
||||
int * extranonce2_len)
|
||||
int _parse_stratum_subscribe_result_message(const char *result_json_str,
|
||||
char **extranonce,
|
||||
int *extranonce2_len)
|
||||
{
|
||||
cJSON * root = cJSON_Parse(result_json_str);
|
||||
if (root == NULL) {
|
||||
ESP_LOGE(TAG, "Unable to parse %s", result_json_str);
|
||||
return -1;
|
||||
cJSON *root = cJSON_Parse(result_json_str);
|
||||
if (root == NULL)
|
||||
{
|
||||
ESP_LOGE(TAG, "Unable to parse %s", result_json_str);
|
||||
return -1;
|
||||
}
|
||||
cJSON * result = cJSON_GetObjectItem(root, "result");
|
||||
if (result == NULL) {
|
||||
ESP_LOGE(TAG, "Unable to parse subscribe result %s", result_json_str);
|
||||
return -1;
|
||||
cJSON *result = cJSON_GetObjectItem(root, "result");
|
||||
if (result == NULL)
|
||||
{
|
||||
ESP_LOGE(TAG, "Unable to parse subscribe result %s", result_json_str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
cJSON * extranonce2_len_json = cJSON_GetArrayItem(result, 2);
|
||||
if (extranonce2_len_json == NULL) {
|
||||
ESP_LOGE(TAG, "Unable to parse extranonce2_len: %s", result->valuestring);
|
||||
return -1;
|
||||
cJSON *extranonce2_len_json = cJSON_GetArrayItem(result, 2);
|
||||
if (extranonce2_len_json == NULL)
|
||||
{
|
||||
ESP_LOGE(TAG, "Unable to parse extranonce2_len: %s", result->valuestring);
|
||||
return -1;
|
||||
}
|
||||
*extranonce2_len = extranonce2_len_json->valueint;
|
||||
|
||||
cJSON * extranonce_json = cJSON_GetArrayItem(result, 1);
|
||||
if (extranonce_json == NULL) {
|
||||
ESP_LOGE(TAG, "Unable parse extranonce: %s", result->valuestring);
|
||||
return -1;
|
||||
cJSON *extranonce_json = cJSON_GetArrayItem(result, 1);
|
||||
if (extranonce_json == NULL)
|
||||
{
|
||||
ESP_LOGE(TAG, "Unable parse extranonce: %s", result->valuestring);
|
||||
return -1;
|
||||
}
|
||||
*extranonce = malloc(strlen(extranonce_json->valuestring) + 1);
|
||||
strcpy(*extranonce, extranonce_json->valuestring);
|
||||
@ -250,14 +266,14 @@ int _parse_stratum_subscribe_result_message(const char * result_json_str,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int STRATUM_V1_subscribe(int socket, char ** extranonce, int * extranonce2_len)
|
||||
int STRATUM_V1_subscribe(int socket, char **extranonce, int *extranonce2_len)
|
||||
{
|
||||
// Subscribe
|
||||
char subscribe_msg[BUFFER_SIZE];
|
||||
sprintf(subscribe_msg, "{\"id\": %d, \"method\": \"mining.subscribe\", \"params\": [\"bitaxe %s\"]}\n", send_uid++, CONFIG_ASIC_MODEL);
|
||||
debug_stratum_tx(subscribe_msg);
|
||||
write(socket, subscribe_msg, strlen(subscribe_msg));
|
||||
char * line;
|
||||
char *line;
|
||||
line = STRATUM_V1_receive_jsonrpc_line(socket);
|
||||
|
||||
ESP_LOGI(TAG, "Received result %s", line);
|
||||
@ -288,7 +304,7 @@ int STRATUM_V1_suggest_difficulty(int socket, uint32_t difficulty)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int STRATUM_V1_authenticate(int socket, const char * username)
|
||||
int STRATUM_V1_authenticate(int socket, const char *username)
|
||||
{
|
||||
char authorize_msg[BUFFER_SIZE];
|
||||
sprintf(authorize_msg, "{\"id\": %d, \"method\": \"mining.authorize\", \"params\": [\"%s\", \"x\"]}\n",
|
||||
@ -306,8 +322,8 @@ int STRATUM_V1_authenticate(int socket, const char * username)
|
||||
/// @param ntime The hex-encoded time value use in the block header.
|
||||
/// @param extranonce_2 The hex-encoded value of extra nonce 2.
|
||||
/// @param nonce The hex-encoded nonce value to use in the block header.
|
||||
void STRATUM_V1_submit_share(int socket, const char * username, const char * jobid,
|
||||
const char * extranonce_2, const uint32_t ntime, const uint32_t nonce,
|
||||
void STRATUM_V1_submit_share(int socket, const char *username, const char *jobid,
|
||||
const char *extranonce_2, const uint32_t ntime, const uint32_t nonce,
|
||||
const uint32_t version)
|
||||
{
|
||||
char submit_msg[BUFFER_SIZE];
|
||||
@ -315,10 +331,8 @@ void STRATUM_V1_submit_share(int socket, const char * username, const char * job
|
||||
send_uid++, username, jobid, extranonce_2, ntime, nonce, version);
|
||||
debug_stratum_tx(submit_msg);
|
||||
write(socket, submit_msg, strlen(submit_msg));
|
||||
|
||||
}
|
||||
|
||||
|
||||
void STRATUM_V1_configure_version_rolling(int socket)
|
||||
{
|
||||
// Configure
|
||||
@ -330,6 +344,7 @@ void STRATUM_V1_configure_version_rolling(int socket)
|
||||
return;
|
||||
}
|
||||
|
||||
static void debug_stratum_tx(const char * msg) {
|
||||
static void debug_stratum_tx(const char *msg)
|
||||
{
|
||||
ESP_LOGI(TAG, "tx: %s", msg);
|
||||
}
|
@ -6,11 +6,11 @@
|
||||
|
||||
TEST_CASE("Check coinbase tx construction", "[mining]")
|
||||
{
|
||||
const char * coinbase_1 = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff20020862062f503253482f04b8864e5008";
|
||||
const char * coinbase_2 = "072f736c7573682f000000000100f2052a010000001976a914d23fcdf86f7e756a64a7a9688ef9903327048ed988ac00000000";
|
||||
const char * extranonce = "e9695791";
|
||||
const char * extranonce_2 = "99999999";
|
||||
char * coinbase_tx = construct_coinbase_tx(coinbase_1, coinbase_2, extranonce, extranonce_2);
|
||||
const char *coinbase_1 = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff20020862062f503253482f04b8864e5008";
|
||||
const char *coinbase_2 = "072f736c7573682f000000000100f2052a010000001976a914d23fcdf86f7e756a64a7a9688ef9903327048ed988ac00000000";
|
||||
const char *extranonce = "e9695791";
|
||||
const char *extranonce_2 = "99999999";
|
||||
char *coinbase_tx = construct_coinbase_tx(coinbase_1, coinbase_2, extranonce, extranonce_2);
|
||||
TEST_ASSERT_EQUAL_STRING(coinbase_tx, "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff20020862062f503253482f04b8864e5008e969579199999999072f736c7573682f000000000100f2052a010000001976a914d23fcdf86f7e756a64a7a9688ef9903327048ed988ac00000000");
|
||||
free(coinbase_tx);
|
||||
}
|
||||
@ -18,7 +18,7 @@ TEST_CASE("Check coinbase tx construction", "[mining]")
|
||||
// Values calculated from esp-miner/components/stratum/test/verifiers/merklecalc.py
|
||||
TEST_CASE("Validate merkle root calculation", "[mining]")
|
||||
{
|
||||
const char * coinbase_tx = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff20020862062f503253482f04b8864e5008e969579199999999072f736c7573682f000000000100f2052a010000001976a914d23fcdf86f7e756a64a7a9688ef9903327048ed988ac00000000";
|
||||
const char *coinbase_tx = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff20020862062f503253482f04b8864e5008e969579199999999072f736c7573682f000000000100f2052a010000001976a914d23fcdf86f7e756a64a7a9688ef9903327048ed988ac00000000";
|
||||
uint8_t merkles[12][32];
|
||||
int num_merkles = 12;
|
||||
|
||||
@ -35,14 +35,14 @@ TEST_CASE("Validate merkle root calculation", "[mining]")
|
||||
hex2bin("463c19427286342120039a83218fa87ce45448e246895abac11fff0036076758", merkles[10], 32);
|
||||
hex2bin("03d287f655813e540ddb9c4e7aeb922478662b0f5d8e9d0cbd564b20146bab76", merkles[11], 32);
|
||||
|
||||
char * root_hash = calculate_merkle_root_hash(coinbase_tx, merkles, num_merkles);
|
||||
char *root_hash = calculate_merkle_root_hash(coinbase_tx, merkles, num_merkles);
|
||||
TEST_ASSERT_EQUAL_STRING("adbcbc21e20388422198a55957aedfa0e61be0b8f2b87d7c08510bb9f099a893", root_hash);
|
||||
free(root_hash);
|
||||
}
|
||||
|
||||
TEST_CASE("Validate another merkle root calculation", "[mining]")
|
||||
{
|
||||
const char * coinbase_tx = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff2503777d07062f503253482f0405b8c75208f800880e000000000b2f436f696e48756e74722f0000000001603f352a010000001976a914c633315d376c20a973a758f7422d67f7bfed9c5888ac00000000";
|
||||
const char *coinbase_tx = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff2503777d07062f503253482f0405b8c75208f800880e000000000b2f436f696e48756e74722f0000000001603f352a010000001976a914c633315d376c20a973a758f7422d67f7bfed9c5888ac00000000";
|
||||
uint8_t merkles[5][32];
|
||||
int num_merkles = 5;
|
||||
|
||||
@ -52,7 +52,7 @@ TEST_CASE("Validate another merkle root calculation", "[mining]")
|
||||
hex2bin("9f64f3b0d9edddb14be6f71c3ac2e80455916e207ffc003316c6a515452aa7b4", merkles[3], 32);
|
||||
hex2bin("2d0b54af60fad4ae59ec02031f661d026f2bb95e2eeb1e6657a35036c017c595", merkles[4], 32);
|
||||
|
||||
char * root_hash = calculate_merkle_root_hash(coinbase_tx, merkles, num_merkles);
|
||||
char *root_hash = calculate_merkle_root_hash(coinbase_tx, merkles, num_merkles);
|
||||
TEST_ASSERT_EQUAL_STRING("5cc58f5e84aafc740d521b92a7bf72f4e56c4cc3ad1c2159f1d094f97ac34eee", root_hash);
|
||||
free(root_hash);
|
||||
}
|
||||
@ -65,7 +65,7 @@ TEST_CASE("Validate bm job construction", "[mining]")
|
||||
notify_message.version = 0x20000004;
|
||||
notify_message.target = 0x1705dd01;
|
||||
notify_message.ntime = 0x64658bd8;
|
||||
const char * merkle_root = "cd1be82132ef0d12053dcece1fa0247fcfdb61d4dbd3eb32ea9ef9b4c604a846";
|
||||
const char *merkle_root = "cd1be82132ef0d12053dcece1fa0247fcfdb61d4dbd3eb32ea9ef9b4c604a846";
|
||||
bm_job job = construct_bm_job(¬ify_message, merkle_root, 0);
|
||||
|
||||
uint8_t expected_midstate_bin[32];
|
||||
@ -117,23 +117,23 @@ TEST_CASE("Validate version mask incrementing", "[mining]")
|
||||
|
||||
TEST_CASE("Test extranonce 2 generation", "[mining extranonce2]")
|
||||
{
|
||||
char * first = extranonce_2_generate(0, 4);
|
||||
char *first = extranonce_2_generate(0, 4);
|
||||
TEST_ASSERT_EQUAL_STRING("00000000", first);
|
||||
free(first);
|
||||
|
||||
char * second = extranonce_2_generate(1, 4);
|
||||
char *second = extranonce_2_generate(1, 4);
|
||||
TEST_ASSERT_EQUAL_STRING("01000000", second);
|
||||
free(second);
|
||||
|
||||
char * third = extranonce_2_generate(2, 4);
|
||||
char *third = extranonce_2_generate(2, 4);
|
||||
TEST_ASSERT_EQUAL_STRING("02000000", third);
|
||||
free(third);
|
||||
|
||||
char * fourth = extranonce_2_generate(UINT_MAX - 1, 4);
|
||||
char *fourth = extranonce_2_generate(UINT_MAX - 1, 4);
|
||||
TEST_ASSERT_EQUAL_STRING("feffffff", fourth);
|
||||
free(fourth);
|
||||
|
||||
char * fifth = extranonce_2_generate(UINT_MAX / 2, 6);
|
||||
char *fifth = extranonce_2_generate(UINT_MAX / 2, 6);
|
||||
TEST_ASSERT_EQUAL_STRING("ffffff7f0000", fifth);
|
||||
free(fifth);
|
||||
}
|
||||
@ -145,12 +145,12 @@ TEST_CASE("Test nonce diff checking", "[mining test_nonce]")
|
||||
notify_message.version = 0x20000004;
|
||||
notify_message.target = 0x1705ae3a;
|
||||
notify_message.ntime = 0x646ff1a9;
|
||||
const char * merkle_root = "6d0359c451434605c52a5a9ce074340be47c2c63840731f9edf1db3f26b1cdd9a9f16f64";
|
||||
const char *merkle_root = "6d0359c451434605c52a5a9ce074340be47c2c63840731f9edf1db3f26b1cdd9a9f16f64";
|
||||
bm_job job = construct_bm_job(¬ify_message, merkle_root, 0);
|
||||
|
||||
uint32_t nonce = 0x276E8947;
|
||||
double diff = test_nonce_value(&job, nonce, 0);
|
||||
TEST_ASSERT_EQUAL_INT(18, (int) diff);
|
||||
TEST_ASSERT_EQUAL_INT(18, (int)diff);
|
||||
}
|
||||
|
||||
TEST_CASE("Test nonce diff checking 2", "[mining test_nonce]")
|
||||
@ -161,7 +161,7 @@ TEST_CASE("Test nonce diff checking 2", "[mining test_nonce]")
|
||||
notify_message.target = 0x1705ae3a;
|
||||
notify_message.ntime = 0x647025b5;
|
||||
|
||||
const char * coinbase_tx = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b0389130cfabe6d6d5cbab26a2599e92916edec5657a94a0708ddb970f5c45b5d12905085617eff8e010000000000000031650707758de07b010000000000001cfd7038212f736c7573682f000000000379ad0c2a000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3ae725d3994b811572c1f345deb98b56b465ef8e153ecbbd27fa37bf1b005161380000000000000000266a24aa21a9ed63b06a7946b190a3fda1d76165b25c9b883bcc6621b040773050ee2a1bb18f1800000000";
|
||||
const char *coinbase_tx = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b0389130cfabe6d6d5cbab26a2599e92916edec5657a94a0708ddb970f5c45b5d12905085617eff8e010000000000000031650707758de07b010000000000001cfd7038212f736c7573682f000000000379ad0c2a000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3ae725d3994b811572c1f345deb98b56b465ef8e153ecbbd27fa37bf1b005161380000000000000000266a24aa21a9ed63b06a7946b190a3fda1d76165b25c9b883bcc6621b040773050ee2a1bb18f1800000000";
|
||||
uint8_t merkles[13][32];
|
||||
int num_merkles = 13;
|
||||
|
||||
@ -179,12 +179,12 @@ TEST_CASE("Test nonce diff checking 2", "[mining test_nonce]")
|
||||
hex2bin("c4f5ab01913fc186d550c1a28f3f3e9ffaca2016b961a6a751f8cca0089df924", merkles[11], 32);
|
||||
hex2bin("cff737e1d00176dd6bbfa73071adbb370f227cfb5fba186562e4060fcec877e1", merkles[12], 32);
|
||||
|
||||
char * merkle_root = calculate_merkle_root_hash(coinbase_tx, merkles, num_merkles);
|
||||
char *merkle_root = calculate_merkle_root_hash(coinbase_tx, merkles, num_merkles);
|
||||
TEST_ASSERT_EQUAL_STRING("5bdc1968499c3393873edf8e07a1c3a50a97fc3a9d1a376bbf77087dd63778eb", merkle_root);
|
||||
|
||||
bm_job job = construct_bm_job(¬ify_message, merkle_root, 0);
|
||||
|
||||
uint32_t nonce = 0x0a029ed1;
|
||||
double diff = test_nonce_value(&job, nonce, 0);
|
||||
TEST_ASSERT_EQUAL_INT(683, (int) diff);
|
||||
TEST_ASSERT_EQUAL_INT(683, (int)diff);
|
||||
}
|
||||
|
@ -3,65 +3,56 @@
|
||||
|
||||
TEST_CASE("Parse stratum method", "[stratum]")
|
||||
{
|
||||
StratumApiV1Message stratum_api_v1_message = {};
|
||||
|
||||
const char * json_string_standard = "{\"id\":null,\"method\":\"mining.notify\",\"params\":"
|
||||
"[\"1b4c3d9041\","
|
||||
"\"ef4b9a48c7986466de4adc002f7337a6e121bc43000376ea0000000000000000\","
|
||||
"\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b03a5020cfabe6d6d379ae882651f6469f2ed6b8b40a4f9a4b41fd838a3ad6de8cba775f4e8f1d3080100000000000000\","
|
||||
"\"41903d4c1b2f736c7573682f0000000003ca890d27000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3a4cb4cb2ddfc37c41baf5ef6b6b4899e3253a8f1dfc7e5dd68a5b5b27005014ef0000000000000000266a24aa21a9ed5caa249f1af9fbf71c986fea8e076ca34ae3514fb2f86400561b28c7b15949bf00000000\","
|
||||
"[\"ae23055e00f0f697cc3640124812d96d4fe8bdfa03484c1c638ce5a1c0e9aa81\",\"980fb87cb61021dd7afd314fcb0dabd096f3d56a7377f6f320684652e7410a21\",\"a52e9868343c55ce405be8971ff340f562ae9ab6353f07140d01666180e19b52\",\"7435bdfa004e603953b2ed39f118803934d9cf17b06d979ceb682f2251bafac2\",\"2a91f061a22d27cb8f44eea79938fb241ebeb359891aa907f05ffde7ed44e52e\",\"302401f80eb5e958155135e25200bb8ea181ad2d05e804a531c7314d86403cdc\",\"318ecb6161eb9b4cfd802bd730e2d36c167ddf102e70aa7b4158e2870dd47392\",\"1114332a9858e0cf84b2425bb1e59eaabf91dd102d114aa443d57fc1b3beb0c9\",\"f43f38095c810613ed795a44d9fab02ff25269706f454885db9be05cdf9c06e1\",\"3e2fc26b27fddc39668b59099cd9635761bb72ed92404204e12bdff08b16fb75\",\"463c19427286342120039a83218fa87ce45448e246895abac11fff0036076758\",\"03d287f655813e540ddb9c4e7aeb922478662b0f5d8e9d0cbd564b20146bab76\"],"
|
||||
"\"20000004\",\"1705c739\",\"64495522\",false]}";
|
||||
StratumApiV1Message stratum_api_v1_message = {};
|
||||
|
||||
const char *json_string_standard = "{\"id\":null,\"method\":\"mining.notify\",\"params\":"
|
||||
"[\"1b4c3d9041\","
|
||||
"\"ef4b9a48c7986466de4adc002f7337a6e121bc43000376ea0000000000000000\","
|
||||
"\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b03a5020cfabe6d6d379ae882651f6469f2ed6b8b40a4f9a4b41fd838a3ad6de8cba775f4e8f1d3080100000000000000\","
|
||||
"\"41903d4c1b2f736c7573682f0000000003ca890d27000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3a4cb4cb2ddfc37c41baf5ef6b6b4899e3253a8f1dfc7e5dd68a5b5b27005014ef0000000000000000266a24aa21a9ed5caa249f1af9fbf71c986fea8e076ca34ae3514fb2f86400561b28c7b15949bf00000000\","
|
||||
"[\"ae23055e00f0f697cc3640124812d96d4fe8bdfa03484c1c638ce5a1c0e9aa81\",\"980fb87cb61021dd7afd314fcb0dabd096f3d56a7377f6f320684652e7410a21\",\"a52e9868343c55ce405be8971ff340f562ae9ab6353f07140d01666180e19b52\",\"7435bdfa004e603953b2ed39f118803934d9cf17b06d979ceb682f2251bafac2\",\"2a91f061a22d27cb8f44eea79938fb241ebeb359891aa907f05ffde7ed44e52e\",\"302401f80eb5e958155135e25200bb8ea181ad2d05e804a531c7314d86403cdc\",\"318ecb6161eb9b4cfd802bd730e2d36c167ddf102e70aa7b4158e2870dd47392\",\"1114332a9858e0cf84b2425bb1e59eaabf91dd102d114aa443d57fc1b3beb0c9\",\"f43f38095c810613ed795a44d9fab02ff25269706f454885db9be05cdf9c06e1\",\"3e2fc26b27fddc39668b59099cd9635761bb72ed92404204e12bdff08b16fb75\",\"463c19427286342120039a83218fa87ce45448e246895abac11fff0036076758\",\"03d287f655813e540ddb9c4e7aeb922478662b0f5d8e9d0cbd564b20146bab76\"],"
|
||||
"\"20000004\",\"1705c739\",\"64495522\",false]}";
|
||||
|
||||
STRATUM_V1_parse(&stratum_api_v1_message, json_string_standard);
|
||||
TEST_ASSERT_EQUAL(MINING_NOTIFY, stratum_api_v1_message.method);
|
||||
TEST_ASSERT_EQUAL_INT(0, stratum_api_v1_message.should_abandon_work);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE("Parse stratum mining.notify abandon work", "[stratum]")
|
||||
{
|
||||
StratumApiV1Message stratum_api_v1_message = {};
|
||||
|
||||
const char * json_string_abandon_work_false = "{\"id\":null,\"method\":\"mining.notify\",\"params\":"
|
||||
"[\"1b4c3d9041\","
|
||||
"\"ef4b9a48c7986466de4adc002f7337a6e121bc43000376ea0000000000000000\","
|
||||
"\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b03a5020cfabe6d6d379ae882651f6469f2ed6b8b40a4f9a4b41fd838a3ad6de8cba775f4e8f1d3080100000000000000\","
|
||||
"\"41903d4c1b2f736c7573682f0000000003ca890d27000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3a4cb4cb2ddfc37c41baf5ef6b6b4899e3253a8f1dfc7e5dd68a5b5b27005014ef0000000000000000266a24aa21a9ed5caa249f1af9fbf71c986fea8e076ca34ae3514fb2f86400561b28c7b15949bf00000000\","
|
||||
"[\"ae23055e00f0f697cc3640124812d96d4fe8bdfa03484c1c638ce5a1c0e9aa81\",\"980fb87cb61021dd7afd314fcb0dabd096f3d56a7377f6f320684652e7410a21\",\"a52e9868343c55ce405be8971ff340f562ae9ab6353f07140d01666180e19b52\",\"7435bdfa004e603953b2ed39f118803934d9cf17b06d979ceb682f2251bafac2\",\"2a91f061a22d27cb8f44eea79938fb241ebeb359891aa907f05ffde7ed44e52e\",\"302401f80eb5e958155135e25200bb8ea181ad2d05e804a531c7314d86403cdc\",\"318ecb6161eb9b4cfd802bd730e2d36c167ddf102e70aa7b4158e2870dd47392\",\"1114332a9858e0cf84b2425bb1e59eaabf91dd102d114aa443d57fc1b3beb0c9\",\"f43f38095c810613ed795a44d9fab02ff25269706f454885db9be05cdf9c06e1\",\"3e2fc26b27fddc39668b59099cd9635761bb72ed92404204e12bdff08b16fb75\",\"463c19427286342120039a83218fa87ce45448e246895abac11fff0036076758\",\"03d287f655813e540ddb9c4e7aeb922478662b0f5d8e9d0cbd564b20146bab76\"],"
|
||||
"\"20000004\",\"1705c739\",\"64495522\",false]}";
|
||||
|
||||
const char *json_string_abandon_work_false = "{\"id\":null,\"method\":\"mining.notify\",\"params\":"
|
||||
"[\"1b4c3d9041\","
|
||||
"\"ef4b9a48c7986466de4adc002f7337a6e121bc43000376ea0000000000000000\","
|
||||
"\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b03a5020cfabe6d6d379ae882651f6469f2ed6b8b40a4f9a4b41fd838a3ad6de8cba775f4e8f1d3080100000000000000\","
|
||||
"\"41903d4c1b2f736c7573682f0000000003ca890d27000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3a4cb4cb2ddfc37c41baf5ef6b6b4899e3253a8f1dfc7e5dd68a5b5b27005014ef0000000000000000266a24aa21a9ed5caa249f1af9fbf71c986fea8e076ca34ae3514fb2f86400561b28c7b15949bf00000000\","
|
||||
"[\"ae23055e00f0f697cc3640124812d96d4fe8bdfa03484c1c638ce5a1c0e9aa81\",\"980fb87cb61021dd7afd314fcb0dabd096f3d56a7377f6f320684652e7410a21\",\"a52e9868343c55ce405be8971ff340f562ae9ab6353f07140d01666180e19b52\",\"7435bdfa004e603953b2ed39f118803934d9cf17b06d979ceb682f2251bafac2\",\"2a91f061a22d27cb8f44eea79938fb241ebeb359891aa907f05ffde7ed44e52e\",\"302401f80eb5e958155135e25200bb8ea181ad2d05e804a531c7314d86403cdc\",\"318ecb6161eb9b4cfd802bd730e2d36c167ddf102e70aa7b4158e2870dd47392\",\"1114332a9858e0cf84b2425bb1e59eaabf91dd102d114aa443d57fc1b3beb0c9\",\"f43f38095c810613ed795a44d9fab02ff25269706f454885db9be05cdf9c06e1\",\"3e2fc26b27fddc39668b59099cd9635761bb72ed92404204e12bdff08b16fb75\",\"463c19427286342120039a83218fa87ce45448e246895abac11fff0036076758\",\"03d287f655813e540ddb9c4e7aeb922478662b0f5d8e9d0cbd564b20146bab76\"],"
|
||||
"\"20000004\",\"1705c739\",\"64495522\",false]}";
|
||||
|
||||
STRATUM_V1_parse(&stratum_api_v1_message, json_string_abandon_work_false);
|
||||
TEST_ASSERT_EQUAL(MINING_NOTIFY, stratum_api_v1_message.method);
|
||||
TEST_ASSERT_EQUAL_INT(0, stratum_api_v1_message.should_abandon_work);
|
||||
|
||||
|
||||
const char * json_string_abandon_work = "{\"id\":null,\"method\":\"mining.notify\",\"params\":"
|
||||
"[\"1b4c3d9041\","
|
||||
"\"ef4b9a48c7986466de4adc002f7337a6e121bc43000376ea0000000000000000\","
|
||||
"\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b03a5020cfabe6d6d379ae882651f6469f2ed6b8b40a4f9a4b41fd838a3ad6de8cba775f4e8f1d3080100000000000000\","
|
||||
"\"41903d4c1b2f736c7573682f0000000003ca890d27000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3a4cb4cb2ddfc37c41baf5ef6b6b4899e3253a8f1dfc7e5dd68a5b5b27005014ef0000000000000000266a24aa21a9ed5caa249f1af9fbf71c986fea8e076ca34ae3514fb2f86400561b28c7b15949bf00000000\","
|
||||
"[\"ae23055e00f0f697cc3640124812d96d4fe8bdfa03484c1c638ce5a1c0e9aa81\",\"980fb87cb61021dd7afd314fcb0dabd096f3d56a7377f6f320684652e7410a21\",\"a52e9868343c55ce405be8971ff340f562ae9ab6353f07140d01666180e19b52\",\"7435bdfa004e603953b2ed39f118803934d9cf17b06d979ceb682f2251bafac2\",\"2a91f061a22d27cb8f44eea79938fb241ebeb359891aa907f05ffde7ed44e52e\",\"302401f80eb5e958155135e25200bb8ea181ad2d05e804a531c7314d86403cdc\",\"318ecb6161eb9b4cfd802bd730e2d36c167ddf102e70aa7b4158e2870dd47392\",\"1114332a9858e0cf84b2425bb1e59eaabf91dd102d114aa443d57fc1b3beb0c9\",\"f43f38095c810613ed795a44d9fab02ff25269706f454885db9be05cdf9c06e1\",\"3e2fc26b27fddc39668b59099cd9635761bb72ed92404204e12bdff08b16fb75\",\"463c19427286342120039a83218fa87ce45448e246895abac11fff0036076758\",\"03d287f655813e540ddb9c4e7aeb922478662b0f5d8e9d0cbd564b20146bab76\"],"
|
||||
"\"20000004\",\"1705c739\",\"64495522\",true]}";
|
||||
|
||||
const char *json_string_abandon_work = "{\"id\":null,\"method\":\"mining.notify\",\"params\":"
|
||||
"[\"1b4c3d9041\","
|
||||
"\"ef4b9a48c7986466de4adc002f7337a6e121bc43000376ea0000000000000000\","
|
||||
"\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b03a5020cfabe6d6d379ae882651f6469f2ed6b8b40a4f9a4b41fd838a3ad6de8cba775f4e8f1d3080100000000000000\","
|
||||
"\"41903d4c1b2f736c7573682f0000000003ca890d27000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3a4cb4cb2ddfc37c41baf5ef6b6b4899e3253a8f1dfc7e5dd68a5b5b27005014ef0000000000000000266a24aa21a9ed5caa249f1af9fbf71c986fea8e076ca34ae3514fb2f86400561b28c7b15949bf00000000\","
|
||||
"[\"ae23055e00f0f697cc3640124812d96d4fe8bdfa03484c1c638ce5a1c0e9aa81\",\"980fb87cb61021dd7afd314fcb0dabd096f3d56a7377f6f320684652e7410a21\",\"a52e9868343c55ce405be8971ff340f562ae9ab6353f07140d01666180e19b52\",\"7435bdfa004e603953b2ed39f118803934d9cf17b06d979ceb682f2251bafac2\",\"2a91f061a22d27cb8f44eea79938fb241ebeb359891aa907f05ffde7ed44e52e\",\"302401f80eb5e958155135e25200bb8ea181ad2d05e804a531c7314d86403cdc\",\"318ecb6161eb9b4cfd802bd730e2d36c167ddf102e70aa7b4158e2870dd47392\",\"1114332a9858e0cf84b2425bb1e59eaabf91dd102d114aa443d57fc1b3beb0c9\",\"f43f38095c810613ed795a44d9fab02ff25269706f454885db9be05cdf9c06e1\",\"3e2fc26b27fddc39668b59099cd9635761bb72ed92404204e12bdff08b16fb75\",\"463c19427286342120039a83218fa87ce45448e246895abac11fff0036076758\",\"03d287f655813e540ddb9c4e7aeb922478662b0f5d8e9d0cbd564b20146bab76\"],"
|
||||
"\"20000004\",\"1705c739\",\"64495522\",true]}";
|
||||
|
||||
STRATUM_V1_parse(&stratum_api_v1_message, json_string_abandon_work);
|
||||
TEST_ASSERT_EQUAL(MINING_NOTIFY, stratum_api_v1_message.method);
|
||||
TEST_ASSERT_EQUAL_INT(1, stratum_api_v1_message.should_abandon_work);
|
||||
|
||||
|
||||
const char * json_string_abandon_work_length_9 = "{\"id\":null,\"method\":\"mining.notify\",\"params\":"
|
||||
"[\"1b4c3d9041\","
|
||||
"\"ef4b9a48c7986466de4adc002f7337a6e121bc43000376ea0000000000000000\","
|
||||
"\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b03a5020cfabe6d6d379ae882651f6469f2ed6b8b40a4f9a4b41fd838a3ad6de8cba775f4e8f1d3080100000000000000\","
|
||||
"\"41903d4c1b2f736c7573682f0000000003ca890d27000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3a4cb4cb2ddfc37c41baf5ef6b6b4899e3253a8f1dfc7e5dd68a5b5b27005014ef0000000000000000266a24aa21a9ed5caa249f1af9fbf71c986fea8e076ca34ae3514fb2f86400561b28c7b15949bf00000000\","
|
||||
"[\"ae23055e00f0f697cc3640124812d96d4fe8bdfa03484c1c638ce5a1c0e9aa81\",\"980fb87cb61021dd7afd314fcb0dabd096f3d56a7377f6f320684652e7410a21\",\"a52e9868343c55ce405be8971ff340f562ae9ab6353f07140d01666180e19b52\",\"7435bdfa004e603953b2ed39f118803934d9cf17b06d979ceb682f2251bafac2\",\"2a91f061a22d27cb8f44eea79938fb241ebeb359891aa907f05ffde7ed44e52e\",\"302401f80eb5e958155135e25200bb8ea181ad2d05e804a531c7314d86403cdc\",\"318ecb6161eb9b4cfd802bd730e2d36c167ddf102e70aa7b4158e2870dd47392\",\"1114332a9858e0cf84b2425bb1e59eaabf91dd102d114aa443d57fc1b3beb0c9\",\"f43f38095c810613ed795a44d9fab02ff25269706f454885db9be05cdf9c06e1\",\"3e2fc26b27fddc39668b59099cd9635761bb72ed92404204e12bdff08b16fb75\",\"463c19427286342120039a83218fa87ce45448e246895abac11fff0036076758\",\"03d287f655813e540ddb9c4e7aeb922478662b0f5d8e9d0cbd564b20146bab76\"],"
|
||||
"\"20000004\",\"1705c739\",\"64495522\",\"64495522\",true]}";
|
||||
|
||||
const char *json_string_abandon_work_length_9 = "{\"id\":null,\"method\":\"mining.notify\",\"params\":"
|
||||
"[\"1b4c3d9041\","
|
||||
"\"ef4b9a48c7986466de4adc002f7337a6e121bc43000376ea0000000000000000\","
|
||||
"\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b03a5020cfabe6d6d379ae882651f6469f2ed6b8b40a4f9a4b41fd838a3ad6de8cba775f4e8f1d3080100000000000000\","
|
||||
"\"41903d4c1b2f736c7573682f0000000003ca890d27000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3a4cb4cb2ddfc37c41baf5ef6b6b4899e3253a8f1dfc7e5dd68a5b5b27005014ef0000000000000000266a24aa21a9ed5caa249f1af9fbf71c986fea8e076ca34ae3514fb2f86400561b28c7b15949bf00000000\","
|
||||
"[\"ae23055e00f0f697cc3640124812d96d4fe8bdfa03484c1c638ce5a1c0e9aa81\",\"980fb87cb61021dd7afd314fcb0dabd096f3d56a7377f6f320684652e7410a21\",\"a52e9868343c55ce405be8971ff340f562ae9ab6353f07140d01666180e19b52\",\"7435bdfa004e603953b2ed39f118803934d9cf17b06d979ceb682f2251bafac2\",\"2a91f061a22d27cb8f44eea79938fb241ebeb359891aa907f05ffde7ed44e52e\",\"302401f80eb5e958155135e25200bb8ea181ad2d05e804a531c7314d86403cdc\",\"318ecb6161eb9b4cfd802bd730e2d36c167ddf102e70aa7b4158e2870dd47392\",\"1114332a9858e0cf84b2425bb1e59eaabf91dd102d114aa443d57fc1b3beb0c9\",\"f43f38095c810613ed795a44d9fab02ff25269706f454885db9be05cdf9c06e1\",\"3e2fc26b27fddc39668b59099cd9635761bb72ed92404204e12bdff08b16fb75\",\"463c19427286342120039a83218fa87ce45448e246895abac11fff0036076758\",\"03d287f655813e540ddb9c4e7aeb922478662b0f5d8e9d0cbd564b20146bab76\"],"
|
||||
"\"20000004\",\"1705c739\",\"64495522\",\"64495522\",true]}";
|
||||
|
||||
STRATUM_V1_parse(&stratum_api_v1_message, json_string_abandon_work_length_9);
|
||||
TEST_ASSERT_EQUAL(MINING_NOTIFY, stratum_api_v1_message.method);
|
||||
@ -70,24 +61,23 @@ TEST_CASE("Parse stratum mining.notify abandon work", "[stratum]")
|
||||
|
||||
TEST_CASE("Parse stratum set_difficulty params", "[mining.set_difficulty]")
|
||||
{
|
||||
const char * json_string = "{\"id\":null,\"method\":\"mining.set_difficulty\",\"params\":[1638]}";
|
||||
const char *json_string = "{\"id\":null,\"method\":\"mining.set_difficulty\",\"params\":[1638]}";
|
||||
StratumApiV1Message stratum_api_v1_message = {};
|
||||
STRATUM_V1_parse(&stratum_api_v1_message, json_string);
|
||||
TEST_ASSERT_EQUAL(MINING_SET_DIFFICULTY, stratum_api_v1_message.method);
|
||||
TEST_ASSERT_EQUAL(1638, stratum_api_v1_message.new_difficulty);
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE("Parse stratum notify params", "[mining.notify]")
|
||||
{
|
||||
StratumApiV1Message stratum_api_v1_message = {};
|
||||
const char * json_string = "{\"id\":null,\"method\":\"mining.notify\",\"params\":"
|
||||
"[\"1d2e0c4d3d\","
|
||||
"\"ef4b9a48c7986466de4adc002f7337a6e121bc43000376ea0000000000000000\","
|
||||
"\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b03a5020cfabe6d6d379ae882651f6469f2ed6b8b40a4f9a4b41fd838a3ad6de8cba775f4e8f1d3080100000000000000\","
|
||||
"\"41903d4c1b2f736c7573682f0000000003ca890d27000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3a4cb4cb2ddfc37c41baf5ef6b6b4899e3253a8f1dfc7e5dd68a5b5b27005014ef0000000000000000266a24aa21a9ed5caa249f1af9fbf71c986fea8e076ca34ae3514fb2f86400561b28c7b15949bf00000000\","
|
||||
"[\"ae23055e00f0f697cc3640124812d96d4fe8bdfa03484c1c638ce5a1c0e9aa81\",\"980fb87cb61021dd7afd314fcb0dabd096f3d56a7377f6f320684652e7410a21\",\"a52e9868343c55ce405be8971ff340f562ae9ab6353f07140d01666180e19b52\",\"7435bdfa004e603953b2ed39f118803934d9cf17b06d979ceb682f2251bafac2\",\"2a91f061a22d27cb8f44eea79938fb241ebeb359891aa907f05ffde7ed44e52e\",\"302401f80eb5e958155135e25200bb8ea181ad2d05e804a531c7314d86403cdc\",\"318ecb6161eb9b4cfd802bd730e2d36c167ddf102e70aa7b4158e2870dd47392\",\"1114332a9858e0cf84b2425bb1e59eaabf91dd102d114aa443d57fc1b3beb0c9\",\"f43f38095c810613ed795a44d9fab02ff25269706f454885db9be05cdf9c06e1\",\"3e2fc26b27fddc39668b59099cd9635761bb72ed92404204e12bdff08b16fb75\",\"463c19427286342120039a83218fa87ce45448e246895abac11fff0036076758\",\"03d287f655813e540ddb9c4e7aeb922478662b0f5d8e9d0cbd564b20146bab76\"],"
|
||||
"\"20000004\",\"1705c739\",\"64495522\",false]}";
|
||||
StratumApiV1Message stratum_api_v1_message = {};
|
||||
const char *json_string = "{\"id\":null,\"method\":\"mining.notify\",\"params\":"
|
||||
"[\"1d2e0c4d3d\","
|
||||
"\"ef4b9a48c7986466de4adc002f7337a6e121bc43000376ea0000000000000000\","
|
||||
"\"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4b03a5020cfabe6d6d379ae882651f6469f2ed6b8b40a4f9a4b41fd838a3ad6de8cba775f4e8f1d3080100000000000000\","
|
||||
"\"41903d4c1b2f736c7573682f0000000003ca890d27000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3a4cb4cb2ddfc37c41baf5ef6b6b4899e3253a8f1dfc7e5dd68a5b5b27005014ef0000000000000000266a24aa21a9ed5caa249f1af9fbf71c986fea8e076ca34ae3514fb2f86400561b28c7b15949bf00000000\","
|
||||
"[\"ae23055e00f0f697cc3640124812d96d4fe8bdfa03484c1c638ce5a1c0e9aa81\",\"980fb87cb61021dd7afd314fcb0dabd096f3d56a7377f6f320684652e7410a21\",\"a52e9868343c55ce405be8971ff340f562ae9ab6353f07140d01666180e19b52\",\"7435bdfa004e603953b2ed39f118803934d9cf17b06d979ceb682f2251bafac2\",\"2a91f061a22d27cb8f44eea79938fb241ebeb359891aa907f05ffde7ed44e52e\",\"302401f80eb5e958155135e25200bb8ea181ad2d05e804a531c7314d86403cdc\",\"318ecb6161eb9b4cfd802bd730e2d36c167ddf102e70aa7b4158e2870dd47392\",\"1114332a9858e0cf84b2425bb1e59eaabf91dd102d114aa443d57fc1b3beb0c9\",\"f43f38095c810613ed795a44d9fab02ff25269706f454885db9be05cdf9c06e1\",\"3e2fc26b27fddc39668b59099cd9635761bb72ed92404204e12bdff08b16fb75\",\"463c19427286342120039a83218fa87ce45448e246895abac11fff0036076758\",\"03d287f655813e540ddb9c4e7aeb922478662b0f5d8e9d0cbd564b20146bab76\"],"
|
||||
"\"20000004\",\"1705c739\",\"64495522\",false]}";
|
||||
STRATUM_V1_parse(&stratum_api_v1_message, json_string);
|
||||
TEST_ASSERT_EQUAL_STRING("1d2e0c4d3d", stratum_api_v1_message.mining_notification->job_id);
|
||||
TEST_ASSERT_EQUAL_STRING("ef4b9a48c7986466de4adc002f7337a6e121bc43000376ea0000000000000000", stratum_api_v1_message.mining_notification->prev_block_hash);
|
||||
|
@ -4,16 +4,16 @@
|
||||
|
||||
TEST_CASE("Test double sha", "[utils]")
|
||||
{
|
||||
const char * input = "68656c6c6f";
|
||||
char * output = double_sha256(input);
|
||||
const char *input = "68656c6c6f";
|
||||
char *output = double_sha256(input);
|
||||
TEST_ASSERT_EQUAL_STRING("9595c9df90075148eb06860365df33584b75bff782a510c6cd4883a419833d50", output);
|
||||
}
|
||||
|
||||
TEST_CASE("Test hex2bin", "[utils]")
|
||||
{
|
||||
char * hex_string = "48454c4c4f";
|
||||
char *hex_string = "48454c4c4f";
|
||||
size_t bin_len = strlen(hex_string) / 2;
|
||||
uint8_t * bin = malloc(bin_len);
|
||||
uint8_t *bin = malloc(bin_len);
|
||||
hex2bin(hex_string, bin, bin_len);
|
||||
TEST_ASSERT_EQUAL(72, bin[0]);
|
||||
TEST_ASSERT_EQUAL(69, bin[1]);
|
||||
@ -30,7 +30,6 @@ TEST_CASE("Test bin2hex", "[utils]")
|
||||
TEST_ASSERT_EQUAL_STRING("48454c4c4f", hex_string);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("Test hex2char", "[utils]")
|
||||
{
|
||||
char output;
|
||||
|
@ -6,38 +6,41 @@
|
||||
#include "mbedtls/sha256.h"
|
||||
|
||||
#ifndef bswap_16
|
||||
#define bswap_16(a) ((((uint16_t) (a) << 8) & 0xff00) | (((uint16_t) (a) >> 8) & 0xff))
|
||||
#define bswap_16(a) ((((uint16_t)(a) << 8) & 0xff00) | (((uint16_t)(a) >> 8) & 0xff))
|
||||
#endif
|
||||
|
||||
#ifndef bswap_32
|
||||
#define bswap_32(a) ((((uint32_t) (a) << 24) & 0xff000000) | \
|
||||
(((uint32_t) (a) << 8) & 0xff0000) | \
|
||||
(((uint32_t) (a) >> 8) & 0xff00) | \
|
||||
(((uint32_t) (a) >> 24) & 0xff))
|
||||
#define bswap_32(a) ((((uint32_t)(a) << 24) & 0xff000000) | \
|
||||
(((uint32_t)(a) << 8) & 0xff0000) | \
|
||||
(((uint32_t)(a) >> 8) & 0xff00) | \
|
||||
(((uint32_t)(a) >> 24) & 0xff))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* General byte order swapping functions.
|
||||
*/
|
||||
#define bswap16(x) __bswap16(x)
|
||||
#define bswap32(x) __bswap32(x)
|
||||
#define bswap64(x) __bswap64(x)
|
||||
#define bswap16(x) __bswap16(x)
|
||||
#define bswap32(x) __bswap32(x)
|
||||
#define bswap64(x) __bswap64(x)
|
||||
|
||||
uint32_t swab32(uint32_t v) {
|
||||
uint32_t swab32(uint32_t v)
|
||||
{
|
||||
return bswap_32(v);
|
||||
}
|
||||
|
||||
//takes 80 bytes and flips every 4 bytes
|
||||
void flip80bytes(void *dest_p, const void *src_p) {
|
||||
uint32_t *dest = dest_p;
|
||||
const uint32_t *src = src_p;
|
||||
int i;
|
||||
// takes 80 bytes and flips every 4 bytes
|
||||
void flip80bytes(void *dest_p, const void *src_p)
|
||||
{
|
||||
uint32_t *dest = dest_p;
|
||||
const uint32_t *src = src_p;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 20; i++)
|
||||
dest[i] = swab32(src[i]);
|
||||
for (i = 0; i < 20; i++)
|
||||
dest[i] = swab32(src[i]);
|
||||
}
|
||||
|
||||
void flip64bytes(void *dest_p, const void *src_p) {
|
||||
void flip64bytes(void *dest_p, const void *src_p)
|
||||
{
|
||||
uint32_t *dest = dest_p;
|
||||
const uint32_t *src = src_p;
|
||||
int i;
|
||||
@ -46,7 +49,8 @@ void flip64bytes(void *dest_p, const void *src_p) {
|
||||
dest[i] = swab32(src[i]);
|
||||
}
|
||||
|
||||
void flip32bytes(void *dest_p, const void *src_p) {
|
||||
void flip32bytes(void *dest_p, const void *src_p)
|
||||
{
|
||||
uint32_t *dest = dest_p;
|
||||
const uint32_t *src = src_p;
|
||||
int i;
|
||||
@ -55,14 +59,18 @@ void flip32bytes(void *dest_p, const void *src_p) {
|
||||
dest[i] = swab32(src[i]);
|
||||
}
|
||||
|
||||
|
||||
int hex2char(uint8_t x, char *c)
|
||||
{
|
||||
if (x <= 9) {
|
||||
if (x <= 9)
|
||||
{
|
||||
*c = x + '0';
|
||||
} else if (x <= 15) {
|
||||
}
|
||||
else if (x <= 15)
|
||||
{
|
||||
*c = x - 10 + 'a';
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -71,15 +79,19 @@ int hex2char(uint8_t x, char *c)
|
||||
|
||||
size_t bin2hex(const uint8_t *buf, size_t buflen, char *hex, size_t hexlen)
|
||||
{
|
||||
if ((hexlen + 1) < buflen * 2) {
|
||||
if ((hexlen + 1) < buflen * 2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < buflen; i++) {
|
||||
if (hex2char(buf[i] >> 4, &hex[2 * i]) < 0) {
|
||||
for (size_t i = 0; i < buflen; i++)
|
||||
{
|
||||
if (hex2char(buf[i] >> 4, &hex[2 * i]) < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (hex2char(buf[i] & 0xf, &hex[2 * i + 1]) < 0) {
|
||||
if (hex2char(buf[i] & 0xf, &hex[2 * i + 1]) < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -90,13 +102,20 @@ size_t bin2hex(const uint8_t *buf, size_t buflen, char *hex, size_t hexlen)
|
||||
|
||||
uint8_t hex2val(char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9') {
|
||||
if (c >= '0' && c <= '9')
|
||||
{
|
||||
return c - '0';
|
||||
} else if (c >= 'a' && c <= 'f') {
|
||||
}
|
||||
else if (c >= 'a' && c <= 'f')
|
||||
{
|
||||
return c - 'a' + 10;
|
||||
} else if (c >= 'A' && c <= 'F') {
|
||||
}
|
||||
else if (c >= 'A' && c <= 'F')
|
||||
{
|
||||
return c - 'A' + 10;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -105,10 +124,12 @@ size_t hex2bin(const char *hex, uint8_t *bin, size_t bin_len)
|
||||
{
|
||||
size_t len = 0;
|
||||
|
||||
while (*hex && len < bin_len) {
|
||||
while (*hex && len < bin_len)
|
||||
{
|
||||
bin[len] = hex2val(*hex++) << 4;
|
||||
|
||||
if (!*hex) {
|
||||
if (!*hex)
|
||||
{
|
||||
len++;
|
||||
break;
|
||||
}
|
||||
@ -119,35 +140,35 @@ size_t hex2bin(const char *hex, uint8_t *bin, size_t bin_len)
|
||||
return len;
|
||||
}
|
||||
|
||||
void print_hex(const uint8_t * b, size_t len,
|
||||
const size_t in_line, const char * prefix)
|
||||
void print_hex(const uint8_t *b, size_t len,
|
||||
const size_t in_line, const char *prefix)
|
||||
{
|
||||
size_t i = 0;
|
||||
const uint8_t * end = b + len;
|
||||
const uint8_t *end = b + len;
|
||||
|
||||
if( prefix == NULL )
|
||||
if (prefix == NULL)
|
||||
{
|
||||
prefix = "";
|
||||
}
|
||||
|
||||
printf( "%s", prefix );
|
||||
while( b < end )
|
||||
printf("%s", prefix);
|
||||
while (b < end)
|
||||
{
|
||||
if( ++i > in_line )
|
||||
if (++i > in_line)
|
||||
{
|
||||
printf( "\n%s", prefix );
|
||||
printf("\n%s", prefix);
|
||||
i = 1;
|
||||
}
|
||||
printf( "%02X ", (uint8_t) *b++ );
|
||||
printf("%02X ", (uint8_t)*b++);
|
||||
}
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
char * double_sha256(const char * hex_string)
|
||||
char *double_sha256(const char *hex_string)
|
||||
{
|
||||
size_t bin_len = strlen(hex_string) / 2;
|
||||
uint8_t * bin = malloc(bin_len);
|
||||
uint8_t *bin = malloc(bin_len);
|
||||
hex2bin(hex_string, bin, bin_len);
|
||||
|
||||
unsigned char first_hash_output[32], second_hash_output[32];
|
||||
@ -157,15 +178,15 @@ char * double_sha256(const char * hex_string)
|
||||
|
||||
free(bin);
|
||||
|
||||
char * output_hash = malloc(64 + 1);
|
||||
char *output_hash = malloc(64 + 1);
|
||||
bin2hex(second_hash_output, 32, output_hash, 65);
|
||||
return output_hash;
|
||||
}
|
||||
|
||||
uint8_t * double_sha256_bin(const uint8_t * data, const size_t data_len)
|
||||
uint8_t *double_sha256_bin(const uint8_t *data, const size_t data_len)
|
||||
{
|
||||
uint8_t first_hash_output[32];
|
||||
uint8_t * second_hash_output = malloc(32);
|
||||
uint8_t *second_hash_output = malloc(32);
|
||||
|
||||
mbedtls_sha256(data, data_len, first_hash_output, 0);
|
||||
mbedtls_sha256(first_hash_output, 32, second_hash_output, 0);
|
||||
@ -173,9 +194,9 @@ uint8_t * double_sha256_bin(const uint8_t * data, const size_t data_len)
|
||||
return second_hash_output;
|
||||
}
|
||||
|
||||
void single_sha256_bin( const uint8_t * data, const size_t data_len, uint8_t * dest)
|
||||
void single_sha256_bin(const uint8_t *data, const size_t data_len, uint8_t *dest)
|
||||
{
|
||||
//mbedtls_sha256(data, data_len, dest, 0);
|
||||
// mbedtls_sha256(data, data_len, dest, 0);
|
||||
|
||||
// Initialize SHA256 context
|
||||
mbedtls_sha256_context sha256_ctx;
|
||||
@ -189,34 +210,36 @@ void single_sha256_bin( const uint8_t * data, const size_t data_len, uint8_t * d
|
||||
|
||||
// Compute midstate from hash
|
||||
memcpy(dest, hash, 32);
|
||||
|
||||
}
|
||||
|
||||
void midstate_sha256_bin( const uint8_t * data, const size_t data_len, uint8_t * dest)
|
||||
void midstate_sha256_bin(const uint8_t *data, const size_t data_len, uint8_t *dest)
|
||||
{
|
||||
mbedtls_sha256_context midstate;
|
||||
|
||||
//Calculate midstate
|
||||
// Calculate midstate
|
||||
mbedtls_sha256_init(&midstate);
|
||||
mbedtls_sha256_starts(&midstate, 0);
|
||||
mbedtls_sha256_update(&midstate, data, 64);
|
||||
|
||||
//memcpy(dest, midstate.state, 32);
|
||||
// memcpy(dest, midstate.state, 32);
|
||||
flip32bytes(dest, midstate.state);
|
||||
|
||||
}
|
||||
|
||||
void swap_endian_words(const char * hex_words, uint8_t * output) {
|
||||
void swap_endian_words(const char *hex_words, uint8_t *output)
|
||||
{
|
||||
size_t hex_length = strlen(hex_words);
|
||||
if (hex_length % 8 != 0) {
|
||||
if (hex_length % 8 != 0)
|
||||
{
|
||||
fprintf(stderr, "Must be 4-byte word aligned\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
size_t binary_length = hex_length / 2;
|
||||
|
||||
for (size_t i = 0; i < binary_length; i += 4) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
for (size_t i = 0; i < binary_length; i += 4)
|
||||
{
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
unsigned int byte_val;
|
||||
sscanf(hex_words + (i + j) * 2, "%2x", &byte_val);
|
||||
output[i + (3 - j)] = byte_val;
|
||||
@ -224,15 +247,17 @@ void swap_endian_words(const char * hex_words, uint8_t * output) {
|
||||
}
|
||||
}
|
||||
|
||||
void reverse_bytes(uint8_t * data, size_t len) {
|
||||
for (int i = 0; i < len / 2; ++i) {
|
||||
void reverse_bytes(uint8_t *data, size_t len)
|
||||
{
|
||||
for (int i = 0; i < len / 2; ++i)
|
||||
{
|
||||
uint8_t temp = data[i];
|
||||
data[i] = data[len - 1 - i];
|
||||
data[len - 1 - i] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
//static const double truediffone = 26959535291011309493156476344723991336010898738574164086137773096960.0;
|
||||
// static const double truediffone = 26959535291011309493156476344723991336010898738574164086137773096960.0;
|
||||
static const double bits192 = 6277101735386680763835789423207666416102355444464034512896.0;
|
||||
static const double bits128 = 340282366920938463463374607431768211456.0;
|
||||
static const double bits64 = 18446744073709551616.0;
|
||||
@ -240,34 +265,37 @@ static const double bits64 = 18446744073709551616.0;
|
||||
/* Converts a little endian 256 bit value to a double */
|
||||
double le256todouble(const void *target)
|
||||
{
|
||||
uint64_t *data64;
|
||||
double dcut64;
|
||||
uint64_t *data64;
|
||||
double dcut64;
|
||||
|
||||
data64 = (uint64_t *)(target + 24);
|
||||
dcut64 = *data64 * bits192;
|
||||
data64 = (uint64_t *)(target + 24);
|
||||
dcut64 = *data64 * bits192;
|
||||
|
||||
data64 = (uint64_t *)(target + 16);
|
||||
dcut64 += *data64 * bits128;
|
||||
data64 = (uint64_t *)(target + 16);
|
||||
dcut64 += *data64 * bits128;
|
||||
|
||||
data64 = (uint64_t *)(target + 8);
|
||||
dcut64 += *data64 * bits64;
|
||||
data64 = (uint64_t *)(target + 8);
|
||||
dcut64 += *data64 * bits64;
|
||||
|
||||
data64 = (uint64_t *)(target);
|
||||
dcut64 += *data64;
|
||||
data64 = (uint64_t *)(target);
|
||||
dcut64 += *data64;
|
||||
|
||||
return dcut64;
|
||||
return dcut64;
|
||||
}
|
||||
|
||||
void prettyHex(unsigned char * buf, int len) {
|
||||
void prettyHex(unsigned char *buf, int len)
|
||||
{
|
||||
int i;
|
||||
printf("[");
|
||||
for (i = 0; i < len-1; i++) {
|
||||
for (i = 0; i < len - 1; i++)
|
||||
{
|
||||
printf("%02X ", buf[i]);
|
||||
}
|
||||
printf("%02X]\n", buf[len-1]);
|
||||
printf("%02X]\n", buf[len - 1]);
|
||||
}
|
||||
|
||||
uint32_t flip32(uint32_t val) {
|
||||
uint32_t flip32(uint32_t val)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
ret |= (val & 0xFF) << 24;
|
||||
ret |= (val & 0xFF00) << 8;
|
||||
|
@ -3,54 +3,55 @@
|
||||
#include "esp_log.h"
|
||||
#include "driver/i2c.h"
|
||||
|
||||
#define I2C_MASTER_SCL_IO 48 /*!< GPIO number used for I2C master clock */
|
||||
#define I2C_MASTER_SDA_IO 47 /*!< GPIO number used for I2C master data */
|
||||
#define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
|
||||
#define I2C_MASTER_FREQ_HZ 400000 /*!< I2C master clock frequency */
|
||||
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
|
||||
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
|
||||
#define I2C_MASTER_TIMEOUT_MS 1000
|
||||
#define I2C_MASTER_SCL_IO 48 /*!< GPIO number used for I2C master clock */
|
||||
#define I2C_MASTER_SDA_IO 47 /*!< GPIO number used for I2C master data */
|
||||
#define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
|
||||
#define I2C_MASTER_FREQ_HZ 400000 /*!< I2C master clock frequency */
|
||||
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
|
||||
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
|
||||
#define I2C_MASTER_TIMEOUT_MS 1000
|
||||
|
||||
// DS4432U+ -- Adjustable current DAC for use with the TPS40305 voltage regulator
|
||||
// address: 0x90
|
||||
#define DS4432U_SENSOR_ADDR 0x48 // Slave address of the DS4432U+
|
||||
#define DS4432U_OUT0_REG 0xF8 // register for current output 0
|
||||
#define DS4432U_OUT1_REG 0xF9 // register for current output 1
|
||||
|
||||
//DS4432U+ -- Adjustable current DAC for use with the TPS40305 voltage regulator
|
||||
//address: 0x90
|
||||
#define DS4432U_SENSOR_ADDR 0x48 //Slave address of the DS4432U+
|
||||
#define DS4432U_OUT0_REG 0xF8 //register for current output 0
|
||||
#define DS4432U_OUT1_REG 0xF9 //register for current output 1
|
||||
|
||||
//DS4432U Transfer function constants
|
||||
// DS4432U Transfer function constants
|
||||
#define VFB 0.6
|
||||
#define IFS 0.000098921 // (Vrfs / Rfs) x (127/16) -> Vrfs = 0.997, Rfs = 80000
|
||||
#define RA 4750.0 //R14
|
||||
#define RB 3320.0 //R15
|
||||
#define NOMINAL 1.451 //this is with the current DAC set to 0. Should be pretty close to (VFB*(RA+RB))/RB
|
||||
#define RA 4750.0 // R14
|
||||
#define RB 3320.0 // R15
|
||||
#define NOMINAL 1.451 // this is with the current DAC set to 0. Should be pretty close to (VFB*(RA+RB))/RB
|
||||
#define MAXV 2.39
|
||||
#define MINV 0.046
|
||||
|
||||
|
||||
static const char *TAG = "DS4432U.c";
|
||||
|
||||
/**
|
||||
* @brief voltage_to_reg takes a voltage and returns a register setting for the DS4432U to get that voltage on the TPS40305
|
||||
* careful with this one!!
|
||||
*/
|
||||
static uint8_t voltage_to_reg(float vout) {
|
||||
float change;
|
||||
static uint8_t voltage_to_reg(float vout)
|
||||
{
|
||||
float change;
|
||||
uint8_t reg;
|
||||
|
||||
//make sure the requested voltage is in within range of MINV and MAXV
|
||||
if (vout > MAXV || vout < MINV) {
|
||||
return 0;
|
||||
}
|
||||
// make sure the requested voltage is in within range of MINV and MAXV
|
||||
if (vout > MAXV || vout < MINV)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//this is the transfer function. comes from the DS4432U+ datasheet
|
||||
change = fabs((((VFB/RB) - ((vout-VFB)/RA))/IFS) * 127);
|
||||
reg = (uint8_t)ceil(change);
|
||||
// this is the transfer function. comes from the DS4432U+ datasheet
|
||||
change = fabs((((VFB / RB) - ((vout - VFB) / RA)) / IFS) * 127);
|
||||
reg = (uint8_t)ceil(change);
|
||||
|
||||
//Set the MSB high if the requested voltage is BELOW nominal
|
||||
if (vout < NOMINAL) {
|
||||
reg |= 0x80;
|
||||
}
|
||||
// Set the MSB high if the requested voltage is BELOW nominal
|
||||
if (vout < NOMINAL)
|
||||
{
|
||||
reg |= 0x80;
|
||||
}
|
||||
|
||||
return reg;
|
||||
}
|
||||
@ -58,7 +59,8 @@ static uint8_t voltage_to_reg(float vout) {
|
||||
/**
|
||||
* @brief i2c master initialization
|
||||
*/
|
||||
esp_err_t i2c_master_init(void) {
|
||||
esp_err_t i2c_master_init(void)
|
||||
{
|
||||
int i2c_master_port = I2C_MASTER_NUM;
|
||||
|
||||
i2c_config_t conf = {
|
||||
@ -78,22 +80,24 @@ esp_err_t i2c_master_init(void) {
|
||||
/**
|
||||
* @brief i2c master delete
|
||||
*/
|
||||
esp_err_t i2c_master_delete(void) {
|
||||
esp_err_t i2c_master_delete(void)
|
||||
{
|
||||
return i2c_driver_delete(I2C_MASTER_NUM);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Read a sequence of I2C bytes
|
||||
*/
|
||||
static esp_err_t register_read(uint8_t reg_addr, uint8_t *data, size_t len) {
|
||||
return i2c_master_write_read_device(I2C_MASTER_NUM, DS4432U_SENSOR_ADDR, ®_addr, 1, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
|
||||
static esp_err_t register_read(uint8_t reg_addr, uint8_t *data, size_t len)
|
||||
{
|
||||
return i2c_master_write_read_device(I2C_MASTER_NUM, DS4432U_SENSOR_ADDR, ®_addr, 1, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write a byte to a I2C register
|
||||
*/
|
||||
static esp_err_t register_write_byte(uint8_t reg_addr, uint8_t data) {
|
||||
static esp_err_t register_write_byte(uint8_t reg_addr, uint8_t data)
|
||||
{
|
||||
int ret;
|
||||
uint8_t write_buf[2] = {reg_addr, data};
|
||||
|
||||
@ -102,7 +106,8 @@ static esp_err_t register_write_byte(uint8_t reg_addr, uint8_t data) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DS4432U_read(void) {
|
||||
void DS4432U_read(void)
|
||||
{
|
||||
uint8_t data[3];
|
||||
|
||||
/* Read the DS4432U+ WHO_AM_I register, on power up the register should have the value 0x00 */
|
||||
@ -110,19 +115,21 @@ void DS4432U_read(void) {
|
||||
ESP_LOGI(TAG, "DS4432U+ OUT1 = 0x%02X", data[0]);
|
||||
}
|
||||
|
||||
static void DS4432U_set(uint8_t val) {
|
||||
static void DS4432U_set(uint8_t val)
|
||||
{
|
||||
ESP_LOGI(TAG, "Writing 0x%02X", val);
|
||||
ESP_ERROR_CHECK(register_write_byte(DS4432U_OUT0_REG, val));
|
||||
}
|
||||
|
||||
bool DS4432U_set_vcore(float core_voltage) {
|
||||
bool DS4432U_set_vcore(float core_voltage)
|
||||
{
|
||||
uint8_t reg_setting;
|
||||
|
||||
reg_setting = voltage_to_reg(core_voltage);
|
||||
|
||||
ESP_LOGI(TAG, "Set BM1397 voltage = %.3fV [0x%02X]", core_voltage, reg_setting);
|
||||
|
||||
DS4432U_set(reg_setting); ///eek!
|
||||
DS4432U_set(reg_setting); /// eek!
|
||||
|
||||
return true;
|
||||
}
|
@ -4,27 +4,29 @@
|
||||
|
||||
#include "EMC2101.h"
|
||||
|
||||
#define I2C_MASTER_SCL_IO 48 /*!< GPIO number used for I2C master clock */
|
||||
#define I2C_MASTER_SDA_IO 47 /*!< GPIO number used for I2C master data */
|
||||
#define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
|
||||
#define I2C_MASTER_FREQ_HZ 400000 /*!< I2C master clock frequency */
|
||||
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
|
||||
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
|
||||
#define I2C_MASTER_TIMEOUT_MS 1000
|
||||
#define I2C_MASTER_SCL_IO 48 /*!< GPIO number used for I2C master clock */
|
||||
#define I2C_MASTER_SDA_IO 47 /*!< GPIO number used for I2C master data */
|
||||
#define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
|
||||
#define I2C_MASTER_FREQ_HZ 400000 /*!< I2C master clock frequency */
|
||||
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
|
||||
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
|
||||
#define I2C_MASTER_TIMEOUT_MS 1000
|
||||
|
||||
//static const char *TAG = "EMC2101.c";
|
||||
// static const char *TAG = "EMC2101.c";
|
||||
|
||||
/**
|
||||
* @brief Read a sequence of I2C bytes
|
||||
*/
|
||||
static esp_err_t register_read(uint8_t reg_addr, uint8_t *data, size_t len) {
|
||||
return i2c_master_write_read_device(I2C_MASTER_NUM, EMC2101_I2CADDR_DEFAULT, ®_addr, 1, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
|
||||
static esp_err_t register_read(uint8_t reg_addr, uint8_t *data, size_t len)
|
||||
{
|
||||
return i2c_master_write_read_device(I2C_MASTER_NUM, EMC2101_I2CADDR_DEFAULT, ®_addr, 1, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write a byte to a I2C register
|
||||
*/
|
||||
static esp_err_t register_write_byte(uint8_t reg_addr, uint8_t data) {
|
||||
static esp_err_t register_write_byte(uint8_t reg_addr, uint8_t data)
|
||||
{
|
||||
int ret;
|
||||
uint8_t write_buf[2] = {reg_addr, data};
|
||||
|
||||
@ -33,23 +35,26 @@ static esp_err_t register_write_byte(uint8_t reg_addr, uint8_t data) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
//run this first. sets up the config register
|
||||
void EMC2101_init(void) {
|
||||
// run this first. sets up the config register
|
||||
void EMC2101_init(void)
|
||||
{
|
||||
|
||||
//set the TACH input
|
||||
// set the TACH input
|
||||
ESP_ERROR_CHECK(register_write_byte(EMC2101_REG_CONFIG, 0x04));
|
||||
}
|
||||
|
||||
//takes a fan speed percent
|
||||
void EMC2101_set_fan_speed(float percent) {
|
||||
// takes a fan speed percent
|
||||
void EMC2101_set_fan_speed(float percent)
|
||||
{
|
||||
uint8_t speed;
|
||||
|
||||
speed = (uint8_t)(63.0 * percent);
|
||||
ESP_ERROR_CHECK(register_write_byte(EMC2101_REG_FAN_SETTING, speed));
|
||||
}
|
||||
|
||||
//RPM = 5400000/reading
|
||||
uint16_t EMC2101_get_fan_speed(void) {
|
||||
// RPM = 5400000/reading
|
||||
uint16_t EMC2101_get_fan_speed(void)
|
||||
{
|
||||
uint8_t tach_lsb, tach_msb;
|
||||
uint16_t reading;
|
||||
uint16_t RPM;
|
||||
@ -57,20 +62,20 @@ uint16_t EMC2101_get_fan_speed(void) {
|
||||
ESP_ERROR_CHECK(register_read(EMC2101_TACH_LSB, &tach_lsb, 1));
|
||||
ESP_ERROR_CHECK(register_read(EMC2101_TACH_MSB, &tach_msb, 1));
|
||||
|
||||
//ESP_LOGI(TAG, "Raw Fan Speed = %02X %02X", tach_msb, tach_lsb);
|
||||
// ESP_LOGI(TAG, "Raw Fan Speed = %02X %02X", tach_msb, tach_lsb);
|
||||
|
||||
reading = tach_lsb | (tach_msb << 8);
|
||||
RPM = 5400000/reading;
|
||||
RPM = 5400000 / reading;
|
||||
|
||||
//ESP_LOGI(TAG, "Fan Speed = %d RPM", RPM);
|
||||
// ESP_LOGI(TAG, "Fan Speed = %d RPM", RPM);
|
||||
return RPM;
|
||||
}
|
||||
|
||||
float EMC2101_get_chip_temp(void) {
|
||||
float EMC2101_get_chip_temp(void)
|
||||
{
|
||||
uint8_t temp_msb, temp_lsb;
|
||||
uint16_t reading;
|
||||
|
||||
|
||||
ESP_ERROR_CHECK(register_read(EMC2101_EXTERNAL_TEMP_MSB, &temp_msb, 1));
|
||||
ESP_ERROR_CHECK(register_read(EMC2101_EXTERNAL_TEMP_LSB, &temp_lsb, 1));
|
||||
|
||||
|
@ -3,47 +3,48 @@
|
||||
|
||||
#define EMC2101_I2CADDR_DEFAULT 0x4C ///< EMC2101 default i2c address
|
||||
#define EMC2101_CHIP_ID 0x16 ///< EMC2101 default device id from part id
|
||||
#define EMC2101_ALT_CHIP_ID 0x28 ///< EMC2101 alternate device id from part id
|
||||
#define EMC2101_WHOAMI 0xFD ///< Chip ID register
|
||||
#define EMC2101_ALT_CHIP_ID 0x28 ///< EMC2101 alternate device id from part id
|
||||
#define EMC2101_WHOAMI 0xFD ///< Chip ID register
|
||||
|
||||
#define EMC2101_INTERNAL_TEMP 0x00 ///< The internal temperature register
|
||||
#define EMC2101_INTERNAL_TEMP 0x00 ///< The internal temperature register
|
||||
#define EMC2101_EXTERNAL_TEMP_MSB 0x01 ///< high byte for the external temperature reading
|
||||
#define EMC2101_EXTERNAL_TEMP_LSB 0x10 ///< low byte for the external temperature reading
|
||||
|
||||
#define EMC2101_STATUS 0x02 ///< Status register
|
||||
#define EMC2101_REG_CONFIG 0x03 ///< configuration register
|
||||
#define EMC2101_REG_DATA_RATE 0x04 ///< Data rate config
|
||||
#define EMC2101_TEMP_FORCE 0x0C ///< Temp force setting for LUT testing
|
||||
#define EMC2101_TACH_LSB 0x46 ///< Tach RPM data low byte
|
||||
#define EMC2101_TACH_MSB 0x47 ///< Tach RPM data high byte
|
||||
#define EMC2101_TACH_LIMIT_LSB 0x48 ///< Tach low-speed setting low byte. INVERSE OF THE SPEED
|
||||
#define EMC2101_TACH_LIMIT_MSB 0x49 ///< Tach low-speed setting high byte. INVERSE OF THE SPEED
|
||||
#define EMC2101_FAN_CONFIG 0x4A ///< General fan config register
|
||||
#define EMC2101_FAN_SPINUP 0x4B ///< Fan spinup behavior settings
|
||||
#define EMC2101_STATUS 0x02 ///< Status register
|
||||
#define EMC2101_REG_CONFIG 0x03 ///< configuration register
|
||||
#define EMC2101_REG_DATA_RATE 0x04 ///< Data rate config
|
||||
#define EMC2101_TEMP_FORCE 0x0C ///< Temp force setting for LUT testing
|
||||
#define EMC2101_TACH_LSB 0x46 ///< Tach RPM data low byte
|
||||
#define EMC2101_TACH_MSB 0x47 ///< Tach RPM data high byte
|
||||
#define EMC2101_TACH_LIMIT_LSB 0x48 ///< Tach low-speed setting low byte. INVERSE OF THE SPEED
|
||||
#define EMC2101_TACH_LIMIT_MSB 0x49 ///< Tach low-speed setting high byte. INVERSE OF THE SPEED
|
||||
#define EMC2101_FAN_CONFIG 0x4A ///< General fan config register
|
||||
#define EMC2101_FAN_SPINUP 0x4B ///< Fan spinup behavior settings
|
||||
#define EMC2101_REG_FAN_SETTING 0x4C ///< Fan speed for non-LUT settings, as a % PWM duty cycle
|
||||
#define EMC2101_PWM_FREQ 0x4D ///< PWM frequency setting
|
||||
#define EMC2101_PWM_DIV 0x4E ///< PWM frequency divisor
|
||||
#define EMC2101_LUT_HYSTERESIS 0x4F ///< The hysteresis value for LUT lookups when temp is decreasing
|
||||
#define EMC2101_PWM_FREQ 0x4D ///< PWM frequency setting
|
||||
#define EMC2101_PWM_DIV 0x4E ///< PWM frequency divisor
|
||||
#define EMC2101_LUT_HYSTERESIS 0x4F ///< The hysteresis value for LUT lookups when temp is decreasing
|
||||
|
||||
#define EMC2101_LUT_START 0x50 ///< The first temp threshold register
|
||||
|
||||
#define EMC2101_TEMP_FILTER 0xBF ///< The external temperature sensor filtering behavior
|
||||
#define EMC2101_REG_PARTID 0xFD ///< 0x16
|
||||
#define EMC2101_REG_MFGID 0xFE ///< 0xFF16
|
||||
#define EMC2101_REG_PARTID 0xFD ///< 0x16
|
||||
#define EMC2101_REG_MFGID 0xFE ///< 0xFF16
|
||||
|
||||
#define MAX_LUT_SPEED 0x3F ///< 6-bit value
|
||||
#define MAX_LUT_TEMP 0x7F ///< 7-bit
|
||||
|
||||
#define EMC2101_I2C_ADDR 0x4C ///< The default I2C address
|
||||
#define EMC2101_FAN_RPM_NUMERATOR 5400000 ///< Conversion unit to convert LSBs to fan RPM
|
||||
#define _TEMP_LSB 0.125 ///< single bit value for internal temperature readings
|
||||
#define EMC2101_I2C_ADDR 0x4C ///< The default I2C address
|
||||
#define EMC2101_FAN_RPM_NUMERATOR 5400000 ///< Conversion unit to convert LSBs to fan RPM
|
||||
#define _TEMP_LSB 0.125 ///< single bit value for internal temperature readings
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* Allowed values for `setDataRate`.
|
||||
*/
|
||||
typedef enum {
|
||||
typedef enum
|
||||
{
|
||||
EMC2101_RATE_1_16_HZ, ///< 1_16_HZ
|
||||
EMC2101_RATE_1_8_HZ, ///< 1_8_HZ
|
||||
EMC2101_RATE_1_4_HZ, ///< 1_4_HZ
|
||||
@ -57,7 +58,7 @@ typedef enum {
|
||||
} emc2101_rate_t;
|
||||
|
||||
void EMC2101_set_fan_speed(float);
|
||||
//void EMC2101_read(void);
|
||||
// void EMC2101_read(void);
|
||||
uint16_t EMC2101_get_fan_speed(void);
|
||||
void EMC2101_init(void);
|
||||
float EMC2101_get_chip_temp(void);
|
||||
|
@ -4,20 +4,21 @@
|
||||
|
||||
#include "INA260.h"
|
||||
|
||||
#define I2C_MASTER_SCL_IO 48 /*!< GPIO number used for I2C master clock */
|
||||
#define I2C_MASTER_SDA_IO 47 /*!< GPIO number used for I2C master data */
|
||||
#define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
|
||||
#define I2C_MASTER_FREQ_HZ 400000 /*!< I2C master clock frequency */
|
||||
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
|
||||
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
|
||||
#define I2C_MASTER_TIMEOUT_MS 1000
|
||||
#define I2C_MASTER_SCL_IO 48 /*!< GPIO number used for I2C master clock */
|
||||
#define I2C_MASTER_SDA_IO 47 /*!< GPIO number used for I2C master data */
|
||||
#define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
|
||||
#define I2C_MASTER_FREQ_HZ 400000 /*!< I2C master clock frequency */
|
||||
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
|
||||
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
|
||||
#define I2C_MASTER_TIMEOUT_MS 1000
|
||||
|
||||
//static const char *TAG = "INA260.c";
|
||||
// static const char *TAG = "INA260.c";
|
||||
|
||||
/**
|
||||
* @brief Read a sequence of I2C bytes
|
||||
*/
|
||||
static esp_err_t register_read(uint8_t reg_addr, uint8_t *data, size_t len) {
|
||||
static esp_err_t register_read(uint8_t reg_addr, uint8_t *data, size_t len)
|
||||
{
|
||||
return i2c_master_write_read_device(I2C_MASTER_NUM, INA260_I2CADDR_DEFAULT, ®_addr, 1, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
@ -33,29 +34,32 @@ static esp_err_t register_read(uint8_t reg_addr, uint8_t *data, size_t len) {
|
||||
// return ret;
|
||||
// }
|
||||
|
||||
float INA260_read_current(void) {
|
||||
uint8_t data[2];
|
||||
|
||||
ESP_ERROR_CHECK(register_read(INA260_REG_CURRENT, data, 2));
|
||||
//ESP_LOGI(TAG, "Raw Current = %02X %02X", data[1], data[0]);
|
||||
|
||||
return (uint16_t)(data[1] | (data[0] << 8)) * 1.25;
|
||||
}
|
||||
|
||||
float INA260_read_voltage(void) {
|
||||
float INA260_read_current(void)
|
||||
{
|
||||
uint8_t data[2];
|
||||
|
||||
ESP_ERROR_CHECK(register_read(INA260_REG_BUSVOLTAGE, data, 2));
|
||||
//ESP_LOGI(TAG, "Raw Voltage = %02X %02X", data[1], data[0]);
|
||||
ESP_ERROR_CHECK(register_read(INA260_REG_CURRENT, data, 2));
|
||||
// ESP_LOGI(TAG, "Raw Current = %02X %02X", data[1], data[0]);
|
||||
|
||||
return (uint16_t)(data[1] | (data[0] << 8)) * 1.25;
|
||||
}
|
||||
|
||||
float INA260_read_power(void) {
|
||||
float INA260_read_voltage(void)
|
||||
{
|
||||
uint8_t data[2];
|
||||
|
||||
ESP_ERROR_CHECK(register_read(INA260_REG_BUSVOLTAGE, data, 2));
|
||||
// ESP_LOGI(TAG, "Raw Voltage = %02X %02X", data[1], data[0]);
|
||||
|
||||
return (uint16_t)(data[1] | (data[0] << 8)) * 1.25;
|
||||
}
|
||||
|
||||
float INA260_read_power(void)
|
||||
{
|
||||
uint8_t data[2];
|
||||
|
||||
ESP_ERROR_CHECK(register_read(INA260_REG_POWER, data, 2));
|
||||
//ESP_LOGI(TAG, "Raw Power = %02X %02X", data[1], data[0]);
|
||||
// ESP_LOGI(TAG, "Raw Power = %02X %02X", data[1], data[0]);
|
||||
|
||||
return (data[1] | (data[0] << 8)) * 10;
|
||||
}
|
@ -3,9 +3,9 @@
|
||||
|
||||
#define INA260_I2CADDR_DEFAULT 0x40 ///< INA260 default i2c address
|
||||
#define INA260_REG_CONFIG 0x00 ///< Configuration register
|
||||
#define INA260_REG_CURRENT 0x01 ///< Current measurement register (signed) in mA
|
||||
#define INA260_REG_BUSVOLTAGE 0x02 ///< Bus voltage measurement register in mV
|
||||
#define INA260_REG_POWER 0x03 ///< Power calculation register in mW
|
||||
#define INA260_REG_CURRENT 0x01 ///< Current measurement register (signed) in mA
|
||||
#define INA260_REG_BUSVOLTAGE 0x02 ///< Bus voltage measurement register in mV
|
||||
#define INA260_REG_POWER 0x03 ///< Power calculation register in mW
|
||||
#define INA260_REG_MASK_ENABLE 0x06 ///< Interrupt/Alert setting and checking register
|
||||
#define INA260_REG_ALERT_LIMIT 0x07 ///< Alert limit value register
|
||||
#define INA260_REG_MFG_UID 0xFE ///< Manufacturer ID Register
|
||||
@ -16,7 +16,8 @@
|
||||
*
|
||||
* Allowed values for setMode.
|
||||
*/
|
||||
typedef enum _mode {
|
||||
typedef enum _mode
|
||||
{
|
||||
INA260_MODE_SHUTDOWN = 0x00, /**< SHUTDOWN: Minimize quiescient current and
|
||||
turn off current into the device inputs. Set
|
||||
another mode to exit shutown mode **/
|
||||
@ -33,7 +34,8 @@ typedef enum _mode {
|
||||
*
|
||||
* Allowed values for setCurrentConversionTime and setVoltageConversionTime.
|
||||
*/
|
||||
typedef enum _conversion_time {
|
||||
typedef enum _conversion_time
|
||||
{
|
||||
INA260_TIME_140_us, ///< Measurement time: 140us
|
||||
INA260_TIME_204_us, ///< Measurement time: 204us
|
||||
INA260_TIME_332_us, ///< Measurement time: 332us
|
||||
@ -49,7 +51,8 @@ typedef enum _conversion_time {
|
||||
*
|
||||
* Allowed values forsetAveragingCount.
|
||||
*/
|
||||
typedef enum _count {
|
||||
typedef enum _count
|
||||
{
|
||||
INA260_COUNT_1, ///< Window size: 1 sample (Default)
|
||||
INA260_COUNT_4, ///< Window size: 4 samples
|
||||
INA260_COUNT_16, ///< Window size: 16 samples
|
||||
@ -65,7 +68,8 @@ typedef enum _count {
|
||||
*
|
||||
* Allowed values for setAlertType.
|
||||
*/
|
||||
typedef enum _alert_type {
|
||||
typedef enum _alert_type
|
||||
{
|
||||
INA260_ALERT_CONVERSION_READY = 0x1, ///< Trigger on conversion ready
|
||||
INA260_ALERT_OVERPOWER = 0x2, ///< Trigger on power over limit
|
||||
INA260_ALERT_UNDERVOLTAGE = 0x4, ///< Trigger on bus voltage under limit
|
||||
@ -80,8 +84,9 @@ typedef enum _alert_type {
|
||||
*
|
||||
* Allowed values for setAlertPolarity.
|
||||
*/
|
||||
typedef enum _alert_polarity {
|
||||
INA260_ALERT_POLARITY_NORMAL = 0x0, ///< Active high open-collector (Default)
|
||||
typedef enum _alert_polarity
|
||||
{
|
||||
INA260_ALERT_POLARITY_NORMAL = 0x0, ///< Active high open-collector (Default)
|
||||
INA260_ALERT_POLARITY_INVERTED = 0x1, ///< Active low open-collector
|
||||
} INA260_AlertPolarity;
|
||||
|
||||
@ -90,14 +95,14 @@ typedef enum _alert_polarity {
|
||||
*
|
||||
* Allowed values for setAlertLatch.
|
||||
*/
|
||||
typedef enum _alert_latch {
|
||||
typedef enum _alert_latch
|
||||
{
|
||||
INA260_ALERT_LATCH_ENABLED = 0x1, /**< Alert will latch until Mask/Enable
|
||||
register is read **/
|
||||
INA260_ALERT_LATCH_TRANSPARENT = 0x0, /**< Alert will reset when fault is
|
||||
cleared **/
|
||||
} INA260_AlertLatch;
|
||||
|
||||
|
||||
float INA260_read_current(void);
|
||||
float INA260_read_voltage(void);
|
||||
float INA260_read_power(void);
|
||||
|
12
main/adc.c
12
main/adc.c
@ -1,17 +1,19 @@
|
||||
#include "driver/adc.h"
|
||||
#include "esp_adc_cal.h"
|
||||
|
||||
//static const char *TAG = "adc.c";
|
||||
// static const char *TAG = "adc.c";
|
||||
static esp_adc_cal_characteristics_t adc1_chars;
|
||||
|
||||
//Sets up the ADC to read Vcore. Run this before ADC_get_vcore()
|
||||
void ADC_init(void) {
|
||||
// Sets up the ADC to read Vcore. Run this before ADC_get_vcore()
|
||||
void ADC_init(void)
|
||||
{
|
||||
adc1_config_channel_atten(ADC1_CHANNEL_1, ADC_ATTEN_DB_11);
|
||||
esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_DEFAULT, 0, &adc1_chars);
|
||||
}
|
||||
|
||||
//returns the ADC voltage in mV
|
||||
uint16_t ADC_get_vcore(void) {
|
||||
// returns the ADC voltage in mV
|
||||
uint16_t ADC_get_vcore(void)
|
||||
{
|
||||
adc1_config_width(ADC_WIDTH_BIT_DEFAULT);
|
||||
return esp_adc_cal_raw_to_voltage(adc1_get_raw(ADC1_CHANNEL_1), &adc1_chars);
|
||||
}
|
96
main/fonts.c
96
main/fonts.c
@ -1,50 +1,50 @@
|
||||
|
||||
// 5x7 font (in 6x8 cell)
|
||||
unsigned char ucSmallFont[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x45,0x51,0x45,0x3e,0x00,0x3e,0x6b,0x6f,
|
||||
0x6b,0x3e,0x00,0x1c,0x3e,0x7c,0x3e,0x1c,0x00,0x18,0x3c,0x7e,0x3c,0x18,0x00,0x30,
|
||||
0x36,0x7f,0x36,0x30,0x00,0x18,0x5c,0x7e,0x5c,0x18,0x00,0x00,0x18,0x18,0x00,0x00,
|
||||
0x00,0xff,0xe7,0xe7,0xff,0xff,0x00,0x3c,0x24,0x24,0x3c,0x00,0x00,0xc3,0xdb,0xdb,
|
||||
0xc3,0xff,0x00,0x30,0x48,0x4a,0x36,0x0e,0x00,0x06,0x29,0x79,0x29,0x06,0x00,0x60,
|
||||
0x70,0x3f,0x02,0x04,0x00,0x60,0x7e,0x0a,0x35,0x3f,0x00,0x2a,0x1c,0x36,0x1c,0x2a,
|
||||
0x00,0x00,0x7f,0x3e,0x1c,0x08,0x00,0x08,0x1c,0x3e,0x7f,0x00,0x00,0x14,0x36,0x7f,
|
||||
0x36,0x14,0x00,0x00,0x5f,0x00,0x5f,0x00,0x00,0x06,0x09,0x7f,0x01,0x7f,0x00,0x22,
|
||||
0x4d,0x55,0x59,0x22,0x00,0x60,0x60,0x60,0x60,0x00,0x00,0x14,0xb6,0xff,0xb6,0x14,
|
||||
0x00,0x04,0x06,0x7f,0x06,0x04,0x00,0x10,0x30,0x7f,0x30,0x10,0x00,0x08,0x08,0x3e,
|
||||
0x1c,0x08,0x00,0x08,0x1c,0x3e,0x08,0x08,0x00,0x78,0x40,0x40,0x40,0x40,0x00,0x08,
|
||||
0x3e,0x08,0x3e,0x08,0x00,0x30,0x3c,0x3f,0x3c,0x30,0x00,0x03,0x0f,0x3f,0x0f,0x03,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x5f,0x06,0x00,0x00,0x07,0x03,0x00,
|
||||
0x07,0x03,0x00,0x24,0x7e,0x24,0x7e,0x24,0x00,0x24,0x2b,0x6a,0x12,0x00,0x00,0x63,
|
||||
0x13,0x08,0x64,0x63,0x00,0x36,0x49,0x56,0x20,0x50,0x00,0x00,0x07,0x03,0x00,0x00,
|
||||
0x00,0x00,0x3e,0x41,0x00,0x00,0x00,0x00,0x41,0x3e,0x00,0x00,0x00,0x08,0x3e,0x1c,
|
||||
0x3e,0x08,0x00,0x08,0x08,0x3e,0x08,0x08,0x00,0x00,0xe0,0x60,0x00,0x00,0x00,0x08,
|
||||
0x08,0x08,0x08,0x08,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,
|
||||
0x00,0x3e,0x51,0x49,0x45,0x3e,0x00,0x00,0x42,0x7f,0x40,0x00,0x00,0x62,0x51,0x49,
|
||||
0x49,0x46,0x00,0x22,0x49,0x49,0x49,0x36,0x00,0x18,0x14,0x12,0x7f,0x10,0x00,0x2f,
|
||||
0x49,0x49,0x49,0x31,0x00,0x3c,0x4a,0x49,0x49,0x30,0x00,0x01,0x71,0x09,0x05,0x03,
|
||||
0x00,0x36,0x49,0x49,0x49,0x36,0x00,0x06,0x49,0x49,0x29,0x1e,0x00,0x00,0x6c,0x6c,
|
||||
0x00,0x00,0x00,0x00,0xec,0x6c,0x00,0x00,0x00,0x08,0x14,0x22,0x41,0x00,0x00,0x24,
|
||||
0x24,0x24,0x24,0x24,0x00,0x00,0x41,0x22,0x14,0x08,0x00,0x02,0x01,0x59,0x09,0x06,
|
||||
0x00,0x3e,0x41,0x5d,0x55,0x1e,0x00,0x7e,0x11,0x11,0x11,0x7e,0x00,0x7f,0x49,0x49,
|
||||
0x49,0x36,0x00,0x3e,0x41,0x41,0x41,0x22,0x00,0x7f,0x41,0x41,0x41,0x3e,0x00,0x7f,
|
||||
0x49,0x49,0x49,0x41,0x00,0x7f,0x09,0x09,0x09,0x01,0x00,0x3e,0x41,0x49,0x49,0x7a,
|
||||
0x00,0x7f,0x08,0x08,0x08,0x7f,0x00,0x00,0x41,0x7f,0x41,0x00,0x00,0x30,0x40,0x40,
|
||||
0x40,0x3f,0x00,0x7f,0x08,0x14,0x22,0x41,0x00,0x7f,0x40,0x40,0x40,0x40,0x00,0x7f,
|
||||
0x02,0x04,0x02,0x7f,0x00,0x7f,0x02,0x04,0x08,0x7f,0x00,0x3e,0x41,0x41,0x41,0x3e,
|
||||
0x00,0x7f,0x09,0x09,0x09,0x06,0x00,0x3e,0x41,0x51,0x21,0x5e,0x00,0x7f,0x09,0x09,
|
||||
0x19,0x66,0x00,0x26,0x49,0x49,0x49,0x32,0x00,0x01,0x01,0x7f,0x01,0x01,0x00,0x3f,
|
||||
0x40,0x40,0x40,0x3f,0x00,0x1f,0x20,0x40,0x20,0x1f,0x00,0x3f,0x40,0x3c,0x40,0x3f,
|
||||
0x00,0x63,0x14,0x08,0x14,0x63,0x00,0x07,0x08,0x70,0x08,0x07,0x00,0x71,0x49,0x45,
|
||||
0x43,0x00,0x00,0x00,0x7f,0x41,0x41,0x00,0x00,0x02,0x04,0x08,0x10,0x20,0x00,0x00,
|
||||
0x41,0x41,0x7f,0x00,0x00,0x04,0x02,0x01,0x02,0x04,0x00,0x80,0x80,0x80,0x80,0x80,
|
||||
0x00,0x00,0x03,0x07,0x00,0x00,0x00,0x20,0x54,0x54,0x54,0x78,0x00,0x7f,0x44,0x44,
|
||||
0x44,0x38,0x00,0x38,0x44,0x44,0x44,0x28,0x00,0x38,0x44,0x44,0x44,0x7f,0x00,0x38,
|
||||
0x54,0x54,0x54,0x08,0x00,0x08,0x7e,0x09,0x09,0x00,0x00,0x18,0xa4,0xa4,0xa4,0x7c,
|
||||
0x00,0x7f,0x04,0x04,0x78,0x00,0x00,0x00,0x00,0x7d,0x40,0x00,0x00,0x40,0x80,0x84,
|
||||
0x7d,0x00,0x00,0x7f,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x7f,0x40,0x00,0x00,0x7c,
|
||||
0x04,0x18,0x04,0x78,0x00,0x7c,0x04,0x04,0x78,0x00,0x00,0x38,0x44,0x44,0x44,0x38,
|
||||
0x00,0xfc,0x44,0x44,0x44,0x38,0x00,0x38,0x44,0x44,0x44,0xfc,0x00,0x44,0x78,0x44,
|
||||
0x04,0x08,0x00,0x08,0x54,0x54,0x54,0x20,0x00,0x04,0x3e,0x44,0x24,0x00,0x00,0x3c,
|
||||
0x40,0x20,0x7c,0x00,0x00,0x1c,0x20,0x40,0x20,0x1c,0x00,0x3c,0x60,0x30,0x60,0x3c,
|
||||
0x00,0x6c,0x10,0x10,0x6c,0x00,0x00,0x9c,0xa0,0x60,0x3c,0x00,0x00,0x64,0x54,0x54,
|
||||
0x4c,0x00,0x00,0x08,0x3e,0x41,0x41,0x00,0x00,0x00,0x00,0x77,0x00,0x00,0x00,0x00,
|
||||
0x41,0x41,0x3e,0x08,0x00,0x02,0x01,0x02,0x01,0x00,0x00,0x3c,0x26,0x23,0x26,0x3c};
|
||||
unsigned char ucSmallFont[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x45, 0x51, 0x45, 0x3e, 0x00, 0x3e, 0x6b, 0x6f,
|
||||
0x6b, 0x3e, 0x00, 0x1c, 0x3e, 0x7c, 0x3e, 0x1c, 0x00, 0x18, 0x3c, 0x7e, 0x3c, 0x18, 0x00, 0x30,
|
||||
0x36, 0x7f, 0x36, 0x30, 0x00, 0x18, 0x5c, 0x7e, 0x5c, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
|
||||
0x00, 0xff, 0xe7, 0xe7, 0xff, 0xff, 0x00, 0x3c, 0x24, 0x24, 0x3c, 0x00, 0x00, 0xc3, 0xdb, 0xdb,
|
||||
0xc3, 0xff, 0x00, 0x30, 0x48, 0x4a, 0x36, 0x0e, 0x00, 0x06, 0x29, 0x79, 0x29, 0x06, 0x00, 0x60,
|
||||
0x70, 0x3f, 0x02, 0x04, 0x00, 0x60, 0x7e, 0x0a, 0x35, 0x3f, 0x00, 0x2a, 0x1c, 0x36, 0x1c, 0x2a,
|
||||
0x00, 0x00, 0x7f, 0x3e, 0x1c, 0x08, 0x00, 0x08, 0x1c, 0x3e, 0x7f, 0x00, 0x00, 0x14, 0x36, 0x7f,
|
||||
0x36, 0x14, 0x00, 0x00, 0x5f, 0x00, 0x5f, 0x00, 0x00, 0x06, 0x09, 0x7f, 0x01, 0x7f, 0x00, 0x22,
|
||||
0x4d, 0x55, 0x59, 0x22, 0x00, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x14, 0xb6, 0xff, 0xb6, 0x14,
|
||||
0x00, 0x04, 0x06, 0x7f, 0x06, 0x04, 0x00, 0x10, 0x30, 0x7f, 0x30, 0x10, 0x00, 0x08, 0x08, 0x3e,
|
||||
0x1c, 0x08, 0x00, 0x08, 0x1c, 0x3e, 0x08, 0x08, 0x00, 0x78, 0x40, 0x40, 0x40, 0x40, 0x00, 0x08,
|
||||
0x3e, 0x08, 0x3e, 0x08, 0x00, 0x30, 0x3c, 0x3f, 0x3c, 0x30, 0x00, 0x03, 0x0f, 0x3f, 0x0f, 0x03,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x5f, 0x06, 0x00, 0x00, 0x07, 0x03, 0x00,
|
||||
0x07, 0x03, 0x00, 0x24, 0x7e, 0x24, 0x7e, 0x24, 0x00, 0x24, 0x2b, 0x6a, 0x12, 0x00, 0x00, 0x63,
|
||||
0x13, 0x08, 0x64, 0x63, 0x00, 0x36, 0x49, 0x56, 0x20, 0x50, 0x00, 0x00, 0x07, 0x03, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3e, 0x41, 0x00, 0x00, 0x00, 0x00, 0x41, 0x3e, 0x00, 0x00, 0x00, 0x08, 0x3e, 0x1c,
|
||||
0x3e, 0x08, 0x00, 0x08, 0x08, 0x3e, 0x08, 0x08, 0x00, 0x00, 0xe0, 0x60, 0x00, 0x00, 0x00, 0x08,
|
||||
0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02,
|
||||
0x00, 0x3e, 0x51, 0x49, 0x45, 0x3e, 0x00, 0x00, 0x42, 0x7f, 0x40, 0x00, 0x00, 0x62, 0x51, 0x49,
|
||||
0x49, 0x46, 0x00, 0x22, 0x49, 0x49, 0x49, 0x36, 0x00, 0x18, 0x14, 0x12, 0x7f, 0x10, 0x00, 0x2f,
|
||||
0x49, 0x49, 0x49, 0x31, 0x00, 0x3c, 0x4a, 0x49, 0x49, 0x30, 0x00, 0x01, 0x71, 0x09, 0x05, 0x03,
|
||||
0x00, 0x36, 0x49, 0x49, 0x49, 0x36, 0x00, 0x06, 0x49, 0x49, 0x29, 0x1e, 0x00, 0x00, 0x6c, 0x6c,
|
||||
0x00, 0x00, 0x00, 0x00, 0xec, 0x6c, 0x00, 0x00, 0x00, 0x08, 0x14, 0x22, 0x41, 0x00, 0x00, 0x24,
|
||||
0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x41, 0x22, 0x14, 0x08, 0x00, 0x02, 0x01, 0x59, 0x09, 0x06,
|
||||
0x00, 0x3e, 0x41, 0x5d, 0x55, 0x1e, 0x00, 0x7e, 0x11, 0x11, 0x11, 0x7e, 0x00, 0x7f, 0x49, 0x49,
|
||||
0x49, 0x36, 0x00, 0x3e, 0x41, 0x41, 0x41, 0x22, 0x00, 0x7f, 0x41, 0x41, 0x41, 0x3e, 0x00, 0x7f,
|
||||
0x49, 0x49, 0x49, 0x41, 0x00, 0x7f, 0x09, 0x09, 0x09, 0x01, 0x00, 0x3e, 0x41, 0x49, 0x49, 0x7a,
|
||||
0x00, 0x7f, 0x08, 0x08, 0x08, 0x7f, 0x00, 0x00, 0x41, 0x7f, 0x41, 0x00, 0x00, 0x30, 0x40, 0x40,
|
||||
0x40, 0x3f, 0x00, 0x7f, 0x08, 0x14, 0x22, 0x41, 0x00, 0x7f, 0x40, 0x40, 0x40, 0x40, 0x00, 0x7f,
|
||||
0x02, 0x04, 0x02, 0x7f, 0x00, 0x7f, 0x02, 0x04, 0x08, 0x7f, 0x00, 0x3e, 0x41, 0x41, 0x41, 0x3e,
|
||||
0x00, 0x7f, 0x09, 0x09, 0x09, 0x06, 0x00, 0x3e, 0x41, 0x51, 0x21, 0x5e, 0x00, 0x7f, 0x09, 0x09,
|
||||
0x19, 0x66, 0x00, 0x26, 0x49, 0x49, 0x49, 0x32, 0x00, 0x01, 0x01, 0x7f, 0x01, 0x01, 0x00, 0x3f,
|
||||
0x40, 0x40, 0x40, 0x3f, 0x00, 0x1f, 0x20, 0x40, 0x20, 0x1f, 0x00, 0x3f, 0x40, 0x3c, 0x40, 0x3f,
|
||||
0x00, 0x63, 0x14, 0x08, 0x14, 0x63, 0x00, 0x07, 0x08, 0x70, 0x08, 0x07, 0x00, 0x71, 0x49, 0x45,
|
||||
0x43, 0x00, 0x00, 0x00, 0x7f, 0x41, 0x41, 0x00, 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00,
|
||||
0x41, 0x41, 0x7f, 0x00, 0x00, 0x04, 0x02, 0x01, 0x02, 0x04, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x00, 0x20, 0x54, 0x54, 0x54, 0x78, 0x00, 0x7f, 0x44, 0x44,
|
||||
0x44, 0x38, 0x00, 0x38, 0x44, 0x44, 0x44, 0x28, 0x00, 0x38, 0x44, 0x44, 0x44, 0x7f, 0x00, 0x38,
|
||||
0x54, 0x54, 0x54, 0x08, 0x00, 0x08, 0x7e, 0x09, 0x09, 0x00, 0x00, 0x18, 0xa4, 0xa4, 0xa4, 0x7c,
|
||||
0x00, 0x7f, 0x04, 0x04, 0x78, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x40, 0x00, 0x00, 0x40, 0x80, 0x84,
|
||||
0x7d, 0x00, 0x00, 0x7f, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x40, 0x00, 0x00, 0x7c,
|
||||
0x04, 0x18, 0x04, 0x78, 0x00, 0x7c, 0x04, 0x04, 0x78, 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38,
|
||||
0x00, 0xfc, 0x44, 0x44, 0x44, 0x38, 0x00, 0x38, 0x44, 0x44, 0x44, 0xfc, 0x00, 0x44, 0x78, 0x44,
|
||||
0x04, 0x08, 0x00, 0x08, 0x54, 0x54, 0x54, 0x20, 0x00, 0x04, 0x3e, 0x44, 0x24, 0x00, 0x00, 0x3c,
|
||||
0x40, 0x20, 0x7c, 0x00, 0x00, 0x1c, 0x20, 0x40, 0x20, 0x1c, 0x00, 0x3c, 0x60, 0x30, 0x60, 0x3c,
|
||||
0x00, 0x6c, 0x10, 0x10, 0x6c, 0x00, 0x00, 0x9c, 0xa0, 0x60, 0x3c, 0x00, 0x00, 0x64, 0x54, 0x54,
|
||||
0x4c, 0x00, 0x00, 0x08, 0x3e, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x00,
|
||||
0x41, 0x41, 0x3e, 0x08, 0x00, 0x02, 0x01, 0x02, 0x01, 0x00, 0x00, 0x3c, 0x26, 0x23, 0x26, 0x3c};
|
||||
|
@ -13,15 +13,17 @@
|
||||
|
||||
#define STRATUM_USER CONFIG_STRATUM_USER
|
||||
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
void (*init_fn)(u_int64_t);
|
||||
task_result * (*receive_result_fn)(void *GLOBAL_STATE);
|
||||
task_result *(*receive_result_fn)(void *GLOBAL_STATE);
|
||||
int (*set_max_baud_fn)(void);
|
||||
void (*set_difficulty_mask_fn)(int);
|
||||
void (*send_work_fn)(void *GLOBAL_STATE, bm_job *next_bm_job);
|
||||
} AsicFunctions;
|
||||
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
AsicFunctions ASIC_functions;
|
||||
double asic_job_frequency_ms;
|
||||
|
||||
@ -33,13 +35,11 @@ typedef struct {
|
||||
AsicTaskModule ASIC_TASK_MODULE;
|
||||
PowerManagementModule POWER_MANAGEMENT_MODULE;
|
||||
|
||||
|
||||
|
||||
char * extranonce_str;
|
||||
char *extranonce_str;
|
||||
int extranonce_2_len;
|
||||
int abandon_work;
|
||||
|
||||
uint8_t * valid_jobs;
|
||||
uint8_t *valid_jobs;
|
||||
pthread_mutex_t valid_jobs_lock;
|
||||
|
||||
uint32_t stratum_difficulty;
|
||||
@ -47,11 +47,6 @@ typedef struct {
|
||||
|
||||
int sock;
|
||||
|
||||
|
||||
} GlobalState;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* GLOBAL_STATE_H_ */
|
@ -33,44 +33,48 @@ static const char *TAG = "http_server";
|
||||
|
||||
static GlobalState *GLOBAL_STATE;
|
||||
|
||||
|
||||
#define REST_CHECK(a, str, goto_tag, ...) \
|
||||
do \
|
||||
{ \
|
||||
if (!(a)) \
|
||||
{ \
|
||||
#define REST_CHECK(a, str, goto_tag, ...) \
|
||||
do \
|
||||
{ \
|
||||
if (!(a)) \
|
||||
{ \
|
||||
ESP_LOGE(TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
|
||||
goto goto_tag; \
|
||||
} \
|
||||
goto goto_tag; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define FILE_PATH_MAX (ESP_VFS_PATH_MAX + 128)
|
||||
#define SCRATCH_BUFSIZE (10240)
|
||||
|
||||
typedef struct rest_server_context {
|
||||
typedef struct rest_server_context
|
||||
{
|
||||
char base_path[ESP_VFS_PATH_MAX + 1];
|
||||
char scratch[SCRATCH_BUFSIZE];
|
||||
} rest_server_context_t;
|
||||
|
||||
#define CHECK_FILE_EXTENSION(filename, ext) (strcasecmp(&filename[strlen(filename) - strlen(ext)], ext) == 0)
|
||||
|
||||
|
||||
esp_err_t init_fs(void)
|
||||
{
|
||||
esp_vfs_spiffs_conf_t conf = {
|
||||
.base_path = "",
|
||||
.partition_label = NULL,
|
||||
.max_files = 5,
|
||||
.format_if_mount_failed = false
|
||||
};
|
||||
.format_if_mount_failed = false};
|
||||
esp_err_t ret = esp_vfs_spiffs_register(&conf);
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
if (ret == ESP_FAIL) {
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
if (ret == ESP_FAIL)
|
||||
{
|
||||
ESP_LOGE(TAG, "Failed to mount or format filesystem");
|
||||
} else if (ret == ESP_ERR_NOT_FOUND) {
|
||||
}
|
||||
else if (ret == ESP_ERR_NOT_FOUND)
|
||||
{
|
||||
ESP_LOGE(TAG, "Failed to find SPIFFS partition");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret));
|
||||
}
|
||||
return ESP_FAIL;
|
||||
@ -78,9 +82,12 @@ esp_err_t init_fs(void)
|
||||
|
||||
size_t total = 0, used = 0;
|
||||
ret = esp_spiffs_info(NULL, &total, &used);
|
||||
if (ret != ESP_OK) {
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "Failed to get SPIFFS partition information (%s)", esp_err_to_name(ret));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used);
|
||||
}
|
||||
return ESP_OK;
|
||||
@ -89,7 +96,8 @@ esp_err_t init_fs(void)
|
||||
/* Function for stopping the webserver */
|
||||
void stop_webserver(httpd_handle_t server)
|
||||
{
|
||||
if (server) {
|
||||
if (server)
|
||||
{
|
||||
/* Stop the httpd server */
|
||||
httpd_stop(server);
|
||||
}
|
||||
@ -99,17 +107,28 @@ void stop_webserver(httpd_handle_t server)
|
||||
static esp_err_t set_content_type_from_file(httpd_req_t *req, const char *filepath)
|
||||
{
|
||||
const char *type = "text/plain";
|
||||
if (CHECK_FILE_EXTENSION(filepath, ".html")) {
|
||||
if (CHECK_FILE_EXTENSION(filepath, ".html"))
|
||||
{
|
||||
type = "text/html";
|
||||
} else if (CHECK_FILE_EXTENSION(filepath, ".js")) {
|
||||
}
|
||||
else if (CHECK_FILE_EXTENSION(filepath, ".js"))
|
||||
{
|
||||
type = "application/javascript";
|
||||
} else if (CHECK_FILE_EXTENSION(filepath, ".css")) {
|
||||
}
|
||||
else if (CHECK_FILE_EXTENSION(filepath, ".css"))
|
||||
{
|
||||
type = "text/css";
|
||||
} else if (CHECK_FILE_EXTENSION(filepath, ".png")) {
|
||||
}
|
||||
else if (CHECK_FILE_EXTENSION(filepath, ".png"))
|
||||
{
|
||||
type = "image/png";
|
||||
} else if (CHECK_FILE_EXTENSION(filepath, ".ico")) {
|
||||
}
|
||||
else if (CHECK_FILE_EXTENSION(filepath, ".ico"))
|
||||
{
|
||||
type = "image/x-icon";
|
||||
} else if (CHECK_FILE_EXTENSION(filepath, ".svg")) {
|
||||
}
|
||||
else if (CHECK_FILE_EXTENSION(filepath, ".svg"))
|
||||
{
|
||||
type = "text/xml";
|
||||
}
|
||||
return httpd_resp_set_type(req, type);
|
||||
@ -122,13 +141,17 @@ static esp_err_t rest_common_get_handler(httpd_req_t *req)
|
||||
|
||||
rest_server_context_t *rest_context = (rest_server_context_t *)req->user_ctx;
|
||||
strlcpy(filepath, rest_context->base_path, sizeof(filepath));
|
||||
if (req->uri[strlen(req->uri) - 1] == '/') {
|
||||
if (req->uri[strlen(req->uri) - 1] == '/')
|
||||
{
|
||||
strlcat(filepath, "/index.html", sizeof(filepath));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
strlcat(filepath, req->uri, sizeof(filepath));
|
||||
}
|
||||
int fd = open(filepath, O_RDONLY, 0);
|
||||
if (fd == -1) {
|
||||
if (fd == -1)
|
||||
{
|
||||
ESP_LOGE(TAG, "Failed to open file : %s", filepath);
|
||||
/* Respond with 500 Internal Server Error */
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to read existing file");
|
||||
@ -139,14 +162,19 @@ static esp_err_t rest_common_get_handler(httpd_req_t *req)
|
||||
|
||||
char *chunk = rest_context->scratch;
|
||||
ssize_t read_bytes;
|
||||
do {
|
||||
do
|
||||
{
|
||||
/* Read file in chunks into the scratch buffer */
|
||||
read_bytes = read(fd, chunk, SCRATCH_BUFSIZE);
|
||||
if (read_bytes == -1) {
|
||||
if (read_bytes == -1)
|
||||
{
|
||||
ESP_LOGE(TAG, "Failed to read file : %s", filepath);
|
||||
} else if (read_bytes > 0) {
|
||||
}
|
||||
else if (read_bytes > 0)
|
||||
{
|
||||
/* Send the buffer contents as HTTP response chunk */
|
||||
if (httpd_resp_send_chunk(req, chunk, read_bytes) != ESP_OK) {
|
||||
if (httpd_resp_send_chunk(req, chunk, read_bytes) != ESP_OK)
|
||||
{
|
||||
close(fd);
|
||||
ESP_LOGE(TAG, "File sending failed!");
|
||||
/* Abort sending file */
|
||||
@ -165,21 +193,23 @@ static esp_err_t rest_common_get_handler(httpd_req_t *req)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
static esp_err_t PATCH_update_settings(httpd_req_t *req)
|
||||
{
|
||||
int total_len = req->content_len;
|
||||
int cur_len = 0;
|
||||
char *buf = ((rest_server_context_t *)(req->user_ctx))->scratch;
|
||||
int received = 0;
|
||||
if (total_len >= SCRATCH_BUFSIZE) {
|
||||
if (total_len >= SCRATCH_BUFSIZE)
|
||||
{
|
||||
/* Respond with 500 Internal Server Error */
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "content too long");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
while (cur_len < total_len) {
|
||||
while (cur_len < total_len)
|
||||
{
|
||||
received = httpd_req_recv(req, buf + cur_len, total_len);
|
||||
if (received <= 0) {
|
||||
if (received <= 0)
|
||||
{
|
||||
/* Respond with 500 Internal Server Error */
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to post control value");
|
||||
return ESP_FAIL;
|
||||
@ -195,7 +225,6 @@ static esp_err_t PATCH_update_settings(httpd_req_t *req)
|
||||
char *ssid = cJSON_GetObjectItem(root, "ssid")->valuestring;
|
||||
char *wifiPass = cJSON_GetObjectItem(root, "wifiPass")->valuestring;
|
||||
|
||||
|
||||
nvs_config_set_string(NVS_CONFIG_STRATUM_URL, stratumURL);
|
||||
nvs_config_set_string(NVS_CONFIG_STRATUM_USER, stratumUser);
|
||||
nvs_config_set_u16(NVS_CONFIG_STRATUM_PORT, stratumPort);
|
||||
@ -207,7 +236,6 @@ static esp_err_t PATCH_update_settings(httpd_req_t *req)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
static esp_err_t POST_restart(httpd_req_t *req)
|
||||
{
|
||||
esp_restart();
|
||||
@ -234,16 +262,16 @@ static esp_err_t GET_system_info(httpd_req_t *req)
|
||||
cJSON_AddStringToObject(root, "bestDiff", GLOBAL_STATE->SYSTEM_MODULE.best_diff_string);
|
||||
cJSON_AddNumberToObject(root, "freeHeap", esp_get_free_heap_size());
|
||||
cJSON_AddNumberToObject(root, "coreVoltage", ADC_get_vcore());
|
||||
cJSON_AddStringToObject(root, "ssid", nvs_config_get_string(NVS_CONFIG_WIFI_SSID, CONFIG_ESP_WIFI_SSID));
|
||||
cJSON_AddStringToObject(root, "ssid", nvs_config_get_string(NVS_CONFIG_WIFI_SSID, CONFIG_ESP_WIFI_SSID));
|
||||
cJSON_AddStringToObject(root, "wifiPass", nvs_config_get_string(NVS_CONFIG_WIFI_PASS, CONFIG_ESP_WIFI_PASSWORD));
|
||||
cJSON_AddStringToObject(root, "wifiStatus", GLOBAL_STATE->SYSTEM_MODULE.wifi_status);
|
||||
cJSON_AddNumberToObject(root, "sharesAccepted", GLOBAL_STATE->SYSTEM_MODULE.shares_accepted);
|
||||
cJSON_AddNumberToObject(root, "sharesRejected", GLOBAL_STATE->SYSTEM_MODULE.shares_rejected);
|
||||
cJSON_AddNumberToObject(root, "uptimeSeconds", (esp_timer_get_time() - GLOBAL_STATE->SYSTEM_MODULE.start_time)/1000000);
|
||||
cJSON_AddNumberToObject(root, "uptimeSeconds", (esp_timer_get_time() - GLOBAL_STATE->SYSTEM_MODULE.start_time) / 1000000);
|
||||
cJSON_AddStringToObject(root, "ASICModel", CONFIG_ASIC_MODEL);
|
||||
cJSON_AddStringToObject(root, "stratumURL", nvs_config_get_string(NVS_CONFIG_STRATUM_URL, CONFIG_STRATUM_URL));
|
||||
cJSON_AddNumberToObject(root, "stratumPort", nvs_config_get_u16(NVS_CONFIG_STRATUM_PORT, CONFIG_STRATUM_PORT));
|
||||
cJSON_AddStringToObject(root, "stratumUser", nvs_config_get_string(NVS_CONFIG_STRATUM_USER, CONFIG_STRATUM_USER));
|
||||
cJSON_AddStringToObject(root, "stratumURL", nvs_config_get_string(NVS_CONFIG_STRATUM_URL, CONFIG_STRATUM_URL));
|
||||
cJSON_AddNumberToObject(root, "stratumPort", nvs_config_get_u16(NVS_CONFIG_STRATUM_PORT, CONFIG_STRATUM_PORT));
|
||||
cJSON_AddStringToObject(root, "stratumUser", nvs_config_get_string(NVS_CONFIG_STRATUM_USER, CONFIG_STRATUM_USER));
|
||||
|
||||
const char *sys_info = cJSON_Print(root);
|
||||
httpd_resp_sendstr(req, sys_info);
|
||||
@ -258,7 +286,8 @@ esp_err_t POST_WWW_update(httpd_req_t *req)
|
||||
int remaining = req->content_len;
|
||||
|
||||
const esp_partition_t *www_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_SPIFFS, "www");
|
||||
if (www_partition == NULL) {
|
||||
if (www_partition == NULL)
|
||||
{
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "WWW partition not found");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
@ -266,17 +295,22 @@ esp_err_t POST_WWW_update(httpd_req_t *req)
|
||||
// Erase the entire www partition before writing
|
||||
ESP_ERROR_CHECK(esp_partition_erase_range(www_partition, 0, www_partition->size));
|
||||
|
||||
while (remaining > 0) {
|
||||
while (remaining > 0)
|
||||
{
|
||||
int recv_len = httpd_req_recv(req, buf, MIN(remaining, sizeof(buf)));
|
||||
|
||||
if (recv_len == HTTPD_SOCK_ERR_TIMEOUT) {
|
||||
if (recv_len == HTTPD_SOCK_ERR_TIMEOUT)
|
||||
{
|
||||
continue;
|
||||
} else if (recv_len <= 0) {
|
||||
}
|
||||
else if (recv_len <= 0)
|
||||
{
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Protocol Error");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (esp_partition_write(www_partition, www_partition->size - remaining, (const void *)buf, recv_len) != ESP_OK) {
|
||||
if (esp_partition_write(www_partition, www_partition->size - remaining, (const void *)buf, recv_len) != ESP_OK)
|
||||
{
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Write Error");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
@ -300,21 +334,26 @@ esp_err_t POST_OTA_update(httpd_req_t *req)
|
||||
const esp_partition_t *ota_partition = esp_ota_get_next_update_partition(NULL);
|
||||
ESP_ERROR_CHECK(esp_ota_begin(ota_partition, OTA_SIZE_UNKNOWN, &ota_handle));
|
||||
|
||||
while (remaining > 0) {
|
||||
while (remaining > 0)
|
||||
{
|
||||
int recv_len = httpd_req_recv(req, buf, MIN(remaining, sizeof(buf)));
|
||||
|
||||
// Timeout Error: Just retry
|
||||
if (recv_len == HTTPD_SOCK_ERR_TIMEOUT) {
|
||||
if (recv_len == HTTPD_SOCK_ERR_TIMEOUT)
|
||||
{
|
||||
continue;
|
||||
|
||||
// Serious Error: Abort OTA
|
||||
} else if (recv_len <= 0) {
|
||||
// Serious Error: Abort OTA
|
||||
}
|
||||
else if (recv_len <= 0)
|
||||
{
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Protocol Error");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// Successful Upload: Flash firmware chunk
|
||||
if (esp_ota_write(ota_handle, (const void *)buf, recv_len) != ESP_OK) {
|
||||
if (esp_ota_write(ota_handle, (const void *)buf, recv_len) != ESP_OK)
|
||||
{
|
||||
esp_ota_abort(ota_handle);
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Flash Error");
|
||||
return ESP_FAIL;
|
||||
@ -324,7 +363,8 @@ esp_err_t POST_OTA_update(httpd_req_t *req)
|
||||
}
|
||||
|
||||
// Validate and switch to new OTA image and reboot
|
||||
if (esp_ota_end(ota_handle) != ESP_OK || esp_ota_set_boot_partition(ota_partition) != ESP_OK) {
|
||||
if (esp_ota_end(ota_handle) != ESP_OK || esp_ota_set_boot_partition(ota_partition) != ESP_OK)
|
||||
{
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Validation / Activation Error");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
@ -337,10 +377,9 @@ esp_err_t POST_OTA_update(httpd_req_t *req)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t start_rest_server(void *pvParameters)
|
||||
{
|
||||
GLOBAL_STATE = (GlobalState*)pvParameters;
|
||||
GLOBAL_STATE = (GlobalState *)pvParameters;
|
||||
const char *base_path = "";
|
||||
|
||||
ESP_ERROR_CHECK(init_fs());
|
||||
@ -362,52 +401,43 @@ esp_err_t start_rest_server(void *pvParameters)
|
||||
.uri = "/api/system/info",
|
||||
.method = HTTP_GET,
|
||||
.handler = GET_system_info,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
.user_ctx = rest_context};
|
||||
httpd_register_uri_handler(server, &system_info_get_uri);
|
||||
|
||||
|
||||
httpd_uri_t system_restart_uri = {
|
||||
.uri = "/api/system/restart",
|
||||
.method = HTTP_POST,
|
||||
.handler = POST_restart,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
.user_ctx = rest_context};
|
||||
httpd_register_uri_handler(server, &system_restart_uri);
|
||||
|
||||
httpd_uri_t update_system_settings_uri = {
|
||||
.uri = "/api/system",
|
||||
.method = HTTP_PATCH,
|
||||
.handler = PATCH_update_settings,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
.user_ctx = rest_context};
|
||||
httpd_register_uri_handler(server, &update_system_settings_uri);
|
||||
|
||||
|
||||
httpd_uri_t update_post_ota_firmware = {
|
||||
.uri = "/api/system/OTA",
|
||||
.method = HTTP_POST,
|
||||
.handler = POST_OTA_update,
|
||||
.user_ctx = NULL
|
||||
};
|
||||
.uri = "/api/system/OTA",
|
||||
.method = HTTP_POST,
|
||||
.handler = POST_OTA_update,
|
||||
.user_ctx = NULL};
|
||||
httpd_register_uri_handler(server, &update_post_ota_firmware);
|
||||
|
||||
httpd_uri_t update_post_ota_www = {
|
||||
.uri = "/api/system/OTAWWW",
|
||||
.method = HTTP_POST,
|
||||
.handler = POST_WWW_update,
|
||||
.user_ctx = NULL
|
||||
};
|
||||
.uri = "/api/system/OTAWWW",
|
||||
.method = HTTP_POST,
|
||||
.handler = POST_WWW_update,
|
||||
.user_ctx = NULL};
|
||||
httpd_register_uri_handler(server, &update_post_ota_www);
|
||||
|
||||
|
||||
/* URI handler for getting web server files */
|
||||
httpd_uri_t common_get_uri = {
|
||||
.uri = "/*",
|
||||
.method = HTTP_GET,
|
||||
.handler = rest_common_get_handler,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
.user_ctx = rest_context};
|
||||
httpd_register_uri_handler(server, &common_get_uri);
|
||||
|
||||
return ESP_OK;
|
||||
@ -416,4 +446,3 @@ err_start:
|
||||
err:
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
|
@ -3,15 +3,16 @@
|
||||
#include "driver/ledc.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
//LEDS
|
||||
#define LEDX_R GPIO_NUM_35
|
||||
#define LEDX_G GPIO_NUM_36
|
||||
#define LEDX_B GPIO_NUM_37
|
||||
#define LEDZ_R GPIO_NUM_5
|
||||
#define LEDZ_G GPIO_NUM_6
|
||||
#define LEDZ_B GPIO_NUM_7
|
||||
// LEDS
|
||||
#define LEDX_R GPIO_NUM_35
|
||||
#define LEDX_G GPIO_NUM_36
|
||||
#define LEDX_B GPIO_NUM_37
|
||||
#define LEDZ_R GPIO_NUM_5
|
||||
#define LEDZ_G GPIO_NUM_6
|
||||
#define LEDZ_B GPIO_NUM_7
|
||||
|
||||
void initLEDs(void) {
|
||||
void initLEDs(void)
|
||||
{
|
||||
gpio_set_direction(LEDX_R, GPIO_MODE_OUTPUT);
|
||||
gpio_set_direction(LEDX_G, GPIO_MODE_OUTPUT);
|
||||
gpio_set_direction(LEDX_B, GPIO_MODE_OUTPUT);
|
||||
@ -27,93 +28,88 @@ void initLEDs(void) {
|
||||
gpio_set_level(LEDZ_B, 0);
|
||||
}
|
||||
|
||||
void ledc_init(void) {
|
||||
void ledc_init(void)
|
||||
{
|
||||
// Prepare and then apply the LEDC PWM timer configuration
|
||||
ledc_timer_config_t ledc_timer = {
|
||||
.speed_mode = LEDC_LOW_SPEED_MODE,
|
||||
.timer_num = LEDC_TIMER_0,
|
||||
.duty_resolution = LEDC_TIMER_12_BIT, // Set duty resolution to 12 bits
|
||||
.freq_hz = 5000, // Set output frequency at 5 kHz
|
||||
.clk_cfg = LEDC_AUTO_CLK
|
||||
};
|
||||
.speed_mode = LEDC_LOW_SPEED_MODE,
|
||||
.timer_num = LEDC_TIMER_0,
|
||||
.duty_resolution = LEDC_TIMER_12_BIT, // Set duty resolution to 12 bits
|
||||
.freq_hz = 5000, // Set output frequency at 5 kHz
|
||||
.clk_cfg = LEDC_AUTO_CLK};
|
||||
ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));
|
||||
|
||||
// Prepare and then apply the LEDC PWM channel configuration
|
||||
ledc_channel_config_t ledc_channel0 = {
|
||||
.speed_mode = LEDC_LOW_SPEED_MODE,
|
||||
.channel = LEDC_CHANNEL_0,
|
||||
.timer_sel = LEDC_TIMER_0,
|
||||
.intr_type = LEDC_INTR_DISABLE,
|
||||
.gpio_num = 35, // Define the output GPIO
|
||||
.duty = 0, // Set duty to 0%
|
||||
.hpoint = 0
|
||||
};
|
||||
.speed_mode = LEDC_LOW_SPEED_MODE,
|
||||
.channel = LEDC_CHANNEL_0,
|
||||
.timer_sel = LEDC_TIMER_0,
|
||||
.intr_type = LEDC_INTR_DISABLE,
|
||||
.gpio_num = 35, // Define the output GPIO
|
||||
.duty = 0, // Set duty to 0%
|
||||
.hpoint = 0};
|
||||
ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel0));
|
||||
|
||||
ledc_channel_config_t ledc_channel1 = {
|
||||
.speed_mode = LEDC_LOW_SPEED_MODE,
|
||||
.channel = LEDC_CHANNEL_1,
|
||||
.timer_sel = LEDC_TIMER_0,
|
||||
.intr_type = LEDC_INTR_DISABLE,
|
||||
.gpio_num = 36, // Define the output GPIO
|
||||
.duty = 0, // Set duty to 0%
|
||||
.hpoint = 0
|
||||
};
|
||||
.speed_mode = LEDC_LOW_SPEED_MODE,
|
||||
.channel = LEDC_CHANNEL_1,
|
||||
.timer_sel = LEDC_TIMER_0,
|
||||
.intr_type = LEDC_INTR_DISABLE,
|
||||
.gpio_num = 36, // Define the output GPIO
|
||||
.duty = 0, // Set duty to 0%
|
||||
.hpoint = 0};
|
||||
ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel1));
|
||||
|
||||
ledc_channel_config_t ledc_channel2 = {
|
||||
.speed_mode = LEDC_LOW_SPEED_MODE,
|
||||
.channel = LEDC_CHANNEL_2,
|
||||
.timer_sel = LEDC_TIMER_0,
|
||||
.intr_type = LEDC_INTR_DISABLE,
|
||||
.gpio_num = 37, // Define the output GPIO
|
||||
.duty = 0, // Set duty to 0%
|
||||
.hpoint = 0
|
||||
};
|
||||
.speed_mode = LEDC_LOW_SPEED_MODE,
|
||||
.channel = LEDC_CHANNEL_2,
|
||||
.timer_sel = LEDC_TIMER_0,
|
||||
.intr_type = LEDC_INTR_DISABLE,
|
||||
.gpio_num = 37, // Define the output GPIO
|
||||
.duty = 0, // Set duty to 0%
|
||||
.hpoint = 0};
|
||||
ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel2));
|
||||
|
||||
ledc_channel_config_t ledc_channel3 = {
|
||||
.speed_mode = LEDC_LOW_SPEED_MODE,
|
||||
.channel = LEDC_CHANNEL_3,
|
||||
.timer_sel = LEDC_TIMER_0,
|
||||
.intr_type = LEDC_INTR_DISABLE,
|
||||
.gpio_num = 38, // Define the output GPIO
|
||||
.duty = 0, // Set duty to 0%
|
||||
.hpoint = 0
|
||||
};
|
||||
.speed_mode = LEDC_LOW_SPEED_MODE,
|
||||
.channel = LEDC_CHANNEL_3,
|
||||
.timer_sel = LEDC_TIMER_0,
|
||||
.intr_type = LEDC_INTR_DISABLE,
|
||||
.gpio_num = 38, // Define the output GPIO
|
||||
.duty = 0, // Set duty to 0%
|
||||
.hpoint = 0};
|
||||
ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel3));
|
||||
|
||||
ledc_channel_config_t ledc_channel4 = {
|
||||
.speed_mode = LEDC_LOW_SPEED_MODE,
|
||||
.channel = LEDC_CHANNEL_4,
|
||||
.timer_sel = LEDC_TIMER_0,
|
||||
.intr_type = LEDC_INTR_DISABLE,
|
||||
.gpio_num = 39, // Define the output GPIO
|
||||
.duty = 0, // Set duty to 0%
|
||||
.hpoint = 0
|
||||
};
|
||||
.speed_mode = LEDC_LOW_SPEED_MODE,
|
||||
.channel = LEDC_CHANNEL_4,
|
||||
.timer_sel = LEDC_TIMER_0,
|
||||
.intr_type = LEDC_INTR_DISABLE,
|
||||
.gpio_num = 39, // Define the output GPIO
|
||||
.duty = 0, // Set duty to 0%
|
||||
.hpoint = 0};
|
||||
ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel4));
|
||||
|
||||
ledc_channel_config_t ledc_channel5 = {
|
||||
.speed_mode = LEDC_LOW_SPEED_MODE,
|
||||
.channel = LEDC_CHANNEL_5,
|
||||
.timer_sel = LEDC_TIMER_0,
|
||||
.intr_type = LEDC_INTR_DISABLE,
|
||||
.gpio_num = 40, // Define the output GPIO
|
||||
.duty = 0, // Set duty to 0%
|
||||
.hpoint = 0
|
||||
};
|
||||
.speed_mode = LEDC_LOW_SPEED_MODE,
|
||||
.channel = LEDC_CHANNEL_5,
|
||||
.timer_sel = LEDC_TIMER_0,
|
||||
.intr_type = LEDC_INTR_DISABLE,
|
||||
.gpio_num = 40, // Define the output GPIO
|
||||
.duty = 0, // Set duty to 0%
|
||||
.hpoint = 0};
|
||||
ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel5));
|
||||
}
|
||||
|
||||
void led_set(void) {
|
||||
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 3000)); //r
|
||||
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_1, 1000)); //g
|
||||
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_2, 0)); //b
|
||||
void led_set(void)
|
||||
{
|
||||
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 3000)); // r
|
||||
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_1, 1000)); // g
|
||||
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_2, 0)); // b
|
||||
|
||||
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_3, 3000)); //r
|
||||
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_4, 1000)); //g
|
||||
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_5, 0)); //b
|
||||
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_3, 3000)); // r
|
||||
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_4, 1000)); // g
|
||||
ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_5, 0)); // b
|
||||
|
||||
// Update duty to apply the new value
|
||||
ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0));
|
||||
|
94
main/main.c
94
main/main.c
@ -3,10 +3,9 @@
|
||||
#include "esp_log.h"
|
||||
#include "nvs_flash.h"
|
||||
|
||||
//#include "protocol_examples_common.h"
|
||||
// #include "protocol_examples_common.h"
|
||||
#include "main.h"
|
||||
|
||||
|
||||
#include "stratum_task.h"
|
||||
#include "asic_task.h"
|
||||
#include "create_jobs_task.h"
|
||||
@ -18,11 +17,8 @@
|
||||
#include "esp_netif.h"
|
||||
#include "user_input_task.h"
|
||||
|
||||
|
||||
|
||||
#define ASIC_MODEL CONFIG_ASIC_MODEL
|
||||
|
||||
|
||||
static GlobalState GLOBAL_STATE = {
|
||||
.extranonce_str = NULL,
|
||||
.extranonce_2_len = 0,
|
||||
@ -30,80 +26,88 @@ static GlobalState GLOBAL_STATE = {
|
||||
.version_mask = 0,
|
||||
.POWER_MANAGEMENT_MODULE = {
|
||||
.frequency_multiplier = 1,
|
||||
.frequency_value = ASIC_FREQUENCY
|
||||
}
|
||||
};
|
||||
.frequency_value = ASIC_FREQUENCY}};
|
||||
|
||||
static const char *TAG = "miner";
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
|
||||
if(strcmp(ASIC_MODEL, "BM1366") == 0){
|
||||
if (strcmp(ASIC_MODEL, "BM1366") == 0)
|
||||
{
|
||||
ESP_LOGI(TAG, "ASIC: BM1366");
|
||||
AsicFunctions ASIC_functions = {
|
||||
AsicFunctions ASIC_functions = {
|
||||
.init_fn = BM1366_init,
|
||||
.receive_result_fn = BM1366_proccess_work,
|
||||
.set_max_baud_fn = BM1366_set_max_baud,
|
||||
.set_difficulty_mask_fn = BM1366_set_job_difficulty_mask,
|
||||
.send_work_fn = BM1366_send_work
|
||||
};
|
||||
.send_work_fn = BM1366_send_work};
|
||||
GLOBAL_STATE.asic_job_frequency_ms = BM1366_FULLSCAN_MS;
|
||||
|
||||
GLOBAL_STATE.ASIC_functions = ASIC_functions;
|
||||
}else if(strcmp(ASIC_MODEL, "BM1397") == 0){
|
||||
}
|
||||
else if (strcmp(ASIC_MODEL, "BM1397") == 0)
|
||||
{
|
||||
ESP_LOGI(TAG, "ASIC: BM1397");
|
||||
AsicFunctions ASIC_functions = {
|
||||
AsicFunctions ASIC_functions = {
|
||||
.init_fn = BM1397_init,
|
||||
.receive_result_fn = BM1397_proccess_work,
|
||||
.set_max_baud_fn = BM1397_set_max_baud,
|
||||
.set_difficulty_mask_fn = BM1397_set_job_difficulty_mask,
|
||||
.send_work_fn = BM1397_send_work
|
||||
};
|
||||
.send_work_fn = BM1397_send_work};
|
||||
GLOBAL_STATE.asic_job_frequency_ms = BM1397_FULLSCAN_MS;
|
||||
|
||||
GLOBAL_STATE.ASIC_functions = ASIC_functions;
|
||||
}else{
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(TAG, "Invalid ASIC model");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Welcome to the bitaxe!");
|
||||
//wait between 0 and 5 seconds for multiple units
|
||||
// wait between 0 and 5 seconds for multiple units
|
||||
vTaskDelay(rand() % 5001 / portTICK_PERIOD_MS);
|
||||
ESP_ERROR_CHECK(nvs_flash_init());
|
||||
|
||||
xTaskCreate(SYSTEM_task, "SYSTEM_task", 4096, (void*)&GLOBAL_STATE, 3, NULL);
|
||||
xTaskCreate(SYSTEM_task, "SYSTEM_task", 4096, (void *)&GLOBAL_STATE, 3, NULL);
|
||||
|
||||
//pull the wifi credentials out of NVS
|
||||
char * wifi_ssid = nvs_config_get_string(NVS_CONFIG_WIFI_SSID, WIFI_SSID);
|
||||
char * wifi_pass = nvs_config_get_string(NVS_CONFIG_WIFI_PASS, WIFI_PASS);
|
||||
// pull the wifi credentials out of NVS
|
||||
char *wifi_ssid = nvs_config_get_string(NVS_CONFIG_WIFI_SSID, WIFI_SSID);
|
||||
char *wifi_pass = nvs_config_get_string(NVS_CONFIG_WIFI_PASS, WIFI_PASS);
|
||||
|
||||
//copy the wifi ssid to the global state
|
||||
// copy the wifi ssid to the global state
|
||||
strncpy(GLOBAL_STATE.SYSTEM_MODULE.ssid, wifi_ssid, 20);
|
||||
|
||||
//init and connect to wifi
|
||||
// init and connect to wifi
|
||||
wifi_init(wifi_ssid, wifi_pass);
|
||||
start_rest_server((void*)&GLOBAL_STATE);
|
||||
start_rest_server((void *)&GLOBAL_STATE);
|
||||
EventBits_t result_bits = wifi_connect();
|
||||
|
||||
if (result_bits & WIFI_CONNECTED_BIT) {
|
||||
if (result_bits & WIFI_CONNECTED_BIT)
|
||||
{
|
||||
ESP_LOGI(TAG, "Connected to SSID: %s", wifi_ssid);
|
||||
strncpy(GLOBAL_STATE.SYSTEM_MODULE.wifi_status, "Connected!", 20);
|
||||
} else if (result_bits & WIFI_FAIL_BIT) {
|
||||
}
|
||||
else if (result_bits & WIFI_FAIL_BIT)
|
||||
{
|
||||
ESP_LOGE(TAG, "Failed to connect to SSID: %s", wifi_ssid);
|
||||
strncpy(GLOBAL_STATE.SYSTEM_MODULE.wifi_status, "Failed to connect", 20);
|
||||
// User might be trying to configure with AP, just chill here
|
||||
ESP_LOGI(TAG,"Finished, waiting for user input.");
|
||||
while(1){
|
||||
ESP_LOGI(TAG, "Finished, waiting for user input.");
|
||||
while (1)
|
||||
{
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGE(TAG, "UNEXPECTED EVENT");
|
||||
strncpy(GLOBAL_STATE.SYSTEM_MODULE.wifi_status, "unexpected error", 20);
|
||||
// User might be trying to configure with AP, just chill here
|
||||
ESP_LOGI(TAG,"Finished, waiting for user input.");
|
||||
while(1){
|
||||
ESP_LOGI(TAG, "Finished, waiting for user input.");
|
||||
while (1)
|
||||
{
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
@ -120,25 +124,27 @@ void app_main(void)
|
||||
|
||||
(*GLOBAL_STATE.ASIC_functions.init_fn)(GLOBAL_STATE.POWER_MANAGEMENT_MODULE.frequency_value);
|
||||
|
||||
//set the startup_done flag
|
||||
// set the startup_done flag
|
||||
GLOBAL_STATE.SYSTEM_MODULE.startup_done = true;
|
||||
|
||||
xTaskCreate(stratum_task, "stratum admin", 8192, (void*)&GLOBAL_STATE, 5, NULL);
|
||||
xTaskCreate(create_jobs_task, "stratum miner", 8192, (void*)&GLOBAL_STATE, 10, NULL);
|
||||
xTaskCreate(POWER_MANAGEMENT_task, "power mangement", 8192, (void*)&GLOBAL_STATE, 10, NULL);
|
||||
xTaskCreate(ASIC_task, "asic", 8192, (void*)&GLOBAL_STATE, 10, NULL);
|
||||
xTaskCreate(ASIC_result_task, "asic result", 8192, (void*)&GLOBAL_STATE, 15, NULL);
|
||||
|
||||
xTaskCreate(USER_INPUT_task, "user input", 8192, (void*)&GLOBAL_STATE, 5, NULL);
|
||||
|
||||
xTaskCreate(stratum_task, "stratum admin", 8192, (void *)&GLOBAL_STATE, 5, NULL);
|
||||
xTaskCreate(create_jobs_task, "stratum miner", 8192, (void *)&GLOBAL_STATE, 10, NULL);
|
||||
xTaskCreate(POWER_MANAGEMENT_task, "power mangement", 8192, (void *)&GLOBAL_STATE, 10, NULL);
|
||||
xTaskCreate(ASIC_task, "asic", 8192, (void *)&GLOBAL_STATE, 10, NULL);
|
||||
xTaskCreate(ASIC_result_task, "asic result", 8192, (void *)&GLOBAL_STATE, 15, NULL);
|
||||
|
||||
xTaskCreate(USER_INPUT_task, "user input", 8192, (void *)&GLOBAL_STATE, 5, NULL);
|
||||
}
|
||||
|
||||
void MINER_set_wifi_status(wifi_status_t status, uint16_t retry_count) {
|
||||
if (status == WIFI_RETRYING) {
|
||||
void MINER_set_wifi_status(wifi_status_t status, uint16_t retry_count)
|
||||
{
|
||||
if (status == WIFI_RETRYING)
|
||||
{
|
||||
snprintf(GLOBAL_STATE.SYSTEM_MODULE.wifi_status, 20, "Retrying: %d/%d", retry_count, WIFI_MAXIMUM_RETRY);
|
||||
return;
|
||||
} else if (status == WIFI_CONNECT_FAILED) {
|
||||
}
|
||||
else if (status == WIFI_CONNECT_FAILED)
|
||||
{
|
||||
snprintf(GLOBAL_STATE.SYSTEM_MODULE.wifi_status, 20, "Connect Failed!");
|
||||
return;
|
||||
}
|
||||
|
@ -5,9 +5,9 @@
|
||||
|
||||
#define NVS_CONFIG_NAMESPACE "main"
|
||||
|
||||
static const char * TAG = "nvs_config";
|
||||
static const char *TAG = "nvs_config";
|
||||
|
||||
char * nvs_config_get_string(const char * key, const char * default_value)
|
||||
char *nvs_config_get_string(const char *key, const char *default_value)
|
||||
{
|
||||
nvs_handle handle;
|
||||
esp_err_t err;
|
||||
@ -27,7 +27,7 @@ char * nvs_config_get_string(const char * key, const char * default_value)
|
||||
return strdup(default_value);
|
||||
}
|
||||
|
||||
char * out = malloc(size);
|
||||
char *out = malloc(size);
|
||||
err = nvs_get_str(handle, key, out, &size);
|
||||
|
||||
if (err != ESP_OK)
|
||||
@ -40,7 +40,7 @@ char * nvs_config_get_string(const char * key, const char * default_value)
|
||||
return out;
|
||||
}
|
||||
|
||||
void nvs_config_set_string(const char * key, const char * value)
|
||||
void nvs_config_set_string(const char *key, const char *value)
|
||||
{
|
||||
|
||||
nvs_handle handle;
|
||||
@ -63,7 +63,7 @@ void nvs_config_set_string(const char * key, const char * value)
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t nvs_config_get_u16(const char * key, const uint16_t default_value)
|
||||
uint16_t nvs_config_get_u16(const char *key, const uint16_t default_value)
|
||||
{
|
||||
nvs_handle handle;
|
||||
esp_err_t err;
|
||||
@ -87,7 +87,7 @@ uint16_t nvs_config_get_u16(const char * key, const uint16_t default_value)
|
||||
return out;
|
||||
}
|
||||
|
||||
void nvs_config_set_u16(const char * key, const uint16_t value)
|
||||
void nvs_config_set_u16(const char *key, const uint16_t value)
|
||||
{
|
||||
|
||||
nvs_handle handle;
|
||||
|
@ -13,9 +13,9 @@
|
||||
#define NVS_CONFIG_ASIC_VOLTAGE "asicvoltage"
|
||||
#define NVS_CONFIG_ASIC_MODEL "asicModel"
|
||||
|
||||
char * nvs_config_get_string(const char * key, const char * default_value);
|
||||
void nvs_config_set_string(const char * key, const char * default_value);
|
||||
uint16_t nvs_config_get_u16(const char * key, const uint16_t default_value);
|
||||
void nvs_config_set_u16(const char * key, const uint16_t value);
|
||||
char *nvs_config_get_string(const char *key, const char *default_value);
|
||||
void nvs_config_set_string(const char *key, const char *default_value);
|
||||
uint16_t nvs_config_get_u16(const char *key, const uint16_t default_value);
|
||||
void nvs_config_set_u16(const char *key, const uint16_t value);
|
||||
|
||||
#endif // MAIN_NVS_CONFIG_H
|
||||
|
156
main/oled.c
156
main/oled.c
@ -15,7 +15,6 @@
|
||||
// A copy of the display memory is maintained by this code so that single pixel
|
||||
// writes can occur without having to read from the display controller.
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
@ -26,14 +25,13 @@
|
||||
|
||||
#include "oled.h"
|
||||
|
||||
|
||||
#define I2C_TIMEOUT 1000
|
||||
#define OLED_FLIP 1
|
||||
#define OLED_INVERT 0
|
||||
#define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
|
||||
#define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
|
||||
|
||||
extern unsigned char ucSmallFont[];
|
||||
static int iScreenOffset; // current write offset of screen data
|
||||
static int iScreenOffset; // current write offset of screen data
|
||||
static unsigned char ucScreen[1024]; // local copy of the image buffer
|
||||
static int oled_type, oled_flip;
|
||||
|
||||
@ -42,34 +40,34 @@ static esp_err_t write(uint8_t *, uint8_t);
|
||||
|
||||
static bool oled_active;
|
||||
|
||||
|
||||
//Initialialize the OLED Screen
|
||||
bool OLED_init(void) {
|
||||
// Initialialize the OLED Screen
|
||||
bool OLED_init(void)
|
||||
{
|
||||
uint8_t oled32_initbuf[] = {
|
||||
0x00,
|
||||
0xae, //cmd: display off
|
||||
0xd5, //cmd: set display clock
|
||||
0x80,
|
||||
0xa8, //cmd: set multiplex ratio
|
||||
0x1f, //HEIGHT - 1 -> 31
|
||||
0xd3, //cmd: set display offset
|
||||
0x00,
|
||||
0x40, //cmd: Set Display Start Line
|
||||
0x8d,
|
||||
0x14, //cmd: Set Higher Column Start Address for Page Addressing Mode
|
||||
0xa1,
|
||||
0xc8, //cmd: Set COM Output Scan Direction C0/C8
|
||||
0xda, //cmd: Set COM Pins Hardware Configuration
|
||||
0x02, //
|
||||
0x81, //cmd: Set Contrast control
|
||||
0x7f,
|
||||
0xd9, //cmd: Set Pre-Charge Period
|
||||
0xf1,
|
||||
0xdb, //comd: Vcom regulator output
|
||||
0x40,
|
||||
0xa4, //cmd: display on ram contents
|
||||
0xa6, //cmd: set normal
|
||||
0xaf}; //cmd: display on
|
||||
0x00,
|
||||
0xae, // cmd: display off
|
||||
0xd5, // cmd: set display clock
|
||||
0x80,
|
||||
0xa8, // cmd: set multiplex ratio
|
||||
0x1f, // HEIGHT - 1 -> 31
|
||||
0xd3, // cmd: set display offset
|
||||
0x00,
|
||||
0x40, // cmd: Set Display Start Line
|
||||
0x8d,
|
||||
0x14, // cmd: Set Higher Column Start Address for Page Addressing Mode
|
||||
0xa1,
|
||||
0xc8, // cmd: Set COM Output Scan Direction C0/C8
|
||||
0xda, // cmd: Set COM Pins Hardware Configuration
|
||||
0x02, //
|
||||
0x81, // cmd: Set Contrast control
|
||||
0x7f,
|
||||
0xd9, // cmd: Set Pre-Charge Period
|
||||
0xf1,
|
||||
0xdb, // comd: Vcom regulator output
|
||||
0x40,
|
||||
0xa4, // cmd: display on ram contents
|
||||
0xa6, // cmd: set normal
|
||||
0xaf}; // cmd: display on
|
||||
uint8_t uc[4];
|
||||
|
||||
uint8_t bFlip = OLED_FLIP;
|
||||
@ -100,13 +98,15 @@ bool OLED_init(void) {
|
||||
|
||||
write(oled32_initbuf, sizeof(oled32_initbuf));
|
||||
|
||||
if (bInvert) {
|
||||
uc[0] = 0; // command
|
||||
if (bInvert)
|
||||
{
|
||||
uc[0] = 0; // command
|
||||
uc[1] = 0xa7; // invert command
|
||||
write(uc, 2);
|
||||
}
|
||||
|
||||
if (bFlip) {// rotate display 180
|
||||
if (bFlip)
|
||||
{ // rotate display 180
|
||||
uc[0] = 0; // command
|
||||
uc[1] = 0xa0;
|
||||
write(uc, 2);
|
||||
@ -118,17 +118,18 @@ bool OLED_init(void) {
|
||||
|
||||
// Sends a command to turn off the OLED display
|
||||
// Closes the I2C file handle
|
||||
void OLED_shutdown() {
|
||||
void OLED_shutdown()
|
||||
{
|
||||
|
||||
write_command(0xaE); // turn off OLED
|
||||
// I2C_close(oled_i2c);
|
||||
// GPIO_write(Board_OLED_DISP_ENABLE, 0); //turn off power
|
||||
oled_active = false;
|
||||
|
||||
}
|
||||
|
||||
// Send a single byte command to the OLED controller
|
||||
static void write_command(uint8_t c) {
|
||||
static void write_command(uint8_t c)
|
||||
{
|
||||
uint8_t buf[2];
|
||||
|
||||
buf[0] = 0x00; // command introducer
|
||||
@ -136,7 +137,8 @@ static void write_command(uint8_t c) {
|
||||
write(buf, 2);
|
||||
}
|
||||
|
||||
static void oledWriteCommand2(uint8_t c, uint8_t d) {
|
||||
static void oledWriteCommand2(uint8_t c, uint8_t d)
|
||||
{
|
||||
uint8_t buf[3];
|
||||
|
||||
buf[0] = 0x00;
|
||||
@ -145,43 +147,43 @@ static void oledWriteCommand2(uint8_t c, uint8_t d) {
|
||||
write(buf, 3);
|
||||
}
|
||||
|
||||
bool OLED_setContrast(uint8_t ucContrast) {
|
||||
bool OLED_setContrast(uint8_t ucContrast)
|
||||
{
|
||||
|
||||
oledWriteCommand2(0x81, ucContrast);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Send commands to position the "cursor" to the given
|
||||
// row and column
|
||||
static void oledSetPosition(int x, int y) {
|
||||
iScreenOffset = (y*128)+x;
|
||||
static void oledSetPosition(int x, int y)
|
||||
{
|
||||
iScreenOffset = (y * 128) + x;
|
||||
if (oled_type == OLED_64x32) // visible display starts at column 32, row 4
|
||||
{
|
||||
x += 32; // display is centered in VRAM, so this is always true
|
||||
x += 32; // display is centered in VRAM, so this is always true
|
||||
if (oled_flip == 0) // non-flipped display starts from line 4
|
||||
y += 4;
|
||||
y += 4;
|
||||
}
|
||||
else if (oled_type == OLED_132x64) // SH1106 has 128 pixels centered in 132
|
||||
{
|
||||
x += 2;
|
||||
}
|
||||
|
||||
write_command(0xb0 | y); // go to page Y
|
||||
write_command(0x00 | (x & 0xf)); // // lower col addr
|
||||
write_command(0xb0 | y); // go to page Y
|
||||
write_command(0x00 | (x & 0xf)); // // lower col addr
|
||||
write_command(0x10 | ((x >> 4) & 0xf)); // upper col addr
|
||||
}
|
||||
|
||||
|
||||
// Write a block of pixel data to the OLED
|
||||
// Length can be anything from 1 to 1024 (whole display)
|
||||
static void oledWriteDataBlock(uint8_t *ucBuf, int iLen) {
|
||||
static void oledWriteDataBlock(uint8_t *ucBuf, int iLen)
|
||||
{
|
||||
uint8_t ucTemp[129];
|
||||
|
||||
ucTemp[0] = 0x40; // data command
|
||||
memcpy(&ucTemp[1], ucBuf, iLen);
|
||||
write(ucTemp, iLen+1);
|
||||
write(ucTemp, iLen + 1);
|
||||
// Keep a copy in local buffer
|
||||
memcpy(&ucScreen[iScreenOffset], ucBuf, iLen);
|
||||
iScreenOffset += iLen;
|
||||
@ -190,7 +192,8 @@ static void oledWriteDataBlock(uint8_t *ucBuf, int iLen) {
|
||||
// Set (or clear) an individual pixel
|
||||
// The local copy of the frame buffer is used to avoid
|
||||
// reading data from the display controller
|
||||
int OLED_setPixel(int x, int y, uint8_t ucColor) {
|
||||
int OLED_setPixel(int x, int y, uint8_t ucColor)
|
||||
{
|
||||
int i;
|
||||
uint8_t uc, ucOld;
|
||||
|
||||
@ -208,33 +211,35 @@ int OLED_setPixel(int x, int y, uint8_t ucColor) {
|
||||
}
|
||||
if (uc != ucOld) // pixel changed
|
||||
{
|
||||
oledSetPosition(x, y>>3);
|
||||
oledSetPosition(x, y >> 3);
|
||||
oledWriteDataBlock(&uc, 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Draw a string of small (8x8), large (16x24), or very small (6x8) characters
|
||||
// At the given col+row
|
||||
// The X position is in character widths (8 or 16)
|
||||
// The Y position is in memory pages (8 lines each)
|
||||
//
|
||||
int OLED_writeString(int x, int y, char *szMsg) {
|
||||
int OLED_writeString(int x, int y, char *szMsg)
|
||||
{
|
||||
int i, iLen;
|
||||
uint8_t *s;
|
||||
|
||||
//if (oled_i2c == NULL) return -1; // not initialized
|
||||
// if (oled_i2c == NULL) return -1; // not initialized
|
||||
|
||||
iLen = strlen(szMsg);
|
||||
|
||||
oledSetPosition(x*6, y);
|
||||
if (iLen + x > 21) iLen = 21 - x;
|
||||
if (iLen < 0) return -1;
|
||||
for (i=0; i<iLen; i++)
|
||||
oledSetPosition(x * 6, y);
|
||||
if (iLen + x > 21)
|
||||
iLen = 21 - x;
|
||||
if (iLen < 0)
|
||||
return -1;
|
||||
for (i = 0; i < iLen; i++)
|
||||
{
|
||||
s = &ucSmallFont[(unsigned char)szMsg[i]*6];
|
||||
s = &ucSmallFont[(unsigned char)szMsg[i] * 6];
|
||||
oledWriteDataBlock(s, 6);
|
||||
}
|
||||
|
||||
@ -243,46 +248,51 @@ int OLED_writeString(int x, int y, char *szMsg) {
|
||||
|
||||
// Fill the frame buffer with a byte pattern
|
||||
// e.g. all off (0x00) or all on (0xff)
|
||||
int OLED_fill(uint8_t ucData) {
|
||||
int OLED_fill(uint8_t ucData)
|
||||
{
|
||||
int y;
|
||||
uint8_t temp[128];
|
||||
int iLines, iCols;
|
||||
|
||||
//if (oled_i2c == NULL) return -1; // not initialized
|
||||
// if (oled_i2c == NULL) return -1; // not initialized
|
||||
|
||||
iLines = (oled_type == OLED_128x32 || oled_type == OLED_64x32) ? 4 : 8;
|
||||
iCols = (oled_type == OLED_64x32) ? 4 : 8;
|
||||
|
||||
memset(temp, ucData, 128);
|
||||
for (y=0; y<iLines; y++) {
|
||||
oledSetPosition(0,y); // set to (0,Y)
|
||||
oledWriteDataBlock(temp, iCols*16); // fill with data byte
|
||||
} // for y
|
||||
for (y = 0; y < iLines; y++)
|
||||
{
|
||||
oledSetPosition(0, y); // set to (0,Y)
|
||||
oledWriteDataBlock(temp, iCols * 16); // fill with data byte
|
||||
} // for y
|
||||
return 0;
|
||||
}
|
||||
|
||||
int OLED_clearLine(uint8_t line) {
|
||||
int OLED_clearLine(uint8_t line)
|
||||
{
|
||||
uint8_t temp[128];
|
||||
|
||||
//if (oled_i2c == NULL) return -1; // not initialized
|
||||
if (line > 4) return -1; //line number too big
|
||||
// if (oled_i2c == NULL) return -1; // not initialized
|
||||
if (line > 4)
|
||||
return -1; // line number too big
|
||||
|
||||
memset(temp, 0, 128);
|
||||
oledSetPosition(0, line); // set to (0,Y)
|
||||
oledSetPosition(0, line); // set to (0,Y)
|
||||
oledWriteDataBlock(temp, 128); // fill with data byte
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool OLED_status(void) {
|
||||
bool OLED_status(void)
|
||||
{
|
||||
return oled_active;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Write a byte to a I2C register
|
||||
*/
|
||||
static esp_err_t write(uint8_t *data, uint8_t len) {
|
||||
static esp_err_t write(uint8_t *data, uint8_t len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = i2c_master_write_to_device(I2C_MASTER_NUM, 0x3C, data, len, 1000 / portTICK_PERIOD_MS);
|
||||
|
@ -8,7 +8,8 @@
|
||||
// Project started 1/15/2017
|
||||
//
|
||||
// OLED type for init function
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
OLED_128x32 = 1,
|
||||
OLED_128x64,
|
||||
OLED_132x64,
|
||||
@ -17,9 +18,9 @@ enum {
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FONT_NORMAL=0, // 8x8
|
||||
FONT_BIG, // 16x24
|
||||
FONT_SMALL // 6x8
|
||||
FONT_NORMAL = 0, // 8x8
|
||||
FONT_BIG, // 16x24
|
||||
FONT_SMALL // 6x8
|
||||
} FONTSIZE;
|
||||
|
||||
// Initialize the OLED96 library for a specific I2C address
|
||||
|
337
main/system.c
337
main/system.c
@ -25,8 +25,8 @@ static const char *TAG = "SystemModule";
|
||||
|
||||
static void _suffix_string(uint64_t, char *, size_t, int);
|
||||
|
||||
|
||||
static void _init_system(SystemModule* module) {
|
||||
static void _init_system(SystemModule *module)
|
||||
{
|
||||
|
||||
module->duration_start = 0;
|
||||
module->historical_hashrate_rolling_index = 0;
|
||||
@ -41,70 +41,74 @@ static void _init_system(SystemModule* module) {
|
||||
module->FOUND_BLOCK = false;
|
||||
module->startup_done = false;
|
||||
|
||||
//set the best diff string to 0
|
||||
// set the best diff string to 0
|
||||
_suffix_string(0, module->best_diff_string, DIFF_STRING_SIZE, 0);
|
||||
|
||||
//set the ssid string to blank
|
||||
// set the ssid string to blank
|
||||
memset(module->ssid, 0, 20);
|
||||
|
||||
//set the wifi_status to blank
|
||||
// set the wifi_status to blank
|
||||
memset(module->wifi_status, 0, 20);
|
||||
|
||||
//test the LEDs
|
||||
// ESP_LOGI(TAG, "Init LEDs!");
|
||||
// ledc_init();
|
||||
// led_set();
|
||||
// test the LEDs
|
||||
// ESP_LOGI(TAG, "Init LEDs!");
|
||||
// ledc_init();
|
||||
// led_set();
|
||||
|
||||
//Playing with BI level
|
||||
// Playing with BI level
|
||||
gpio_set_direction(GPIO_NUM_10, GPIO_MODE_OUTPUT);
|
||||
gpio_set_level(GPIO_NUM_10, 0);
|
||||
|
||||
//Init I2C
|
||||
// Init I2C
|
||||
ESP_ERROR_CHECK(i2c_master_init());
|
||||
ESP_LOGI(TAG, "I2C initialized successfully");
|
||||
|
||||
ADC_init();
|
||||
|
||||
//DS4432U tests
|
||||
// DS4432U tests
|
||||
DS4432U_set_vcore(ASIC_VOLTAGE / 1000.0);
|
||||
|
||||
//Fan Tests
|
||||
// Fan Tests
|
||||
EMC2101_init();
|
||||
EMC2101_set_fan_speed(0.75);
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
|
||||
//oled
|
||||
if (!OLED_init()) {
|
||||
// oled
|
||||
if (!OLED_init())
|
||||
{
|
||||
ESP_LOGI(TAG, "OLED init failed!");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(TAG, "OLED init success!");
|
||||
//clear the oled screen
|
||||
// clear the oled screen
|
||||
OLED_fill(0);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void _update_hashrate(SystemModule* module){
|
||||
static void _update_hashrate(SystemModule *module)
|
||||
{
|
||||
|
||||
if (module->screen_page != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(module->screen_page != 0){
|
||||
return;
|
||||
}
|
||||
float power = INA260_read_power() / 1000;
|
||||
|
||||
float power = INA260_read_power() / 1000;
|
||||
float efficiency = power / (module->current_hashrate / 1000.0);
|
||||
|
||||
float efficiency = power / (module->current_hashrate/1000.0);
|
||||
|
||||
OLED_clearLine(0);
|
||||
memset(module->oled_buf, 0, 20);
|
||||
snprintf(module->oled_buf, 20, "Gh%s: %.1f W/Th: %.1f", module->historical_hashrate_init < HISTORY_LENGTH ? "*": "", module->current_hashrate, efficiency);
|
||||
OLED_writeString(0, 0, module->oled_buf);
|
||||
OLED_clearLine(0);
|
||||
memset(module->oled_buf, 0, 20);
|
||||
snprintf(module->oled_buf, 20, "Gh%s: %.1f W/Th: %.1f", module->historical_hashrate_init < HISTORY_LENGTH ? "*" : "", module->current_hashrate, efficiency);
|
||||
OLED_writeString(0, 0, module->oled_buf);
|
||||
}
|
||||
|
||||
static void _update_shares(SystemModule* module){
|
||||
if(module->screen_page != 0){
|
||||
return;
|
||||
static void _update_shares(SystemModule *module)
|
||||
{
|
||||
if (module->screen_page != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
OLED_clearLine(1);
|
||||
memset(module->oled_buf, 0, 20);
|
||||
@ -112,30 +116,34 @@ static void _update_shares(SystemModule* module){
|
||||
OLED_writeString(0, 1, module->oled_buf);
|
||||
}
|
||||
|
||||
static void _update_best_diff(SystemModule* module){
|
||||
if(module->screen_page != 0){
|
||||
return;
|
||||
static void _update_best_diff(SystemModule *module)
|
||||
{
|
||||
if (module->screen_page != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
OLED_clearLine(3);
|
||||
memset(module->oled_buf, 0, 20);
|
||||
snprintf(module->oled_buf, 20, module->FOUND_BLOCK ? "!!! BLOCK FOUND !!!" : "BD: %s", module->best_diff_string);
|
||||
snprintf(module->oled_buf, 20, module->FOUND_BLOCK ? "!!! BLOCK FOUND !!!" : "BD: %s", module->best_diff_string);
|
||||
OLED_writeString(0, 3, module->oled_buf);
|
||||
}
|
||||
|
||||
static void _clear_display(void){
|
||||
static void _clear_display(void)
|
||||
{
|
||||
OLED_clearLine(0);
|
||||
OLED_clearLine(1);
|
||||
OLED_clearLine(2);
|
||||
OLED_clearLine(3);
|
||||
}
|
||||
|
||||
static void _update_system_info(GlobalState *GLOBAL_STATE)
|
||||
{
|
||||
|
||||
static void _update_system_info(GlobalState *GLOBAL_STATE) {
|
||||
SystemModule *module = &GLOBAL_STATE->SYSTEM_MODULE;
|
||||
PowerManagementModule *power_management = &GLOBAL_STATE->POWER_MANAGEMENT_MODULE;
|
||||
|
||||
SystemModule * module = &GLOBAL_STATE->SYSTEM_MODULE;
|
||||
PowerManagementModule * power_management = &GLOBAL_STATE->POWER_MANAGEMENT_MODULE;
|
||||
|
||||
if (OLED_status()) {
|
||||
if (OLED_status())
|
||||
{
|
||||
|
||||
memset(module->oled_buf, 0, 20);
|
||||
snprintf(module->oled_buf, 20, " Fan: %d RPM", power_management->fan_speed);
|
||||
@ -150,20 +158,20 @@ static void _update_system_info(GlobalState *GLOBAL_STATE) {
|
||||
OLED_writeString(0, 2, module->oled_buf);
|
||||
|
||||
memset(module->oled_buf, 0, 20);
|
||||
snprintf(module->oled_buf, 20, " %i mV: %i mA",(int)power_management->voltage, (int)power_management->current);
|
||||
snprintf(module->oled_buf, 20, " %i mV: %i mA", (int)power_management->voltage, (int)power_management->current);
|
||||
OLED_writeString(0, 3, module->oled_buf);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void _update_esp32_info(SystemModule* module) {
|
||||
|
||||
static void _update_esp32_info(SystemModule *module)
|
||||
{
|
||||
|
||||
uint32_t free_heap_size = esp_get_free_heap_size();
|
||||
|
||||
uint16_t vcore = ADC_get_vcore();
|
||||
|
||||
if (OLED_status()) {
|
||||
if (OLED_status())
|
||||
{
|
||||
|
||||
memset(module->oled_buf, 0, 20);
|
||||
snprintf(module->oled_buf, 20, "FH: %lu bytes", free_heap_size);
|
||||
@ -177,22 +185,24 @@ static void _update_esp32_info(SystemModule* module) {
|
||||
// snprintf(oled_buf, 20, "Pwr: %.2f W", power);
|
||||
// OLED_writeString(0, 2, oled_buf);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void _init_connection(SystemModule* module) {
|
||||
static void _init_connection(SystemModule *module)
|
||||
{
|
||||
|
||||
if (OLED_status()) {
|
||||
if (OLED_status())
|
||||
{
|
||||
memset(module->oled_buf, 0, 20);
|
||||
snprintf(module->oled_buf, 20, "Connecting to ssid:");
|
||||
OLED_writeString(0, 0, module->oled_buf);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void _update_connection(SystemModule* module) {
|
||||
static void _update_connection(SystemModule *module)
|
||||
{
|
||||
|
||||
if (OLED_status()) {
|
||||
if (OLED_status())
|
||||
{
|
||||
OLED_clearLine(2);
|
||||
memset(module->oled_buf, 0, 20);
|
||||
snprintf(module->oled_buf, 20, "%s", module->ssid);
|
||||
@ -203,11 +213,10 @@ static void _update_connection(SystemModule* module) {
|
||||
snprintf(module->oled_buf, 20, "%s", module->wifi_status);
|
||||
OLED_writeString(0, 3, module->oled_buf);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void _update_system_performance(SystemModule* module){
|
||||
|
||||
static void _update_system_performance(SystemModule *module)
|
||||
{
|
||||
|
||||
// Calculate the uptime in seconds
|
||||
double uptime_in_seconds = (esp_timer_get_time() - module->start_time) / 1000000;
|
||||
@ -217,8 +226,8 @@ static void _update_system_performance(SystemModule* module){
|
||||
remaining_seconds %= 3600;
|
||||
int uptime_in_minutes = remaining_seconds / 60;
|
||||
|
||||
|
||||
if (OLED_status()) {
|
||||
if (OLED_status())
|
||||
{
|
||||
|
||||
_update_hashrate(module);
|
||||
_update_shares(module);
|
||||
@ -230,28 +239,30 @@ static void _update_system_performance(SystemModule* module){
|
||||
}
|
||||
}
|
||||
|
||||
static double _calculate_network_difficulty(uint32_t nBits)
|
||||
{
|
||||
uint32_t mantissa = nBits & 0x007fffff; // Extract the mantissa from nBits
|
||||
uint8_t exponent = (nBits >> 24) & 0xff; // Extract the exponent from nBits
|
||||
|
||||
double target = (double)mantissa * pow(256, (exponent - 3)); // Calculate the target value
|
||||
|
||||
static double _calculate_network_difficulty(uint32_t nBits) {
|
||||
uint32_t mantissa = nBits & 0x007fffff; // Extract the mantissa from nBits
|
||||
uint8_t exponent = (nBits >> 24) & 0xff; // Extract the exponent from nBits
|
||||
|
||||
double target = (double)mantissa * pow(256,(exponent - 3)); // Calculate the target value
|
||||
|
||||
double difficulty = (pow(2, 208) * 65535) / target; // Calculate the difficulty
|
||||
double difficulty = (pow(2, 208) * 65535) / target; // Calculate the difficulty
|
||||
|
||||
return difficulty;
|
||||
}
|
||||
|
||||
static void _check_for_best_diff(SystemModule * module, double diff, uint32_t nbits){
|
||||
if(diff < module->best_nonce_diff){
|
||||
static void _check_for_best_diff(SystemModule *module, double diff, uint32_t nbits)
|
||||
{
|
||||
if (diff < module->best_nonce_diff)
|
||||
{
|
||||
return;
|
||||
}
|
||||
module->best_nonce_diff = diff;
|
||||
//make the best_nonce_diff into a string
|
||||
// make the best_nonce_diff into a string
|
||||
_suffix_string((uint64_t)diff, module->best_diff_string, DIFF_STRING_SIZE, 0);
|
||||
double network_diff = _calculate_network_difficulty(nbits);
|
||||
if(diff > network_diff){
|
||||
if (diff > network_diff)
|
||||
{
|
||||
module->FOUND_BLOCK = true;
|
||||
ESP_LOGI(TAG, "FOUND BLOCK!!!!!!!!!!!!!!!!!!!!!! %f > %f", diff, network_diff);
|
||||
}
|
||||
@ -260,64 +271,81 @@ static void _check_for_best_diff(SystemModule * module, double diff, uint32_t nb
|
||||
|
||||
/* Convert a uint64_t value into a truncated string for displaying with its
|
||||
* associated suitable for Mega, Giga etc. Buf array needs to be long enough */
|
||||
static void _suffix_string(uint64_t val, char *buf, size_t bufsiz, int sigdigits) {
|
||||
const double dkilo = 1000.0;
|
||||
const uint64_t kilo = 1000ull;
|
||||
const uint64_t mega = 1000000ull;
|
||||
const uint64_t giga = 1000000000ull;
|
||||
const uint64_t tera = 1000000000000ull;
|
||||
const uint64_t peta = 1000000000000000ull;
|
||||
const uint64_t exa = 1000000000000000000ull;
|
||||
char suffix[2] = "";
|
||||
bool decimal = true;
|
||||
double dval;
|
||||
static void _suffix_string(uint64_t val, char *buf, size_t bufsiz, int sigdigits)
|
||||
{
|
||||
const double dkilo = 1000.0;
|
||||
const uint64_t kilo = 1000ull;
|
||||
const uint64_t mega = 1000000ull;
|
||||
const uint64_t giga = 1000000000ull;
|
||||
const uint64_t tera = 1000000000000ull;
|
||||
const uint64_t peta = 1000000000000000ull;
|
||||
const uint64_t exa = 1000000000000000000ull;
|
||||
char suffix[2] = "";
|
||||
bool decimal = true;
|
||||
double dval;
|
||||
|
||||
if (val >= exa) {
|
||||
val /= peta;
|
||||
dval = (double)val / dkilo;
|
||||
strcpy(suffix, "E");
|
||||
} else if (val >= peta) {
|
||||
val /= tera;
|
||||
dval = (double)val / dkilo;
|
||||
strcpy(suffix, "P");
|
||||
} else if (val >= tera) {
|
||||
val /= giga;
|
||||
dval = (double)val / dkilo;
|
||||
strcpy(suffix, "T");
|
||||
} else if (val >= giga) {
|
||||
val /= mega;
|
||||
dval = (double)val / dkilo;
|
||||
strcpy(suffix, "G");
|
||||
} else if (val >= mega) {
|
||||
val /= kilo;
|
||||
dval = (double)val / dkilo;
|
||||
strcpy(suffix, "M");
|
||||
} else if (val >= kilo) {
|
||||
dval = (double)val / dkilo;
|
||||
strcpy(suffix, "k");
|
||||
} else {
|
||||
dval = val;
|
||||
decimal = false;
|
||||
}
|
||||
if (val >= exa)
|
||||
{
|
||||
val /= peta;
|
||||
dval = (double)val / dkilo;
|
||||
strcpy(suffix, "E");
|
||||
}
|
||||
else if (val >= peta)
|
||||
{
|
||||
val /= tera;
|
||||
dval = (double)val / dkilo;
|
||||
strcpy(suffix, "P");
|
||||
}
|
||||
else if (val >= tera)
|
||||
{
|
||||
val /= giga;
|
||||
dval = (double)val / dkilo;
|
||||
strcpy(suffix, "T");
|
||||
}
|
||||
else if (val >= giga)
|
||||
{
|
||||
val /= mega;
|
||||
dval = (double)val / dkilo;
|
||||
strcpy(suffix, "G");
|
||||
}
|
||||
else if (val >= mega)
|
||||
{
|
||||
val /= kilo;
|
||||
dval = (double)val / dkilo;
|
||||
strcpy(suffix, "M");
|
||||
}
|
||||
else if (val >= kilo)
|
||||
{
|
||||
dval = (double)val / dkilo;
|
||||
strcpy(suffix, "k");
|
||||
}
|
||||
else
|
||||
{
|
||||
dval = val;
|
||||
decimal = false;
|
||||
}
|
||||
|
||||
if (!sigdigits) {
|
||||
if (decimal)
|
||||
snprintf(buf, bufsiz, "%.3g%s", dval, suffix);
|
||||
else
|
||||
snprintf(buf, bufsiz, "%d%s", (unsigned int)dval, suffix);
|
||||
} else {
|
||||
/* Always show sigdigits + 1, padded on right with zeroes
|
||||
* followed by suffix */
|
||||
int ndigits = sigdigits - 1 - (dval > 0.0 ? floor(log10(dval)) : 0);
|
||||
if (!sigdigits)
|
||||
{
|
||||
if (decimal)
|
||||
snprintf(buf, bufsiz, "%.3g%s", dval, suffix);
|
||||
else
|
||||
snprintf(buf, bufsiz, "%d%s", (unsigned int)dval, suffix);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Always show sigdigits + 1, padded on right with zeroes
|
||||
* followed by suffix */
|
||||
int ndigits = sigdigits - 1 - (dval > 0.0 ? floor(log10(dval)) : 0);
|
||||
|
||||
snprintf(buf, bufsiz, "%*.*f%s", sigdigits + 1, ndigits, dval, suffix);
|
||||
}
|
||||
snprintf(buf, bufsiz, "%*.*f%s", sigdigits + 1, ndigits, dval, suffix);
|
||||
}
|
||||
}
|
||||
|
||||
void SYSTEM_task(void *pvParameters)
|
||||
{
|
||||
|
||||
void SYSTEM_task(void *pvParameters) {
|
||||
|
||||
GlobalState *GLOBAL_STATE = (GlobalState*)pvParameters;
|
||||
GlobalState *GLOBAL_STATE = (GlobalState *)pvParameters;
|
||||
SystemModule *module = &GLOBAL_STATE->SYSTEM_MODULE;
|
||||
|
||||
_init_system(module);
|
||||
@ -325,14 +353,15 @@ void SYSTEM_task(void *pvParameters) {
|
||||
_clear_display();
|
||||
_init_connection(module);
|
||||
|
||||
//show the connection screen
|
||||
while (!module->startup_done) {
|
||||
// show the connection screen
|
||||
while (!module->startup_done)
|
||||
{
|
||||
_update_connection(module);
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
|
||||
while(1){
|
||||
while (1)
|
||||
{
|
||||
_clear_display();
|
||||
module->screen_page = 0;
|
||||
_update_system_performance(module);
|
||||
@ -347,28 +376,30 @@ void SYSTEM_task(void *pvParameters) {
|
||||
module->screen_page = 2;
|
||||
_update_esp32_info(module);
|
||||
vTaskDelay(10000 / portTICK_PERIOD_MS);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SYSTEM_notify_accepted_share(SystemModule* module){
|
||||
void SYSTEM_notify_accepted_share(SystemModule *module)
|
||||
{
|
||||
module->shares_accepted++;
|
||||
_update_shares(module);
|
||||
}
|
||||
void SYSTEM_notify_rejected_share(SystemModule* module){
|
||||
void SYSTEM_notify_rejected_share(SystemModule *module)
|
||||
{
|
||||
module->shares_rejected++;
|
||||
_update_shares(module);
|
||||
}
|
||||
|
||||
|
||||
void SYSTEM_notify_mining_started(SystemModule* module){
|
||||
void SYSTEM_notify_mining_started(SystemModule *module)
|
||||
{
|
||||
module->duration_start = esp_timer_get_time();
|
||||
}
|
||||
|
||||
void SYSTEM_notify_new_ntime(SystemModule* module, uint32_t ntime){
|
||||
void SYSTEM_notify_new_ntime(SystemModule *module, uint32_t ntime)
|
||||
{
|
||||
// Hourly clock sync
|
||||
if(module->lastClockSync + (60 * 60) > ntime){
|
||||
if (module->lastClockSync + (60 * 60) > ntime)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ESP_LOGI(TAG, "Syncing clock");
|
||||
@ -379,14 +410,11 @@ void SYSTEM_notify_new_ntime(SystemModule* module, uint32_t ntime){
|
||||
settimeofday(&tv, NULL);
|
||||
}
|
||||
|
||||
void SYSTEM_notify_found_nonce(SystemModule* module, double pool_diff, double found_diff, uint32_t nbits){
|
||||
|
||||
|
||||
void SYSTEM_notify_found_nonce(SystemModule *module, double pool_diff, double found_diff, uint32_t nbits)
|
||||
{
|
||||
|
||||
// Calculate the time difference in seconds with sub-second precision
|
||||
|
||||
|
||||
|
||||
// hashrate = (nonce_difficulty * 2^32) / time_to_find
|
||||
|
||||
module->historical_hashrate[module->historical_hashrate_rolling_index] = pool_diff;
|
||||
@ -394,27 +422,33 @@ void SYSTEM_notify_found_nonce(SystemModule* module, double pool_diff, double fo
|
||||
|
||||
module->historical_hashrate_rolling_index = (module->historical_hashrate_rolling_index + 1) % HISTORY_LENGTH;
|
||||
|
||||
//ESP_LOGI(TAG, "nonce_diff %.1f, ttf %.1f, res %.1f", nonce_diff, duration, historical_hashrate[historical_hashrate_rolling_index]);
|
||||
// ESP_LOGI(TAG, "nonce_diff %.1f, ttf %.1f, res %.1f", nonce_diff, duration, historical_hashrate[historical_hashrate_rolling_index]);
|
||||
|
||||
|
||||
if(module->historical_hashrate_init < HISTORY_LENGTH){
|
||||
if (module->historical_hashrate_init < HISTORY_LENGTH)
|
||||
{
|
||||
module->historical_hashrate_init++;
|
||||
}else{
|
||||
}
|
||||
else
|
||||
{
|
||||
module->duration_start = module->historical_hashrate_time_stamps[(module->historical_hashrate_rolling_index + 1) % HISTORY_LENGTH];
|
||||
}
|
||||
double sum = 0;
|
||||
for (int i = 0; i < module->historical_hashrate_init; i++) {
|
||||
for (int i = 0; i < module->historical_hashrate_init; i++)
|
||||
{
|
||||
sum += module->historical_hashrate[i];
|
||||
}
|
||||
|
||||
double duration = (double)(esp_timer_get_time() - module->duration_start) / 1000000;
|
||||
|
||||
double rolling_rate = (sum * 4294967296) / (duration * 1000000000);
|
||||
if(module->historical_hashrate_init < HISTORY_LENGTH){
|
||||
if (module->historical_hashrate_init < HISTORY_LENGTH)
|
||||
{
|
||||
module->current_hashrate = rolling_rate;
|
||||
}else{
|
||||
}
|
||||
else
|
||||
{
|
||||
// More smoothing
|
||||
module->current_hashrate = ((module->current_hashrate * 9) + rolling_rate)/10;
|
||||
module->current_hashrate = ((module->current_hashrate * 9) + rolling_rate) / 10;
|
||||
}
|
||||
|
||||
_update_hashrate(module);
|
||||
@ -423,13 +457,4 @@ void SYSTEM_notify_found_nonce(SystemModule* module, double pool_diff, double fo
|
||||
// logArrayContents(historical_hashrate_time_stamps, HISTORY_LENGTH);
|
||||
|
||||
_check_for_best_diff(module, found_diff, nbits);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -5,7 +5,8 @@
|
||||
#define HISTORY_WINDOW_SIZE 5
|
||||
|
||||
#define DIFF_STRING_SIZE 10
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
double duration_start;
|
||||
int historical_hashrate_rolling_index;
|
||||
double historical_hashrate_time_stamps[HISTORY_LENGTH];
|
||||
@ -29,11 +30,10 @@ typedef struct {
|
||||
|
||||
void SYSTEM_task(void *parameters);
|
||||
|
||||
|
||||
void SYSTEM_notify_accepted_share(SystemModule* module);
|
||||
void SYSTEM_notify_rejected_share(SystemModule* module);
|
||||
void SYSTEM_notify_found_nonce(SystemModule* module, double pool_diff, double found_diff, uint32_t nbits);
|
||||
void SYSTEM_notify_mining_started(SystemModule* module);
|
||||
void SYSTEM_notify_new_ntime(SystemModule* module, uint32_t ntime);
|
||||
void SYSTEM_notify_accepted_share(SystemModule *module);
|
||||
void SYSTEM_notify_rejected_share(SystemModule *module);
|
||||
void SYSTEM_notify_found_nonce(SystemModule *module, double pool_diff, double found_diff, uint32_t nbits);
|
||||
void SYSTEM_notify_mining_started(SystemModule *module);
|
||||
void SYSTEM_notify_new_ntime(SystemModule *module, uint32_t ntime);
|
||||
|
||||
#endif /* SYSTEM_H_ */
|
||||
|
@ -7,26 +7,29 @@
|
||||
#include "nvs_config.h"
|
||||
#include "utils.h"
|
||||
|
||||
const char * TAG = "asic_result";
|
||||
const char *TAG = "asic_result";
|
||||
|
||||
void ASIC_result_task(void * pvParameters)
|
||||
void ASIC_result_task(void *pvParameters)
|
||||
{
|
||||
GlobalState *GLOBAL_STATE = (GlobalState*) pvParameters;
|
||||
GlobalState *GLOBAL_STATE = (GlobalState *)pvParameters;
|
||||
SERIAL_clear_buffer();
|
||||
|
||||
char * user = nvs_config_get_string(NVS_CONFIG_STRATUM_USER, STRATUM_USER);
|
||||
char *user = nvs_config_get_string(NVS_CONFIG_STRATUM_USER, STRATUM_USER);
|
||||
|
||||
while(1){
|
||||
while (1)
|
||||
{
|
||||
|
||||
task_result *asic_result = (*GLOBAL_STATE->ASIC_functions.receive_result_fn)(GLOBAL_STATE);
|
||||
|
||||
if(asic_result == NULL){
|
||||
if (asic_result == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
uint8_t job_id = asic_result->job_id;
|
||||
|
||||
if (GLOBAL_STATE->valid_jobs[job_id] == 0) {
|
||||
if (GLOBAL_STATE->valid_jobs[job_id] == 0)
|
||||
{
|
||||
ESP_LOGI(TAG, "Invalid job nonce found, id=%d", job_id);
|
||||
}
|
||||
|
||||
@ -34,8 +37,7 @@ void ASIC_result_task(void * pvParameters)
|
||||
double nonce_diff = test_nonce_value(
|
||||
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id],
|
||||
asic_result->nonce,
|
||||
asic_result->rolled_version
|
||||
);
|
||||
asic_result->rolled_version);
|
||||
|
||||
ESP_LOGI(TAG, "Nonce difficulty %.2f of %ld.", nonce_diff, GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->pool_diff);
|
||||
|
||||
@ -45,9 +47,7 @@ void ASIC_result_task(void * pvParameters)
|
||||
&GLOBAL_STATE->SYSTEM_MODULE,
|
||||
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->pool_diff,
|
||||
nonce_diff,
|
||||
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->target
|
||||
);
|
||||
|
||||
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->target);
|
||||
|
||||
STRATUM_V1_submit_share(
|
||||
GLOBAL_STATE->sock,
|
||||
@ -56,10 +56,7 @@ void ASIC_result_task(void * pvParameters)
|
||||
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->extranonce2,
|
||||
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->ntime,
|
||||
asic_result->nonce,
|
||||
asic_result->rolled_version ^ GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->version
|
||||
);
|
||||
asic_result->rolled_version ^ GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->version);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
#ifndef ASIC_result_TASK_H_
|
||||
#define ASIC_result_TASK_H_
|
||||
|
||||
void ASIC_result_task(void * pvParameters);
|
||||
void ASIC_result_task(void *pvParameters);
|
||||
|
||||
#endif
|
@ -7,49 +7,45 @@
|
||||
|
||||
#include "driver/i2c.h"
|
||||
|
||||
|
||||
static const char *TAG = "ASIC_task";
|
||||
|
||||
// static bm_job ** active_jobs; is required to keep track of the active jobs since the
|
||||
|
||||
|
||||
void ASIC_task(void * pvParameters)
|
||||
void ASIC_task(void *pvParameters)
|
||||
{
|
||||
|
||||
GlobalState *GLOBAL_STATE = (GlobalState*) pvParameters;
|
||||
|
||||
GlobalState *GLOBAL_STATE = (GlobalState *)pvParameters;
|
||||
|
||||
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs = malloc(sizeof(bm_job *) * 128);
|
||||
GLOBAL_STATE->valid_jobs = malloc(sizeof(uint8_t) * 128);
|
||||
for (int i = 0; i < 128; i++) {
|
||||
for (int i = 0; i < 128; i++)
|
||||
{
|
||||
|
||||
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[i] = NULL;
|
||||
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[i] = NULL;
|
||||
GLOBAL_STATE->valid_jobs[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
int baud = (*GLOBAL_STATE->ASIC_functions.set_max_baud_fn)();
|
||||
SERIAL_set_baud(baud);
|
||||
|
||||
SYSTEM_notify_mining_started(&GLOBAL_STATE->SYSTEM_MODULE);
|
||||
ESP_LOGI(TAG, "ASIC Ready!");
|
||||
while (1) {
|
||||
while (1)
|
||||
{
|
||||
|
||||
bm_job * next_bm_job = (bm_job *) queue_dequeue(&GLOBAL_STATE->ASIC_jobs_queue);
|
||||
bm_job *next_bm_job = (bm_job *)queue_dequeue(&GLOBAL_STATE->ASIC_jobs_queue);
|
||||
|
||||
if(next_bm_job->pool_diff != GLOBAL_STATE->stratum_difficulty){
|
||||
//ESP_LOGI(TAG, "New difficulty %d", next_bm_job->pool_diff);
|
||||
if (next_bm_job->pool_diff != GLOBAL_STATE->stratum_difficulty)
|
||||
{
|
||||
// ESP_LOGI(TAG, "New difficulty %d", next_bm_job->pool_diff);
|
||||
(*GLOBAL_STATE->ASIC_functions.set_difficulty_mask_fn)(next_bm_job->pool_diff);
|
||||
GLOBAL_STATE->stratum_difficulty = next_bm_job->pool_diff;
|
||||
}
|
||||
|
||||
(*GLOBAL_STATE->ASIC_functions.send_work_fn)(GLOBAL_STATE, next_bm_job); // send the job to the ASIC
|
||||
|
||||
(*GLOBAL_STATE->ASIC_functions.send_work_fn)(GLOBAL_STATE, next_bm_job); //send the job to the ASIC
|
||||
|
||||
//Time to execute the above code is ~0.3ms
|
||||
//vTaskDelay((BM1397_FULLSCAN_MS - 0.3 ) / portTICK_PERIOD_MS);
|
||||
// Time to execute the above code is ~0.3ms
|
||||
// vTaskDelay((BM1397_FULLSCAN_MS - 0.3 ) / portTICK_PERIOD_MS);
|
||||
vTaskDelay((GLOBAL_STATE->asic_job_frequency_ms - 0.3) / portTICK_PERIOD_MS);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -2,13 +2,14 @@
|
||||
#define ASIC_TASK_H_
|
||||
|
||||
#include "mining.h"
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
// ASIC may not return the nonce in the same order as the jobs were sent
|
||||
// it also may return a previous nonce under some circumstances
|
||||
// so we keep a list of jobs indexed by the job id
|
||||
bm_job ** active_jobs;
|
||||
// it also may return a previous nonce under some circumstances
|
||||
// so we keep a list of jobs indexed by the job id
|
||||
bm_job **active_jobs;
|
||||
} AsicTaskModule;
|
||||
|
||||
void ASIC_task(void * pvParameters);
|
||||
void ASIC_task(void *pvParameters);
|
||||
|
||||
#endif
|
@ -10,27 +10,27 @@
|
||||
|
||||
static const char *TAG = "create_jobs_task";
|
||||
|
||||
void create_jobs_task(void * pvParameters)
|
||||
void create_jobs_task(void *pvParameters)
|
||||
{
|
||||
|
||||
GlobalState *GLOBAL_STATE = (GlobalState*)pvParameters;
|
||||
GlobalState *GLOBAL_STATE = (GlobalState *)pvParameters;
|
||||
|
||||
|
||||
while (1) {
|
||||
mining_notify * mining_notification = (mining_notify *) queue_dequeue(&GLOBAL_STATE->stratum_queue);
|
||||
while (1)
|
||||
{
|
||||
mining_notify *mining_notification = (mining_notify *)queue_dequeue(&GLOBAL_STATE->stratum_queue);
|
||||
ESP_LOGI(TAG, "New Work Dequeued %s", mining_notification->job_id);
|
||||
|
||||
uint32_t extranonce_2 = 0;
|
||||
while (GLOBAL_STATE->stratum_queue.count < 1 && extranonce_2 < UINT_MAX && GLOBAL_STATE->abandon_work == 0)
|
||||
{
|
||||
char * extranonce_2_str = extranonce_2_generate(extranonce_2, GLOBAL_STATE->extranonce_2_len);
|
||||
char *extranonce_2_str = extranonce_2_generate(extranonce_2, GLOBAL_STATE->extranonce_2_len);
|
||||
|
||||
char *coinbase_tx = construct_coinbase_tx(mining_notification->coinbase_1, mining_notification->coinbase_2, GLOBAL_STATE->extranonce_str, extranonce_2_str);
|
||||
|
||||
char *merkle_root = calculate_merkle_root_hash(coinbase_tx, (uint8_t(*)[32])mining_notification->merkle_branches, mining_notification->n_merkle_branches);
|
||||
bm_job next_job = construct_bm_job(mining_notification, merkle_root, GLOBAL_STATE->version_mask);
|
||||
|
||||
bm_job * queued_next_job = malloc(sizeof(bm_job));
|
||||
bm_job *queued_next_job = malloc(sizeof(bm_job));
|
||||
memcpy(queued_next_job, &next_job, sizeof(bm_job));
|
||||
queued_next_job->extranonce2 = strdup(extranonce_2_str);
|
||||
queued_next_job->jobid = strdup(mining_notification->job_id);
|
||||
@ -44,7 +44,8 @@ void create_jobs_task(void * pvParameters)
|
||||
extranonce_2++;
|
||||
}
|
||||
|
||||
if (GLOBAL_STATE->abandon_work == 1) {
|
||||
if (GLOBAL_STATE->abandon_work == 1)
|
||||
{
|
||||
GLOBAL_STATE->abandon_work = 0;
|
||||
ASIC_jobs_queue_clear(&GLOBAL_STATE->ASIC_jobs_queue);
|
||||
}
|
||||
@ -52,6 +53,3 @@ void create_jobs_task(void * pvParameters)
|
||||
STRATUM_V1_free_mining_notify(mining_notification);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#ifndef CREATE_JOBS_TASK_H_
|
||||
#define CREATE_JOBS_TASK_H_
|
||||
|
||||
void create_jobs_task(void * pvParameters);
|
||||
void create_jobs_task(void *pvParameters);
|
||||
|
||||
#endif
|
||||
#endif
|
@ -1,7 +1,8 @@
|
||||
#ifndef POWER_MANAGEMENT_TASK_H_
|
||||
#define POWER_MANAGEMENT_TASK_H_
|
||||
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
uint16_t fan_speed;
|
||||
float chip_temp;
|
||||
float voltage;
|
||||
@ -11,6 +12,6 @@ typedef struct {
|
||||
float current;
|
||||
} PowerManagementModule;
|
||||
|
||||
void POWER_MANAGEMENT_task(void * pvParameters);
|
||||
void POWER_MANAGEMENT_task(void *pvParameters);
|
||||
|
||||
#endif
|
@ -1,5 +1,5 @@
|
||||
#include "esp_log.h"
|
||||
//#include "addr_from_stdin.h"
|
||||
// #include "addr_from_stdin.h"
|
||||
#include "connect.h"
|
||||
#include "lwip/dns.h"
|
||||
#include "work_queue.h"
|
||||
@ -23,39 +23,42 @@ static bool bDNSFound = false;
|
||||
static StratumApiV1Message stratum_api_v1_message = {};
|
||||
|
||||
static SystemTaskModule SYSTEM_TASK_MODULE = {
|
||||
.stratum_difficulty = 8192
|
||||
};
|
||||
.stratum_difficulty = 8192};
|
||||
|
||||
void dns_found_cb(const char * name, const ip_addr_t * ipaddr, void * callback_arg)
|
||||
void dns_found_cb(const char *name, const ip_addr_t *ipaddr, void *callback_arg)
|
||||
{
|
||||
ip_Addr = *ipaddr;
|
||||
bDNSFound = true;
|
||||
}
|
||||
|
||||
void stratum_task(void * pvParameters)
|
||||
void stratum_task(void *pvParameters)
|
||||
{
|
||||
GlobalState *GLOBAL_STATE = (GlobalState*)pvParameters;
|
||||
GlobalState *GLOBAL_STATE = (GlobalState *)pvParameters;
|
||||
|
||||
STRATUM_V1_initialize_buffer();
|
||||
char host_ip[20];
|
||||
int addr_family = 0;
|
||||
int ip_protocol = 0;
|
||||
|
||||
char * stratum_url = nvs_config_get_string(NVS_CONFIG_STRATUM_URL, STRATUM_URL);
|
||||
char *stratum_url = nvs_config_get_string(NVS_CONFIG_STRATUM_URL, STRATUM_URL);
|
||||
uint16_t port = nvs_config_get_u16(NVS_CONFIG_STRATUM_PORT, PORT);
|
||||
|
||||
//check to see if the STRATUM_URL is an ip address already
|
||||
if (inet_pton(AF_INET, stratum_url, &ip_Addr) == 1) {
|
||||
// check to see if the STRATUM_URL is an ip address already
|
||||
if (inet_pton(AF_INET, stratum_url, &ip_Addr) == 1)
|
||||
{
|
||||
bDNSFound = true;
|
||||
} else {
|
||||
//it's a hostname. Lookup the ip address.
|
||||
}
|
||||
else
|
||||
{
|
||||
// it's a hostname. Lookup the ip address.
|
||||
IP_ADDR4(&ip_Addr, 0, 0, 0, 0);
|
||||
ESP_LOGI(TAG, "Get IP for URL: %s\n", stratum_url);
|
||||
dns_gethostbyname(stratum_url, &ip_Addr, dns_found_cb, NULL);
|
||||
while (!bDNSFound);
|
||||
while (!bDNSFound)
|
||||
;
|
||||
}
|
||||
|
||||
//make IP address string from ip_Addr
|
||||
// make IP address string from ip_Addr
|
||||
snprintf(host_ip, sizeof(host_ip), "%d.%d.%d.%d",
|
||||
ip4_addr1(&ip_Addr.u_addr.ip4),
|
||||
ip4_addr2(&ip_Addr.u_addr.ip4),
|
||||
@ -64,7 +67,8 @@ void stratum_task(void * pvParameters)
|
||||
ESP_LOGI(TAG, "Connecting to: stratum+tcp://%s:%d (%s)\n", stratum_url, port, host_ip);
|
||||
free(stratum_url);
|
||||
|
||||
while (1) {
|
||||
while (1)
|
||||
{
|
||||
struct sockaddr_in dest_addr;
|
||||
dest_addr.sin_addr.s_addr = inet_addr(host_ip);
|
||||
dest_addr.sin_family = AF_INET;
|
||||
@ -93,7 +97,7 @@ void stratum_task(void * pvParameters)
|
||||
|
||||
STRATUM_V1_configure_version_rolling(GLOBAL_STATE->sock);
|
||||
|
||||
char * username = nvs_config_get_string(NVS_CONFIG_STRATUM_USER, STRATUM_USER);
|
||||
char *username = nvs_config_get_string(NVS_CONFIG_STRATUM_USER, STRATUM_USER);
|
||||
STRATUM_V1_authenticate(GLOBAL_STATE->sock, username);
|
||||
free(username);
|
||||
|
||||
@ -104,15 +108,16 @@ void stratum_task(void * pvParameters)
|
||||
|
||||
while (1)
|
||||
{
|
||||
char * line = STRATUM_V1_receive_jsonrpc_line( GLOBAL_STATE->sock);
|
||||
ESP_LOGI(TAG, "rx: %s", line); //debug incoming stratum messages
|
||||
char *line = STRATUM_V1_receive_jsonrpc_line(GLOBAL_STATE->sock);
|
||||
ESP_LOGI(TAG, "rx: %s", line); // debug incoming stratum messages
|
||||
STRATUM_V1_parse(&stratum_api_v1_message, line);
|
||||
free(line);
|
||||
|
||||
|
||||
if (stratum_api_v1_message.method == MINING_NOTIFY) {
|
||||
if (stratum_api_v1_message.method == MINING_NOTIFY)
|
||||
{
|
||||
SYSTEM_notify_new_ntime(&GLOBAL_STATE->SYSTEM_MODULE, stratum_api_v1_message.mining_notification->ntime);
|
||||
if (stratum_api_v1_message.should_abandon_work && (GLOBAL_STATE->stratum_queue.count > 0 || GLOBAL_STATE->ASIC_jobs_queue.count > 0)) {
|
||||
if (stratum_api_v1_message.should_abandon_work && (GLOBAL_STATE->stratum_queue.count > 0 || GLOBAL_STATE->ASIC_jobs_queue.count > 0))
|
||||
{
|
||||
ESP_LOGI(TAG, "abandoning work");
|
||||
|
||||
GLOBAL_STATE->abandon_work = 1;
|
||||
@ -120,35 +125,44 @@ void stratum_task(void * pvParameters)
|
||||
|
||||
pthread_mutex_lock(&GLOBAL_STATE->valid_jobs_lock);
|
||||
ASIC_jobs_queue_clear(&GLOBAL_STATE->ASIC_jobs_queue);
|
||||
for (int i = 0; i < 128; i = i + 4) {
|
||||
GLOBAL_STATE->valid_jobs[i] = 0;
|
||||
for (int i = 0; i < 128; i = i + 4)
|
||||
{
|
||||
GLOBAL_STATE->valid_jobs[i] = 0;
|
||||
}
|
||||
pthread_mutex_unlock(&GLOBAL_STATE->valid_jobs_lock);
|
||||
}
|
||||
if (GLOBAL_STATE->stratum_queue.count == QUEUE_SIZE) {
|
||||
mining_notify * next_notify_json_str = (mining_notify *) queue_dequeue(&GLOBAL_STATE->stratum_queue);
|
||||
if (GLOBAL_STATE->stratum_queue.count == QUEUE_SIZE)
|
||||
{
|
||||
mining_notify *next_notify_json_str = (mining_notify *)queue_dequeue(&GLOBAL_STATE->stratum_queue);
|
||||
STRATUM_V1_free_mining_notify(next_notify_json_str);
|
||||
}
|
||||
|
||||
stratum_api_v1_message.mining_notification->difficulty = SYSTEM_TASK_MODULE.stratum_difficulty;
|
||||
queue_enqueue(&GLOBAL_STATE->stratum_queue, stratum_api_v1_message.mining_notification);
|
||||
|
||||
} else if (stratum_api_v1_message.method == MINING_SET_DIFFICULTY) {
|
||||
if (stratum_api_v1_message.new_difficulty != SYSTEM_TASK_MODULE.stratum_difficulty) {
|
||||
}
|
||||
else if (stratum_api_v1_message.method == MINING_SET_DIFFICULTY)
|
||||
{
|
||||
if (stratum_api_v1_message.new_difficulty != SYSTEM_TASK_MODULE.stratum_difficulty)
|
||||
{
|
||||
SYSTEM_TASK_MODULE.stratum_difficulty = stratum_api_v1_message.new_difficulty;
|
||||
ESP_LOGI(TAG, "Set stratum difficulty: %ld", SYSTEM_TASK_MODULE.stratum_difficulty);
|
||||
}
|
||||
|
||||
} else if (stratum_api_v1_message.method == MINING_SET_VERSION_MASK || stratum_api_v1_message.method == STRATUM_RESULT_VERSION_MASK) {
|
||||
//1fffe000
|
||||
}
|
||||
else if (stratum_api_v1_message.method == MINING_SET_VERSION_MASK || stratum_api_v1_message.method == STRATUM_RESULT_VERSION_MASK)
|
||||
{
|
||||
// 1fffe000
|
||||
ESP_LOGI(TAG, "Set version mask: %08lx", stratum_api_v1_message.version_mask);
|
||||
GLOBAL_STATE->version_mask = stratum_api_v1_message.version_mask;
|
||||
|
||||
} else if (stratum_api_v1_message.method == STRATUM_RESULT) {
|
||||
if (stratum_api_v1_message.response_success) {
|
||||
}
|
||||
else if (stratum_api_v1_message.method == STRATUM_RESULT)
|
||||
{
|
||||
if (stratum_api_v1_message.response_success)
|
||||
{
|
||||
ESP_LOGI(TAG, "message result accepted");
|
||||
SYSTEM_notify_accepted_share(&GLOBAL_STATE->SYSTEM_MODULE);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGE(TAG, "message result rejected");
|
||||
SYSTEM_notify_rejected_share(&GLOBAL_STATE->SYSTEM_MODULE);
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
#ifndef STRATUM_TASK_H_
|
||||
#define STRATUM_TASK_H_
|
||||
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
uint32_t stratum_difficulty;
|
||||
} SystemTaskModule;
|
||||
|
||||
void stratum_task(void * pvParameters);
|
||||
void stratum_task(void *pvParameters);
|
||||
|
||||
#endif
|
||||
#endif
|
@ -6,22 +6,27 @@
|
||||
|
||||
#define BUTTON_BOOT GPIO_NUM_0
|
||||
|
||||
static const char * TAG = "user_input";
|
||||
static const char *TAG = "user_input";
|
||||
static bool button_being_pressed = false;
|
||||
|
||||
void USER_INPUT_task(void * pvParameters){
|
||||
void USER_INPUT_task(void *pvParameters)
|
||||
{
|
||||
|
||||
gpio_set_direction(BUTTON_BOOT, GPIO_MODE_INPUT);
|
||||
|
||||
while(1) {
|
||||
if (gpio_get_level(BUTTON_BOOT) == 0 && button_being_pressed == false) { // If button is pressed
|
||||
while (1)
|
||||
{
|
||||
if (gpio_get_level(BUTTON_BOOT) == 0 && button_being_pressed == false)
|
||||
{ // If button is pressed
|
||||
ESP_LOGI(TAG, "BUTTON PRESSED");
|
||||
button_being_pressed = true;
|
||||
toggle_wifi_softap();
|
||||
} else if (gpio_get_level(BUTTON_BOOT) == 1 && button_being_pressed == true){
|
||||
}
|
||||
else if (gpio_get_level(BUTTON_BOOT) == 1 && button_being_pressed == true)
|
||||
{
|
||||
button_being_pressed = false;
|
||||
}
|
||||
|
||||
vTaskDelay(30/portTICK_PERIOD_MS); // Add delay so that current task does not starve idle task and trigger watchdog timer
|
||||
vTaskDelay(30 / portTICK_PERIOD_MS); // Add delay so that current task does not starve idle task and trigger watchdog timer
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
#ifndef USER_INPUT_TASK_H_
|
||||
#define USER_INPUT_TASK_H_
|
||||
|
||||
|
||||
void USER_INPUT_task(void * pvParameters);
|
||||
void USER_INPUT_task(void *pvParameters);
|
||||
|
||||
#endif
|
@ -1,7 +1,8 @@
|
||||
#include "work_queue.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
void queue_init(work_queue * queue) {
|
||||
void queue_init(work_queue *queue)
|
||||
{
|
||||
queue->head = 0;
|
||||
queue->tail = 0;
|
||||
queue->count = 0;
|
||||
@ -10,10 +11,12 @@ void queue_init(work_queue * queue) {
|
||||
pthread_cond_init(&queue->not_full, NULL);
|
||||
}
|
||||
|
||||
void queue_enqueue(work_queue * queue, void * new_work) {
|
||||
void queue_enqueue(work_queue *queue, void *new_work)
|
||||
{
|
||||
pthread_mutex_lock(&queue->lock);
|
||||
|
||||
while (queue->count == QUEUE_SIZE) {
|
||||
while (queue->count == QUEUE_SIZE)
|
||||
{
|
||||
pthread_cond_wait(&queue->not_full, &queue->lock);
|
||||
}
|
||||
|
||||
@ -25,14 +28,16 @@ void queue_enqueue(work_queue * queue, void * new_work) {
|
||||
pthread_mutex_unlock(&queue->lock);
|
||||
}
|
||||
|
||||
void * queue_dequeue(work_queue * queue) {
|
||||
void *queue_dequeue(work_queue *queue)
|
||||
{
|
||||
pthread_mutex_lock(&queue->lock);
|
||||
|
||||
while (queue->count == 0) {
|
||||
while (queue->count == 0)
|
||||
{
|
||||
pthread_cond_wait(&queue->not_empty, &queue->lock);
|
||||
}
|
||||
|
||||
void * next_work = queue->buffer[queue->head];
|
||||
void *next_work = queue->buffer[queue->head];
|
||||
queue->head = (queue->head + 1) % QUEUE_SIZE;
|
||||
queue->count--;
|
||||
|
||||
@ -42,13 +47,13 @@ void * queue_dequeue(work_queue * queue) {
|
||||
return next_work;
|
||||
}
|
||||
|
||||
void queue_clear(work_queue * queue)
|
||||
void queue_clear(work_queue *queue)
|
||||
{
|
||||
pthread_mutex_lock(&queue->lock);
|
||||
|
||||
while (queue->count > 0)
|
||||
{
|
||||
mining_notify * next_work = queue->buffer[queue->head];
|
||||
mining_notify *next_work = queue->buffer[queue->head];
|
||||
STRATUM_V1_free_mining_notify(next_work);
|
||||
queue->head = (queue->head + 1) % QUEUE_SIZE;
|
||||
queue->count--;
|
||||
@ -58,13 +63,13 @@ void queue_clear(work_queue * queue)
|
||||
pthread_mutex_unlock(&queue->lock);
|
||||
}
|
||||
|
||||
void ASIC_jobs_queue_clear(work_queue * queue)
|
||||
void ASIC_jobs_queue_clear(work_queue *queue)
|
||||
{
|
||||
pthread_mutex_lock(&queue->lock);
|
||||
|
||||
while (queue->count > 0)
|
||||
{
|
||||
bm_job * next_work = queue->buffer[queue->head];
|
||||
bm_job *next_work = queue->buffer[queue->head];
|
||||
free(next_work->jobid);
|
||||
free(next_work->extranonce2);
|
||||
free(next_work);
|
||||
|
@ -6,8 +6,9 @@
|
||||
|
||||
#define QUEUE_SIZE 12
|
||||
|
||||
typedef struct {
|
||||
void * buffer[QUEUE_SIZE];
|
||||
typedef struct
|
||||
{
|
||||
void *buffer[QUEUE_SIZE];
|
||||
int head;
|
||||
int tail;
|
||||
int count;
|
||||
@ -16,10 +17,10 @@ typedef struct {
|
||||
pthread_cond_t not_full;
|
||||
} work_queue;
|
||||
|
||||
void queue_init(work_queue * queue);
|
||||
void queue_enqueue(work_queue * queue, void * new_work);
|
||||
void ASIC_jobs_queue_clear(work_queue * queue);
|
||||
void * queue_dequeue(work_queue * queue);
|
||||
void queue_clear(work_queue * queue);
|
||||
void queue_init(work_queue *queue);
|
||||
void queue_enqueue(work_queue *queue, void *new_work);
|
||||
void ASIC_jobs_queue_clear(work_queue *queue);
|
||||
void *queue_dequeue(work_queue *queue);
|
||||
void queue_clear(work_queue *queue);
|
||||
|
||||
#endif // WORK_QUEUE_H
|
@ -2,7 +2,7 @@
|
||||
#include <string.h>
|
||||
#include "unity.h"
|
||||
|
||||
static void print_banner(const char* text);
|
||||
static void print_banner(const char *text);
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
@ -18,7 +18,7 @@ void app_main(void)
|
||||
unity_run_menu();
|
||||
}
|
||||
|
||||
static void print_banner(const char* text)
|
||||
static void print_banner(const char *text)
|
||||
{
|
||||
printf("\n#### %s #####\n\n", text);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user