Merge pull request #3 from shufps/debug-output

Debug output
This commit is contained in:
Thomas Shufps 2024-09-13 20:45:11 +02:00 committed by GitHub
commit 8251f462a1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 109 additions and 76 deletions

View File

@ -48,9 +48,6 @@ typedef struct __attribute__((__packed__))
static const char *TAG = "bm1397Module"; static const char *TAG = "bm1397Module";
static uint8_t asic_response_buffer[CHUNK_SIZE];
static task_result result;
uint32_t increment_bitmask(const uint32_t value, const uint32_t mask); uint32_t increment_bitmask(const uint32_t value, const uint32_t mask);
/// @brief /// @brief
@ -195,7 +192,7 @@ void BM1397_send_hash_frequency(float frequency)
vTaskDelay(10 / portTICK_PERIOD_MS); vTaskDelay(10 / portTICK_PERIOD_MS);
ESP_LOGI(TAG, "Setting Frequency to %.2fMHz (%.2f)", frequency, newf); Serial.printf("Setting Frequency to %.2fMHz (%.2f)\n", frequency, newf);
} }
@ -203,18 +200,19 @@ static uint8_t _send_init(uint64_t frequency, uint16_t asic_count)
{ {
// send the init command // send the init command
_send_read_address(); _send_read_address();
uint8_t buf[11] = {0};
int chip_counter = 0; int chip_counter = 0;
while (true) { while (true) {
int received = SERIAL_rx(asic_response_buffer, 11, 1000); int received = SERIAL_rx(buf, 11, 1000);
if (received > 0) { if (received > 0) {
ESP_LOG_BUFFER_HEX(TAG, asic_response_buffer, received); //ESP_LOG_BUFFER_HEX(TAG, asic_response_buffer, received);
chip_counter++; chip_counter++;
} else { } else {
break; break;
} }
} }
ESP_LOGI(TAG, "%i chip(s) detected on the chain, expected %i", chip_counter, asic_count); Serial.printf("%i chip(s) detected on the chain, expected %i\n", chip_counter, asic_count);
// send serial data // send serial data
vTaskDelay(SLEEP_TIME / portTICK_PERIOD_MS); vTaskDelay(SLEEP_TIME / portTICK_PERIOD_MS);
@ -269,9 +267,7 @@ static void _reset(void)
uint8_t BM1397_init(uint64_t frequency, uint16_t asic_count) uint8_t BM1397_init(uint64_t frequency, uint16_t asic_count)
{ {
ESP_LOGI(TAG, "Initializing BM1397"); Serial.println("Initializing BM1397");
memset(asic_response_buffer, 0, sizeof(asic_response_buffer));
gpio_set_direction(NERD_NOS_GPIO_PEN, GPIO_MODE_OUTPUT); gpio_set_direction(NERD_NOS_GPIO_PEN, GPIO_MODE_OUTPUT);
gpio_set_level(NERD_NOS_GPIO_PEN, 1); gpio_set_level(NERD_NOS_GPIO_PEN, 1);
@ -299,7 +295,7 @@ int BM1397_set_default_baud(void)
int BM1397_set_max_baud(void) int BM1397_set_max_baud(void)
{ {
// divider of 0 for 3,125,000 // divider of 0 for 3,125,000
ESP_LOGI(TAG, "Setting max baud of 3125000"); Serial.println("Setting max baud of 3125000");
unsigned char baudrate[9] = {0x00, MISC_CONTROL, 0x00, 0x00, 0b01100000, 0b00110001}; unsigned char baudrate[9] = {0x00, MISC_CONTROL, 0x00, 0x00, 0b01100000, 0b00110001};
; // baudrate - misc_control ; // baudrate - misc_control
_send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), baudrate, 6, BM1397_SERIALTX_DEBUG); _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), baudrate, 6, BM1397_SERIALTX_DEBUG);
@ -330,7 +326,7 @@ void BM1397_set_job_difficulty_mask(int difficulty)
job_difficulty_mask[5 - i] = reverse_bits(value); job_difficulty_mask[5 - i] = reverse_bits(value);
} }
ESP_LOGI(TAG, "Setting job ASIC mask to %d", difficulty); Serial.printf("Setting job ASIC mask to %d\n", difficulty);
_send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), job_difficulty_mask, 6, BM1397_SERIALTX_DEBUG); _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_WRITE), job_difficulty_mask, 6, BM1397_SERIALTX_DEBUG);
} }
@ -361,45 +357,47 @@ void BM1397_send_work(bm_job_t *next_bm_job, uint8_t job_id)
_send_BM1397((TYPE_JOB | GROUP_SINGLE | CMD_WRITE), (uint8_t*) &job, sizeof(job_packet_t), BM1397_DEBUG_WORK); _send_BM1397((TYPE_JOB | GROUP_SINGLE | CMD_WRITE), (uint8_t*) &job, sizeof(job_packet_t), BM1397_DEBUG_WORK);
} }
asic_result *BM1397_receive_work(uint16_t timeout) bool BM1397_receive_work(uint16_t timeout, asic_result *result)
{ {
uint8_t *rcv_buf = (uint8_t*) result;
// 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, timeout); int received = SERIAL_rx(rcv_buf, 9, timeout);
if (received < 0) if (received < 0)
{ {
ESP_LOGI(TAG, "Error in serial RX"); Serial.println("Error in serial RX");
return NULL; return false;
} }
else if (received == 0) else if (received == 0)
{ {
// Didn't find a solution, restart and try again // Didn't find a solution, restart and try again
return NULL; return false;
} }
if (received != 9 || asic_response_buffer[0] != 0xAA || asic_response_buffer[1] != 0x55) if (received != 9 || rcv_buf[0] != 0xAA || rcv_buf[1] != 0x55)
{ {
ESP_LOGI(TAG, "Serial RX invalid %i", received); Serial.println("Serial RX invalid. Resetting receive buffer ...");
ESP_LOG_BUFFER_HEX(TAG, asic_response_buffer, received); //ESP_LOG_BUFFER_HEX(TAG, asic_response_buffer, received);
return NULL; SERIAL_clear_buffer();
return false;
}
return true;
} }
return (asic_result *)asic_response_buffer; bool BM1397_proccess_work(uint32_t version, uint16_t timeout, task_result *result)
}
task_result *BM1397_proccess_work(uint32_t version, uint16_t timeout)
{ {
asic_result *asic_result = BM1397_receive_work(timeout); asic_result asic_result;
if (asic_result == NULL) if (!BM1397_receive_work(timeout, &asic_result))
{ {
ESP_LOGI(TAG, "return null"); ESP_LOGI(TAG, "return null");
return NULL; return false;
} }
uint8_t rx_job_id = (asic_result->job_id & 0xfc) >> 2; uint8_t rx_job_id = (asic_result.job_id & 0xfc) >> 2;
uint8_t rx_midstate_index = asic_result->job_id & 0x03; uint8_t rx_midstate_index = asic_result.job_id & 0x03;
uint32_t rolled_version = version; uint32_t rolled_version = version;
for (int i = 0; i < rx_midstate_index; i++) for (int i = 0; i < rx_midstate_index; i++)
@ -407,10 +405,10 @@ task_result *BM1397_proccess_work(uint32_t version, uint16_t timeout)
rolled_version = increment_bitmask(rolled_version, 0x1fffe000); rolled_version = increment_bitmask(rolled_version, 0x1fffe000);
} }
result.job_id = rx_job_id; result->job_id = rx_job_id;
result.nonce = asic_result->nonce; result->nonce = asic_result.nonce;
result.rolled_version = rolled_version; result->rolled_version = rolled_version;
return &result; return true;
} }

View File

@ -17,5 +17,5 @@ void BM1397_set_job_difficulty_mask(int);
int BM1397_set_max_baud(void); int BM1397_set_max_baud(void);
int BM1397_set_default_baud(void); int BM1397_set_default_baud(void);
void BM1397_send_hash_frequency(float frequency); void BM1397_send_hash_frequency(float frequency);
task_result *BM1397_proccess_work(uint32_t version, uint16_t timeout); bool BM1397_proccess_work(uint32_t version, uint16_t timeout, task_result *result);

View File

@ -62,8 +62,9 @@ static void calculate_merkle_root_hash(const char *coinbase_tx, mining_job* job,
double_sha256_bin(coinbase_tx_bin, coinbase_tx_bin_len, new_root); double_sha256_bin(coinbase_tx_bin, coinbase_tx_bin_len, new_root);
memcpy(both_merkles, new_root, 32); memcpy(both_merkles, new_root, 32);
for (size_t i = 0; i < job->merkle_branch.size(); i++) { for (size_t i = 0; i < job->merkle_branch_size; i++) {
hex2bin((const char*) job->merkle_branch[i], &both_merkles[32], 32); const char* m = job->merkle_branch[i].c_str();
hex2bin(m, &both_merkles[32], 32);
double_sha256_bin(both_merkles, 64, new_root); double_sha256_bin(both_merkles, 64, new_root);
memcpy(both_merkles, new_root, 32); memcpy(both_merkles, new_root, 32);
} }
@ -140,8 +141,8 @@ void nerdnos_send_work(bm_job_t *next_bm_job, uint8_t job_id) {
BM1397_send_work(next_bm_job, job_id); BM1397_send_work(next_bm_job, job_id);
} }
task_result *nerdnos_proccess_work(uint32_t version, uint16_t timeout) { bool nerdnos_proccess_work(uint32_t version, uint16_t timeout, task_result *result) {
return BM1397_proccess_work(version, timeout); return BM1397_proccess_work(version, timeout, result);
} }
void nerdnos_free_bm_job(bm_job_t *job) { void nerdnos_free_bm_job(bm_job_t *job) {

View File

@ -16,7 +16,7 @@ void nerdnos_create_job(mining_subscribe *mWorker, mining_job *job, bm_job_t *ne
void nerdnos_send_work(bm_job_t *next_bm_job, uint8_t job_id); void nerdnos_send_work(bm_job_t *next_bm_job, uint8_t job_id);
// receive and process responses // receive and process responses
task_result *nerdnos_proccess_work(uint32_t version, uint16_t timeout); bool nerdnos_proccess_work(uint32_t version, uint16_t timeout, task_result *result);
// test difficulty // test difficulty
double nerdnos_test_nonce_value(const bm_job_t *job, const uint32_t nonce, const uint32_t rolled_version, uint8_t hash_result[32]); double nerdnos_test_nonce_value(const bm_job_t *job, const uint32_t nonce, const uint32_t rolled_version, uint8_t hash_result[32]);

View File

@ -51,8 +51,8 @@ int SERIAL_send(uint8_t *data, int len, bool debug)
return uart_write_bytes(UART_NUM_1, (const char *)data, len); return uart_write_bytes(UART_NUM_1, (const char *)data, len);
} }
int SERIAL_check_for_data() { size_t SERIAL_check_for_data() {
int length; size_t length;
uart_get_buffered_data_len(UART_NUM_1, (size_t*)&length); uart_get_buffered_data_len(UART_NUM_1, (size_t*)&length);
return length; return length;
} }
@ -65,7 +65,9 @@ int SERIAL_check_for_data() {
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)
{ {
// don't return incomplete data // don't return incomplete data
if (SERIAL_check_for_data() < size) { size_t available = SERIAL_check_for_data();
if (available && available < size) {
Serial.printf("not returning parts of data ... %d vs %d\n", (int) available, (int) size);
return 0; return 0;
} }

View File

@ -127,6 +127,24 @@ uint8_t hex2val(char c)
} }
} }
bool is_hex_digit(char c) {
return ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
}
bool is_hex_string(const char* str) {
// Check if the string is exactly 64 characters long
if (strlen(str) != 64) {
return false;
}
// Check if each character is a valid hexadecimal digit
for (size_t i = 0; i < 64; i++) {
if (!is_hex_digit(str[i])) {
return false;
}
}
return true;
}
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)
{ {
size_t len = 0; size_t len = 0;

View File

@ -2,6 +2,7 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
int hex2char(uint8_t x, char *c); int hex2char(uint8_t x, char *c);
@ -38,3 +39,6 @@ unsigned char reverse_bits(unsigned char num);
int largest_power_of_two(int num); int largest_power_of_two(int num);
uint32_t increment_bitmask(const uint32_t value, const uint32_t mask); uint32_t increment_bitmask(const uint32_t value, const uint32_t mask);
bool is_hex_digit(char c);
bool is_hex_string(const char* str);

View File

@ -40,7 +40,7 @@ static bm_job_t asic_jobs[ASIC_JOB_COUNT] = {0};
typedef struct { typedef struct {
uint32_t diffs[ASIC_HISTORY_SIZE]; uint32_t diffs[ASIC_HISTORY_SIZE];
uint32_t timestamps[ASIC_HISTORY_SIZE]; uint64_t timestamps[ASIC_HISTORY_SIZE];
uint32_t newest; uint32_t newest;
uint32_t oldest; uint32_t oldest;
uint64_t sum; uint64_t sum;
@ -78,7 +78,7 @@ static void calculate_hashrate(history_t *history, uint32_t diff) {
history->diffs[history->newest % ASIC_HISTORY_SIZE] = diff; history->diffs[history->newest % ASIC_HISTORY_SIZE] = diff;
// micros() wraps around after about 71.58min because it's 32bit casted from 64bit timer :facepalm: // micros() wraps around after about 71.58min because it's 32bit casted from 64bit timer :facepalm:
history->timestamps[history->newest % ASIC_HISTORY_SIZE] = esp_timer_get_time(); history->timestamps[history->newest % ASIC_HISTORY_SIZE] = (uint64_t) esp_timer_get_time();
uint64_t oldest_timestamp = history->timestamps[history->oldest % ASIC_HISTORY_SIZE]; uint64_t oldest_timestamp = history->timestamps[history->oldest % ASIC_HISTORY_SIZE];
uint64_t newest_timestamp = history->timestamps[history->newest % ASIC_HISTORY_SIZE]; uint64_t newest_timestamp = history->timestamps[history->newest % ASIC_HISTORY_SIZE];
@ -172,15 +172,11 @@ void runASIC(void * task_id) {
// send the job and // send the job and
nerdnos_send_work(&asic_jobs[asic_job_id], asic_job_id); nerdnos_send_work(&asic_jobs[asic_job_id], asic_job_id);
// the pointer returned is the RS232 receive buffer :shushing-face: task_result result = {0};
// but we only have a single thread so it should be okay while (nerdnos_proccess_work(version, 1, &result)) {
// process all results if we have more than one
// this is okay because serial uses a buffer and (most likely^^) DMA
task_result *result = NULL;
while ((result = nerdnos_proccess_work(version, 1)) != NULL) {
// check if the ID is in the valid range and the slot is not empty // check if the ID is in the valid range and the slot is not empty
if (result->job_id >= ASIC_JOB_COUNT || !asic_jobs[result->job_id].ntime) { if (result.job_id >= ASIC_JOB_COUNT || !asic_jobs[result.job_id].ntime) {
Serial.printf("Invalid job ID or no job found for ID %02x\n", result->job_id); Serial.printf("Invalid job ID or no job found for ID %02x\n", result.job_id);
continue; continue;
} }
@ -188,9 +184,9 @@ void runASIC(void * task_id) {
// check the nonce difficulty // check the nonce difficulty
double diff_hash = nerdnos_test_nonce_value( double diff_hash = nerdnos_test_nonce_value(
&asic_jobs[result->job_id], &asic_jobs[result.job_id],
result->nonce, result.nonce,
result->rolled_version, result.rolled_version,
hash); hash);
// update best diff // update best diff
@ -199,14 +195,14 @@ void runASIC(void * task_id) {
} }
// calculate the hashrate // calculate the hashrate
if (diff_hash >= asic_jobs[result->job_id].pool_diff) { if (diff_hash >= asic_jobs[result.job_id].pool_diff) {
calculate_hashrate(&history, asic_jobs[result->job_id].pool_diff); calculate_hashrate(&history, asic_jobs[result.job_id].pool_diff);
Serial.printf("avg hashrate: %.2fGH/s (history spans %.2fs, %d shares)\n", history.avg_gh, history.duration, history.shares); Serial.printf("avg hashrate: %.2fGH/s (history spans %.2fs, %d shares)\n", history.avg_gh, history.duration, history.shares);
} }
if(diff_hash > mMiner.poolDifficulty) if(diff_hash > mMiner.poolDifficulty)
{ {
tx_mining_submit_asic(client, mWorker, &asic_jobs[result->job_id], result); tx_mining_submit_asic(client, mWorker, &asic_jobs[result.job_id], &result);
Serial.println("valid share!"); Serial.println("valid share!");
Serial.printf(" - Current diff share: %.3f\n", diff_hash); Serial.printf(" - Current diff share: %.3f\n", diff_hash);
Serial.printf(" - Current pool diff : %.3f\n", mMiner.poolDifficulty); Serial.printf(" - Current pool diff : %.3f\n", mMiner.poolDifficulty);

View File

@ -250,7 +250,7 @@ String getCurrentTemperature() {
} }
String getCurrentVCore() { String getCurrentVCore() {
return String(nerdnos_get_vcore(), 2); return String(nerdnos_get_vcore(), 0);
} }
#else #else
String getCurrentHashRate(unsigned long mElapsed) String getCurrentHashRate(unsigned long mElapsed)
@ -263,7 +263,7 @@ String getCurrentTemperature() {
} }
String getCurrentVCore() { String getCurrentVCore() {
return String(0.0, 2); return String(0.0, 0);
} }
#endif #endif

View File

@ -188,7 +188,20 @@ bool parse_mining_notify(String line, mining_job& mJob)
mJob.prev_block_hash = String((const char*) doc["params"][1]); mJob.prev_block_hash = String((const char*) doc["params"][1]);
mJob.coinb1 = String((const char*) doc["params"][2]); mJob.coinb1 = String((const char*) doc["params"][2]);
mJob.coinb2 = String((const char*) doc["params"][3]); mJob.coinb2 = String((const char*) doc["params"][3]);
mJob.merkle_branch = doc["params"][4];
// this only copies references to the static json buffer
// and can lead to crashes when there is a new stratum response
// and the content of the array is still needed like on NerdNOS
// that computes the merkle tree new each 30ms^^
//mJob.merkle_branch = doc["params"][4];
// This copies the merkle branch
JsonArray merkle_tree = doc["params"][4];
mJob.merkle_branch_size = merkle_tree.size();
for (size_t i = 0; i < mJob.merkle_branch_size; i++) {
mJob.merkle_branch[i] = String((const char*) merkle_tree[i]);
}
mJob.version = String((const char*) doc["params"][5]); mJob.version = String((const char*) doc["params"][5]);
mJob.nbits = String((const char*) doc["params"][6]); mJob.nbits = String((const char*) doc["params"][6]);
mJob.ntime = String((const char*) doc["params"][7]); mJob.ntime = String((const char*) doc["params"][7]);

View File

@ -31,7 +31,8 @@ typedef struct mining_job {
String coinb1; String coinb1;
String coinb2; String coinb2;
String nbits; String nbits;
JsonArray merkle_branch; String merkle_branch[MAX_MERKLE_BRANCHES];
size_t merkle_branch_size;
String version; String version;
uint32_t target; uint32_t target;
String ntime; String ntime;

View File

@ -254,8 +254,8 @@ miner_data calculateMiningData(mining_subscribe& mWorker, mining_job mJob){
memcpy(mMiner.merkle_result, shaResult, sizeof(shaResult)); memcpy(mMiner.merkle_result, shaResult, sizeof(shaResult));
byte merkle_concatenated[32 * 2]; byte merkle_concatenated[32 * 2];
for (size_t k=0; k < mJob.merkle_branch.size(); k++) { for (size_t k=0; k < mJob.merkle_branch_size; k++) {
const char* merkle_element = (const char*) mJob.merkle_branch[k]; const char* merkle_element = (const char*) mJob.merkle_branch[k].c_str();
uint8_t bytearray[32]; uint8_t bytearray[32];
size_t res = to_byte_array(merkle_element, 64, bytearray); size_t res = to_byte_array(merkle_element, 64, bytearray);