mirror of
https://github.com/skot/ESP-Miner.git
synced 2025-11-19 18:37:20 +01:00
* Accept and store float frequency values * Unify PLL resolver for 1366/1368/1370 Pick the closest frequency to the requested target. If there are multiple PLL settings, pick the one with first the lowest VDO frequency, and finally the lowest posdividers. Merged frequency ramp start and loop. This solves overshooting when requesting a target frequency within the current step size. It also eliminates the duplicate setting of the target frequency is that's on a step boundary. Cleaned up several unused defines. * Restore postdiv2 < postdiv1 condition for BM1368 and BM1370 * Whitespace * Clean up intermediate functions Simplify frequency_transition further, finally fix overshoot * Code cleanup * Add debug logging for BM1397 * Fix log * Flip postdiv condition for readability * Add test * Fix BM1370 fb_range * EOF line in test_pll.c
320 lines
11 KiB
C
320 lines
11 KiB
C
#include "bm1366.h"
|
|
|
|
#include "crc.h"
|
|
#include "global_state.h"
|
|
#include "serial.h"
|
|
#include "utils.h"
|
|
|
|
#include "esp_log.h"
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include "frequency_transition_bmXX.h"
|
|
#include "pll.h"
|
|
|
|
#include <math.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <arpa/inet.h>
|
|
|
|
#define BM1366_CHIP_ID 0x1366
|
|
#define BM1366_CHIP_ID_RESPONSE_LENGTH 11
|
|
|
|
#define TYPE_JOB 0x20
|
|
#define TYPE_CMD 0x40
|
|
|
|
#define GROUP_SINGLE 0x00
|
|
#define GROUP_ALL 0x10
|
|
|
|
#define CMD_SETADDRESS 0x00
|
|
#define CMD_WRITE 0x01
|
|
#define CMD_READ 0x02
|
|
#define CMD_INACTIVE 0x03
|
|
|
|
#define MISC_CONTROL 0x18
|
|
|
|
typedef struct __attribute__((__packed__))
|
|
{
|
|
uint16_t preamble;
|
|
uint32_t nonce;
|
|
uint8_t midstate_num;
|
|
uint8_t job_id;
|
|
uint16_t version;
|
|
uint8_t crc;
|
|
} bm1366_asic_result_t;
|
|
|
|
static const char * TAG = "bm1366";
|
|
|
|
static task_result result;
|
|
|
|
/// @brief
|
|
/// @param ftdi
|
|
/// @param header
|
|
/// @param data
|
|
/// @param len
|
|
static void _send_BM1366(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);
|
|
|
|
// allocate memory for buffer
|
|
unsigned char * buf = malloc(total_length);
|
|
|
|
// add the preamble
|
|
buf[0] = 0x55;
|
|
buf[1] = 0xAA;
|
|
|
|
// add the header field
|
|
buf[2] = header;
|
|
|
|
// add the length field
|
|
buf[3] = (packet_type == JOB_PACKET) ? (data_len + 4) : (data_len + 3);
|
|
|
|
// add the data
|
|
memcpy(buf + 4, data, data_len);
|
|
|
|
// add the correct crc type
|
|
if (packet_type == JOB_PACKET) {
|
|
uint16_t crc16_total = crc16_false(buf + 2, data_len + 2);
|
|
buf[4 + data_len] = (crc16_total >> 8) & 0xFF;
|
|
buf[5 + data_len] = crc16_total & 0xFF;
|
|
} else {
|
|
buf[4 + data_len] = crc5(buf + 2, data_len + 2);
|
|
}
|
|
|
|
// send serial data
|
|
SERIAL_send(buf, total_length, debug);
|
|
|
|
free(buf);
|
|
}
|
|
|
|
static void _send_simple(uint8_t * data, uint8_t total_length)
|
|
{
|
|
unsigned char * buf = malloc(total_length);
|
|
memcpy(buf, data, total_length);
|
|
SERIAL_send(buf, total_length, BM1366_SERIALTX_DEBUG);
|
|
|
|
free(buf);
|
|
}
|
|
|
|
static void _send_chain_inactive(void)
|
|
{
|
|
|
|
unsigned char read_address[2] = {0x00, 0x00};
|
|
// send serial data
|
|
_send_BM1366((TYPE_CMD | GROUP_ALL | CMD_INACTIVE), read_address, 2, BM1366_SERIALTX_DEBUG);
|
|
}
|
|
|
|
static void _set_chip_address(uint8_t chipAddr)
|
|
{
|
|
|
|
unsigned char read_address[2] = {chipAddr, 0x00};
|
|
// send serial data
|
|
_send_BM1366((TYPE_CMD | GROUP_SINGLE | CMD_SETADDRESS), read_address, 2, BM1366_SERIALTX_DEBUG);
|
|
}
|
|
|
|
void BM1366_set_version_mask(uint32_t version_mask)
|
|
{
|
|
int versions_to_roll = version_mask >> 13;
|
|
uint8_t version_byte0 = (versions_to_roll >> 8);
|
|
uint8_t version_byte1 = (versions_to_roll & 0xFF);
|
|
uint8_t version_cmd[] = {0x00, 0xA4, 0x90, 0x00, version_byte0, version_byte1};
|
|
_send_BM1366(TYPE_CMD | GROUP_ALL | CMD_WRITE, version_cmd, 6, BM1366_SERIALTX_DEBUG);
|
|
}
|
|
|
|
void BM1366_send_hash_frequency(float target_freq)
|
|
{
|
|
uint8_t fb_divider, refdiv, postdiv1, postdiv2;
|
|
float new_freq;
|
|
|
|
pll_get_parameters(target_freq, 144, 235, &fb_divider, &refdiv, &postdiv1, &postdiv2, &new_freq);
|
|
|
|
uint8_t vdo_scale = (fb_divider * FREQ_MULT / refdiv >= 2400) ? 0x50 : 0x40;
|
|
uint8_t postdiv = (((postdiv1 - 1) & 0xf) << 4) | ((postdiv2 - 1) & 0xf);
|
|
uint8_t freqbuf[6] = {0x00, 0x08, vdo_scale, fb_divider, refdiv, postdiv};
|
|
|
|
_send_BM1366((TYPE_CMD | GROUP_ALL | CMD_WRITE), freqbuf, 6, BM1366_SERIALTX_DEBUG);
|
|
|
|
ESP_LOGI(TAG, "Setting Frequency to %g MHz (%g)", target_freq, new_freq);
|
|
}
|
|
|
|
uint8_t BM1366_init(float frequency, uint16_t asic_count, uint16_t difficulty)
|
|
{
|
|
// set version mask
|
|
for (int i = 0; i < 3; i++) {
|
|
BM1366_set_version_mask(STRATUM_DEFAULT_VERSION_MASK);
|
|
}
|
|
|
|
// read register 00 on all chips
|
|
unsigned char init3[7] = {0x55, 0xAA, 0x52, 0x05, 0x00, 0x00, 0x0A};
|
|
_send_simple(init3, 7);
|
|
|
|
int chip_counter = count_asic_chips(asic_count, BM1366_CHIP_ID, BM1366_CHIP_ID_RESPONSE_LENGTH);
|
|
|
|
if (chip_counter == 0) {
|
|
return 0;
|
|
}
|
|
|
|
unsigned char init4[11] = {0x55, 0xAA, 0x51, 0x09, 0x00, 0xA8, 0x00, 0x07, 0x00, 0x00, 0x03};
|
|
_send_simple(init4, 11);
|
|
|
|
unsigned char init5[11] = {0x55, 0xAA, 0x51, 0x09, 0x00, 0x18, 0xFF, 0x0F, 0xC1, 0x00, 0x00};
|
|
_send_simple(init5, 11);
|
|
|
|
//{0x55, 0xAA, 0x53, 0x05, 0x00, 0x00, 0x03};
|
|
_send_chain_inactive();
|
|
|
|
// split the chip address space evenly
|
|
uint8_t address_interval = (uint8_t) (256 / chip_counter);
|
|
for (uint8_t i = 0; i < chip_counter; i++) {
|
|
//{ 0x55, 0xAA, 0x40, 0x05, 0x00, 0x00, 0x1C };
|
|
_set_chip_address(i * address_interval);
|
|
}
|
|
|
|
unsigned char init135[11] = {0x55, 0xAA, 0x51, 0x09, 0x00, 0x3C, 0x80, 0x00, 0x85, 0x40, 0x0C};
|
|
_send_simple(init135, 11);
|
|
|
|
unsigned char init136[11] = {0x55, 0xAA, 0x51, 0x09, 0x00, 0x3C, 0x80, 0x00, 0x80, 0x20, 0x19};
|
|
_send_simple(init136, 11);
|
|
|
|
//set difficulty mask
|
|
uint8_t difficulty_mask[6];
|
|
get_difficulty_mask(difficulty, difficulty_mask);
|
|
_send_BM1366((TYPE_CMD | GROUP_ALL | CMD_WRITE), difficulty_mask, 6, BM1366_SERIALTX_DEBUG);
|
|
|
|
unsigned char init138[11] = {0x55, 0xAA, 0x51, 0x09, 0x00, 0x54, 0x00, 0x00, 0x00, 0x03, 0x1D};
|
|
_send_simple(init138, 11);
|
|
|
|
unsigned char init139[11] = {0x55, 0xAA, 0x51, 0x09, 0x00, 0x58, 0x02, 0x11, 0x11, 0x11, 0x06};
|
|
_send_simple(init139, 11);
|
|
|
|
unsigned char init171[11] = {0x55, 0xAA, 0x41, 0x09, 0x00, 0x2C, 0x00, 0x7C, 0x00, 0x03, 0x03};
|
|
_send_simple(init171, 11);
|
|
|
|
//S19XP Dump sends baudrate change here.. we wait until later.
|
|
// unsigned char init173[11] = {0x55, 0xAA, 0x51, 0x09, 0x00, 0x28, 0x11, 0x30, 0x02, 0x00, 0x03};
|
|
// _send_simple(init173, 11);
|
|
|
|
for (uint8_t i = 0; i < chip_counter; i++) {
|
|
unsigned char set_a8_register[6] = {i * address_interval, 0xA8, 0x00, 0x07, 0x01, 0xF0};
|
|
_send_BM1366((TYPE_CMD | GROUP_SINGLE | CMD_WRITE), set_a8_register, 6, BM1366_SERIALTX_DEBUG);
|
|
unsigned char set_18_register[6] = {i * address_interval, 0x18, 0xF0, 0x00, 0xC1, 0x00};
|
|
_send_BM1366((TYPE_CMD | GROUP_SINGLE | CMD_WRITE), set_18_register, 6, BM1366_SERIALTX_DEBUG);
|
|
unsigned char set_3c_register_first[6] = {i * address_interval, 0x3C, 0x80, 0x00, 0x85, 0x40};
|
|
_send_BM1366((TYPE_CMD | GROUP_SINGLE | CMD_WRITE), set_3c_register_first, 6, BM1366_SERIALTX_DEBUG);
|
|
unsigned char set_3c_register_second[6] = {i * address_interval, 0x3C, 0x80, 0x00, 0x80, 0x20};
|
|
_send_BM1366((TYPE_CMD | GROUP_SINGLE | CMD_WRITE), set_3c_register_second, 6, BM1366_SERIALTX_DEBUG);
|
|
unsigned char set_3c_register_third[6] = {i * address_interval, 0x3C, 0x80, 0x00, 0x82, 0xAA};
|
|
_send_BM1366((TYPE_CMD | GROUP_SINGLE | CMD_WRITE), set_3c_register_third, 6, BM1366_SERIALTX_DEBUG);
|
|
}
|
|
|
|
do_frequency_transition(frequency, BM1366_send_hash_frequency);
|
|
|
|
//register 10 is still a bit of a mystery. discussion: https://github.com/bitaxeorg/ESP-Miner/pull/167
|
|
|
|
// unsigned char set_10_hash_counting[6] = {0x00, 0x10, 0x00, 0x00, 0x11, 0x5A}; //S19k Pro Default
|
|
// unsigned char set_10_hash_counting[6] = {0x00, 0x10, 0x00, 0x00, 0x14, 0x46}; //S19XP-Luxos Default
|
|
unsigned char set_10_hash_counting[6] = {0x00, 0x10, 0x00, 0x00, 0x15, 0x1C}; //S19XP-Stock Default
|
|
// unsigned char set_10_hash_counting[6] = {0x00, 0x10, 0x00, 0x0F, 0x00, 0x00}; //supposedly the "full" 32bit nonce range
|
|
_send_BM1366((TYPE_CMD | GROUP_ALL | CMD_WRITE), set_10_hash_counting, 6, BM1366_SERIALTX_DEBUG);
|
|
|
|
unsigned char init795[11] = {0x55, 0xAA, 0x51, 0x09, 0x00, 0xA4, 0x90, 0x00, 0xFF, 0xFF, 0x1C};
|
|
_send_simple(init795, 11);
|
|
|
|
return chip_counter;
|
|
}
|
|
|
|
// static void _send_read_address(void)
|
|
// {
|
|
|
|
// unsigned char read_address[2] = {0x00, 0x00};
|
|
// // send serial data
|
|
// _send_BM1366((TYPE_CMD | GROUP_ALL | CMD_READ), read_address, 2, BM1366_SERIALTX_DEBUG);
|
|
// }
|
|
|
|
// Baud formula = 25M/((denominator+1)*8)
|
|
// The denominator is 5 bits found in the misc_control (bits 9-13)
|
|
int BM1366_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_BM1366((TYPE_CMD | GROUP_ALL | CMD_WRITE), baudrate, 6, BM1366_SERIALTX_DEBUG);
|
|
return 115749;
|
|
}
|
|
|
|
int BM1366_set_max_baud(void)
|
|
{
|
|
ESP_LOGI(TAG, "Setting max baud of 1000000");
|
|
|
|
unsigned char reg28[11] = {0x55, 0xAA, 0x51, 0x09, 0x00, 0x28, 0x11, 0x30, 0x02, 0x00, 0x03};
|
|
_send_simple(reg28, 11);
|
|
return 1000000;
|
|
}
|
|
|
|
static uint8_t id = 0;
|
|
|
|
void BM1366_send_work(void * pvParameters, bm_job * next_bm_job)
|
|
{
|
|
|
|
GlobalState * GLOBAL_STATE = (GlobalState *) pvParameters;
|
|
|
|
BM1366_job job;
|
|
id = (id + 8) % 128;
|
|
job.job_id = id;
|
|
job.num_midstates = 0x01;
|
|
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.merkle_root, next_bm_job->merkle_root_be, 32);
|
|
memcpy(job.prev_block_hash, next_bm_job->prev_block_hash_be, 32);
|
|
memcpy(&job.version, &next_bm_job->version, 4);
|
|
|
|
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;
|
|
|
|
pthread_mutex_lock(&GLOBAL_STATE->valid_jobs_lock);
|
|
GLOBAL_STATE->valid_jobs[job.job_id] = 1;
|
|
pthread_mutex_unlock(&GLOBAL_STATE->valid_jobs_lock);
|
|
|
|
//debug sent jobs - this can get crazy if the interval is short
|
|
#if BM1366_DEBUG_JOBS
|
|
ESP_LOGI(TAG, "Send Job: %02X", job.job_id);
|
|
#endif
|
|
|
|
_send_BM1366((TYPE_JOB | GROUP_SINGLE | CMD_WRITE), (uint8_t *)&job, sizeof(BM1366_job), BM1366_DEBUG_WORK);
|
|
}
|
|
|
|
task_result * BM1366_process_work(void * pvParameters)
|
|
{
|
|
bm1366_asic_result_t asic_result = {0};
|
|
|
|
if (receive_work((uint8_t *)&asic_result, sizeof(asic_result)) == ESP_FAIL) {
|
|
return NULL;
|
|
}
|
|
|
|
uint8_t job_id = asic_result.job_id & 0xf8;
|
|
uint8_t core_id = (uint8_t)((ntohl(asic_result.nonce) >> 25) & 0x7f); // BM1366 has 112 cores, so it should be coded on 7 bits
|
|
uint8_t small_core_id = asic_result.job_id & 0x07; // BM1366 has 8 small cores, so it should be coded on 3 bits
|
|
uint32_t version_bits = (ntohs(asic_result.version) << 13); // shift the 16 bit value left 13
|
|
ESP_LOGI(TAG, "Job ID: %02X, Core: %d/%d, Ver: %08" PRIX32, job_id, core_id, small_core_id, version_bits);
|
|
|
|
GlobalState * GLOBAL_STATE = (GlobalState *) pvParameters;
|
|
|
|
if (GLOBAL_STATE->valid_jobs[job_id] == 0) {
|
|
ESP_LOGW(TAG, "Invalid job found, 0x%02X", job_id);
|
|
return NULL;
|
|
}
|
|
|
|
uint32_t rolled_version = GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->version | version_bits;
|
|
|
|
result.job_id = job_id;
|
|
result.nonce = asic_result.nonce;
|
|
result.rolled_version = rolled_version;
|
|
|
|
return &result;
|
|
}
|