1
0
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:
Ben 2023-08-26 12:28:17 -04:00
parent 199c151c0f
commit 79430f6d3a
51 changed files with 2042 additions and 1705 deletions

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(&notify_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(&notify_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(&notify_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, &reg_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, &reg_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, &reg_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, &reg_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, &reg_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);

@ -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);
}

@ -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));

@ -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

@ -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

@ -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);
}