diff --git a/src/drivers/nerd-nos/bm1397.cpp b/src/drivers/nerd-nos/bm1397.cpp index a353574..b797ab8 100644 --- a/src/drivers/nerd-nos/bm1397.cpp +++ b/src/drivers/nerd-nos/bm1397.cpp @@ -101,6 +101,12 @@ static void _send_read_address(void) _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_READ), read_address, 2, BM1397_SERIALTX_DEBUG); } +void BM1397_read_hashrate(void) { + unsigned char read_address[2] = {0x00, 0x04};//0x50}; + // send serial data + _send_BM1397((TYPE_CMD | GROUP_ALL | CMD_READ), read_address, 2, BM1397_SERIALTX_DEBUG); +} + static void _send_chain_inactive(void) { @@ -498,6 +504,14 @@ bool BM1397_proccess_work(uint32_t version, uint16_t timeout, task_result *resul return false; } + // if this matches we can assume it's not a nonce + if ((asic_result.midstate_num == 0) && !(asic_result.nonce & 0x7f)) { + result->data = __bswap32(asic_result.nonce); + result->reg = asic_result.job_id; + result->is_reg_resp = 1; + return true; + } + uint8_t rx_job_id = (asic_result.job_id & 0xfc) >> 2; uint8_t rx_midstate_index = asic_result.job_id & 0x03; diff --git a/src/drivers/nerd-nos/bm1397.h b/src/drivers/nerd-nos/bm1397.h index 02213e6..2114a33 100644 --- a/src/drivers/nerd-nos/bm1397.h +++ b/src/drivers/nerd-nos/bm1397.h @@ -18,4 +18,4 @@ int BM1397_set_max_baud(void); int BM1397_set_default_baud(void); void BM1397_send_hash_frequency(float frequency); bool BM1397_proccess_work(uint32_t version, uint16_t timeout, task_result *result); - +void BM1397_read_hashrate(void); diff --git a/src/drivers/nerd-nos/nerdnos.h b/src/drivers/nerd-nos/nerdnos.h index aac3aee..885dade 100644 --- a/src/drivers/nerd-nos/nerdnos.h +++ b/src/drivers/nerd-nos/nerdnos.h @@ -4,11 +4,14 @@ #define BM1397_INITIAL_DIFFICULTY 128 -typedef struct __attribute__((__packed__)) +typedef struct { uint8_t job_id; uint32_t nonce; uint32_t rolled_version; + uint32_t data; + uint8_t reg; + uint8_t is_reg_resp; } task_result; typedef struct @@ -87,4 +90,4 @@ double nerdnos_test_nonce_value(const bm_job_t *job, const uint32_t nonce, const // free allocated RAM for strings on bm_job_t void nerdnos_free_bm_job(bm_job_t *job); -void nerdnos_init(); \ No newline at end of file +void nerdnos_init(); diff --git a/src/mining_nerdnos.cpp b/src/mining_nerdnos.cpp index a466645..c0996c8 100644 --- a/src/mining_nerdnos.cpp +++ b/src/mining_nerdnos.cpp @@ -29,6 +29,8 @@ extern pthread_mutex_t job_mutex; extern double best_diff; extern unsigned long mLastTXtoPool; +#define REQUEST_ASIC_HASHRATE + // Global share counter extern uint32_t shares; extern uint32_t valids; @@ -50,7 +52,7 @@ static pthread_mutex_t asic_job_mutexes[ASIC_JOB_COUNT]; typedef struct { uint32_t diffs[ASIC_HISTORY_SIZE]; - uint64_t timestamps[ASIC_HISTORY_SIZE]; + uint32_t timestamps[ASIC_HISTORY_SIZE]; uint32_t newest; uint32_t oldest; uint64_t sum; @@ -66,6 +68,8 @@ static volatile uint32_t version = 0x20000000; history_t history = {0}; +static uint32_t last_request_hashrate_ts = 0; + double nerdnos_get_avg_hashrate() { return history.avg_gh; } @@ -89,13 +93,12 @@ static void calculate_hashrate(history_t *history, uint32_t diff) { history->sum += 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: - history->timestamps[history->newest % ASIC_HISTORY_SIZE] = (uint64_t) esp_timer_get_time(); + history->timestamps[history->newest % ASIC_HISTORY_SIZE] = millis(); - uint64_t oldest_timestamp = history->timestamps[history->oldest % ASIC_HISTORY_SIZE]; - uint64_t newest_timestamp = history->timestamps[history->newest % ASIC_HISTORY_SIZE]; + uint32_t oldest_timestamp = history->timestamps[history->oldest % ASIC_HISTORY_SIZE]; + uint32_t newest_timestamp = history->timestamps[history->newest % ASIC_HISTORY_SIZE]; - history->duration = (double) (newest_timestamp - oldest_timestamp) / 1.0e6; + history->duration = (double) (newest_timestamp - oldest_timestamp) / 1.0e3; history->shares = (int) history->newest - (int) history->oldest + 1; if (history->duration) { @@ -117,10 +120,38 @@ static void create_job_timer(TimerHandle_t xTimer) pthread_mutex_unlock(&job_interval_mutex); } +static void process_hashrate_response(task_result *result) { + static float hashrate_long = 0.0; + static float hashrate_short = 0.0; + + // hashrate reported by chip + float hr_gh = (float) ((uint64_t) (result->data & 0x7fffffff) << 20llu) / 1.0e9; + + if (result->data & 0x80000000) { + hashrate_long = hr_gh; + } else { + hashrate_short = hr_gh; + } + + Serial.printf("hashrate reported by asic: %.3fGH (short), %.3fGH (long)\n", hashrate_short, hashrate_long); +} + void runASIC_RX(void * task_id) { while (1) { task_result result = {0}; - nerdnos_proccess_work(version, 10000, &result); + if (!nerdnos_proccess_work(version, 10000, &result)) { + continue; + } + + if (result.is_reg_resp) { + switch (result.reg) { + case 0x04: { + process_hashrate_response(&result); + break; + } + } + continue; + } // check if the ID is in the valid range and the slot is not empty if (result.job_id >= ASIC_JOB_COUNT) { Serial.printf("Invalid job ID %02x\n", result.job_id); @@ -261,6 +292,14 @@ void runASIC(void * task_id) { // use extranonce2 as job id uint8_t asic_job_id = (uint8_t) (extranonce_2 % ASIC_JOB_COUNT); +#ifdef REQUEST_ASIC_HASHRATE + if (millis() - last_request_hashrate_ts > 2500) { + BM1397_read_hashrate(); + last_request_hashrate_ts = millis(); + } +#endif + + pthread_mutex_lock(&asic_job_mutexes[asic_job_id]); // free memory if this slot was used before safe_free_job(&asic_jobs[asic_job_id]); diff --git a/src/mining_nerdnos.h b/src/mining_nerdnos.h index 9ee703f..c50475c 100644 --- a/src/mining_nerdnos.h +++ b/src/mining_nerdnos.h @@ -4,4 +4,4 @@ void runASIC(void * task_id); void runASIC_RX(void * task_id); -double nerdnos_get_avg_hashrate(); \ No newline at end of file +double nerdnos_get_avg_hashrate();