mirror of
https://github.com/skot/ESP-Miner.git
synced 2025-03-17 13:22:53 +01:00
Compare commits
64 Commits
290d0ba13a
...
f267f2857c
Author | SHA1 | Date | |
---|---|---|---|
|
f267f2857c | ||
|
9d8198a4bb | ||
|
36e06236b0 | ||
|
c5609dfce1 | ||
|
dd4ecbc72e | ||
|
64218d63d2 | ||
|
e29b8e3afb | ||
|
a5842a54b3 | ||
|
deaa291675 | ||
|
d032f2da4a | ||
|
1eeb303672 | ||
|
6e1205f30a | ||
|
c267789dbd | ||
|
a0c9710a90 | ||
|
60fba27826 | ||
|
56731b5c63 | ||
|
b92f70d871 | ||
|
b21cd50504 | ||
|
ca4e5dcc2a | ||
|
b60fd3dfce | ||
|
8bd8b88af9 | ||
|
4c76d17a4d | ||
|
ac4ffbc2f2 | ||
|
6d504fe1a1 | ||
|
fe78e05611 | ||
|
91f302c744 | ||
|
29f66b228e | ||
|
ad5d1291b9 | ||
|
bec0863a82 | ||
|
b8c748be69 | ||
|
9c0354653f | ||
|
0d02eb5eec | ||
|
59141357ff | ||
|
7dcb69ebdc | ||
|
080d0fe2cc | ||
|
1014a46a24 | ||
|
678809a5f8 | ||
|
2b958c0b94 | ||
|
cbb02389ba | ||
|
548f91410b | ||
|
19ce1df337 | ||
|
980d213445 | ||
|
c98ac818c9 | ||
|
148d42b1c8 | ||
|
f40972ced2 | ||
|
e7b037df10 | ||
|
1db16a52e1 | ||
|
c8671cf69c | ||
|
7e2d690c64 | ||
|
aa540434be | ||
|
e1a94fe7a7 | ||
|
e471d43e2d | ||
|
06867c474f | ||
|
8d8a01a2e4 | ||
|
0497b1104a | ||
|
e77083507d | ||
|
2f38e202a9 | ||
|
06be7f5ddb | ||
|
40bf6b5ebc | ||
|
f1c0128f73 | ||
|
244dacc26a | ||
|
a04c00ba07 | ||
|
b8123e8c60 | ||
|
f9e1672d6f |
28
.github/workflows/unittest.yml
vendored
Normal file
28
.github/workflows/unittest.yml
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
name: Unit Test
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- name: esp-idf build
|
||||
uses: espressif/esp-idf-ci-action@v1
|
||||
with:
|
||||
esp_idf_version: v5.4
|
||||
target: esp32s3
|
||||
command: GITHUB_ACTIONS="true" idf.py build
|
||||
path: 'test-ci'
|
||||
- name: Run tests and show result
|
||||
uses: bitaxeorg/esp32-qemu-test-action@main
|
||||
with:
|
||||
path: 'test-ci'
|
||||
- name: Inspect log
|
||||
run: cat report.xml
|
||||
- name: Publish Unit Test Results
|
||||
uses: EnricoMi/publish-unit-test-result-action@v1
|
||||
if: always()
|
||||
with:
|
||||
files: report.xml
|
9
SECURITY.md
Normal file
9
SECURITY.md
Normal file
@ -0,0 +1,9 @@
|
||||
# Reporting Security Issues
|
||||
|
||||
We take security bugs in esp-miner seriously. We appreciate your efforts to responsibly disclose your findings, and will make every effort to acknowledge your contributions.
|
||||
|
||||
To report a security issue, please use the GitHub Security Advisory ["Report a Vulnerability"](https://github.com/bitaxeorg/ESP-Miner/security/advisories/new) tab.
|
||||
|
||||
A esp-miner maintainer will send a response indicating the next steps in handling your report. After the initial reply to your report, the security team will keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance.
|
||||
|
||||
Report security bugs in third-party modules to the person or team maintaining the module.
|
@ -7,6 +7,8 @@ SRCS
|
||||
"serial.c"
|
||||
"crc.c"
|
||||
"common.c"
|
||||
"asic.c"
|
||||
"frequency_transition_bmXX.c"
|
||||
|
||||
INCLUDE_DIRS
|
||||
"include"
|
||||
@ -22,4 +24,4 @@ REQUIRES
|
||||
target_include_directories(${COMPONENT_LIB} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../main")
|
||||
|
||||
# Include the header files from "main/tasks" directory
|
||||
target_include_directories(${COMPONENT_LIB} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../main/tasks")
|
||||
target_include_directories(${COMPONENT_LIB} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../main/tasks")
|
||||
|
263
components/asic/asic.c
Normal file
263
components/asic/asic.c
Normal file
@ -0,0 +1,263 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <esp_log.h>
|
||||
|
||||
#include "bm1397.h"
|
||||
#include "bm1366.h"
|
||||
#include "bm1368.h"
|
||||
#include "bm1370.h"
|
||||
|
||||
#include "asic.h"
|
||||
|
||||
static const double NONCE_SPACE = 4294967296.0; // 2^32
|
||||
|
||||
static const char *TAG = "asic";
|
||||
|
||||
// .init_fn = BM1366_init,
|
||||
uint8_t ASIC_init(GlobalState * GLOBAL_STATE) {
|
||||
switch (GLOBAL_STATE->device_model) {
|
||||
case DEVICE_MAX:
|
||||
return BM1397_init(GLOBAL_STATE->POWER_MANAGEMENT_MODULE.frequency_value, BITAXE_MAX_ASIC_COUNT);
|
||||
case DEVICE_ULTRA:
|
||||
return BM1366_init(GLOBAL_STATE->POWER_MANAGEMENT_MODULE.frequency_value, BITAXE_ULTRA_ASIC_COUNT);
|
||||
case DEVICE_SUPRA:
|
||||
return BM1368_init(GLOBAL_STATE->POWER_MANAGEMENT_MODULE.frequency_value, BITAXE_SUPRA_ASIC_COUNT);
|
||||
case DEVICE_GAMMA:
|
||||
return BM1370_init(GLOBAL_STATE->POWER_MANAGEMENT_MODULE.frequency_value, BITAXE_GAMMA_ASIC_COUNT);
|
||||
case DEVICE_GAMMATURBO:
|
||||
return BM1370_init(GLOBAL_STATE->POWER_MANAGEMENT_MODULE.frequency_value, BITAXE_GAMMATURBO_ASIC_COUNT);
|
||||
default:
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
uint8_t ASIC_get_asic_count(GlobalState * GLOBAL_STATE) {
|
||||
switch (GLOBAL_STATE->device_model) {
|
||||
case DEVICE_MAX:
|
||||
return BITAXE_MAX_ASIC_COUNT;
|
||||
case DEVICE_ULTRA:
|
||||
return BITAXE_ULTRA_ASIC_COUNT;
|
||||
case DEVICE_SUPRA:
|
||||
return BITAXE_SUPRA_ASIC_COUNT;
|
||||
case DEVICE_GAMMA:
|
||||
return BITAXE_GAMMA_ASIC_COUNT;
|
||||
case DEVICE_GAMMATURBO:
|
||||
return BITAXE_GAMMATURBO_ASIC_COUNT;
|
||||
default:
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t ASIC_get_small_core_count(GlobalState * GLOBAL_STATE) {
|
||||
switch (GLOBAL_STATE->device_model) {
|
||||
case DEVICE_MAX:
|
||||
return BM1397_SMALL_CORE_COUNT;
|
||||
case DEVICE_ULTRA:
|
||||
return BM1366_SMALL_CORE_COUNT;
|
||||
case DEVICE_SUPRA:
|
||||
return BM1368_SMALL_CORE_COUNT;
|
||||
case DEVICE_GAMMA:
|
||||
return BM1370_SMALL_CORE_COUNT;
|
||||
case DEVICE_GAMMATURBO:
|
||||
return BM1370_SMALL_CORE_COUNT;
|
||||
default:
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// .receive_result_fn = BM1366_process_work,
|
||||
task_result * ASIC_process_work(GlobalState * GLOBAL_STATE) {
|
||||
switch (GLOBAL_STATE->device_model) {
|
||||
case DEVICE_MAX:
|
||||
return BM1397_process_work(GLOBAL_STATE);
|
||||
case DEVICE_ULTRA:
|
||||
return BM1366_process_work(GLOBAL_STATE);
|
||||
case DEVICE_SUPRA:
|
||||
return BM1368_process_work(GLOBAL_STATE);
|
||||
case DEVICE_GAMMA:
|
||||
case DEVICE_GAMMATURBO:
|
||||
return BM1370_process_work(GLOBAL_STATE);
|
||||
default:
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// .set_max_baud_fn = BM1366_set_max_baud,
|
||||
int ASIC_set_max_baud(GlobalState * GLOBAL_STATE) {
|
||||
switch (GLOBAL_STATE->device_model) {
|
||||
case DEVICE_MAX:
|
||||
return BM1397_set_max_baud();
|
||||
case DEVICE_ULTRA:
|
||||
return BM1366_set_max_baud();
|
||||
case DEVICE_SUPRA:
|
||||
return BM1368_set_max_baud();
|
||||
case DEVICE_GAMMA:
|
||||
case DEVICE_GAMMATURBO:
|
||||
return BM1370_set_max_baud();
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// .set_difficulty_mask_fn = BM1366_set_job_difficulty_mask,
|
||||
void ASIC_set_job_difficulty_mask(GlobalState * GLOBAL_STATE, uint8_t mask) {
|
||||
switch (GLOBAL_STATE->device_model) {
|
||||
case DEVICE_MAX:
|
||||
BM1397_set_job_difficulty_mask(mask);
|
||||
break;
|
||||
case DEVICE_ULTRA:
|
||||
BM1366_set_job_difficulty_mask(mask);
|
||||
break;
|
||||
case DEVICE_SUPRA:
|
||||
BM1368_set_job_difficulty_mask(mask);
|
||||
break;
|
||||
case DEVICE_GAMMA:
|
||||
case DEVICE_GAMMATURBO:
|
||||
BM1370_set_job_difficulty_mask(mask);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
// .send_work_fn = BM1366_send_work,
|
||||
void ASIC_send_work(GlobalState * GLOBAL_STATE, void * next_job) {
|
||||
switch (GLOBAL_STATE->device_model) {
|
||||
case DEVICE_MAX:
|
||||
BM1397_send_work(GLOBAL_STATE, next_job);
|
||||
break;
|
||||
case DEVICE_ULTRA:
|
||||
BM1366_send_work(GLOBAL_STATE, next_job);
|
||||
break;
|
||||
case DEVICE_SUPRA:
|
||||
BM1368_send_work(GLOBAL_STATE, next_job);
|
||||
break;
|
||||
case DEVICE_GAMMA:
|
||||
case DEVICE_GAMMATURBO:
|
||||
BM1370_send_work(GLOBAL_STATE, next_job);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// .set_version_mask = BM1366_set_version_mask
|
||||
void ASIC_set_version_mask(GlobalState * GLOBAL_STATE, uint32_t mask) {
|
||||
switch (GLOBAL_STATE->device_model) {
|
||||
case DEVICE_MAX:
|
||||
BM1397_set_version_mask(mask);
|
||||
break;
|
||||
case DEVICE_ULTRA:
|
||||
BM1366_set_version_mask(mask);
|
||||
break;
|
||||
case DEVICE_SUPRA:
|
||||
BM1368_set_version_mask(mask);
|
||||
break;
|
||||
case DEVICE_GAMMA:
|
||||
case DEVICE_GAMMATURBO:
|
||||
BM1370_set_version_mask(mask);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool ASIC_set_frequency(GlobalState * GLOBAL_STATE, float target_frequency) {
|
||||
ESP_LOGI(TAG, "Setting ASIC frequency to %.2f MHz", target_frequency);
|
||||
bool success = false;
|
||||
|
||||
switch (GLOBAL_STATE->asic_model) {
|
||||
case ASIC_BM1366:
|
||||
success = BM1366_set_frequency(target_frequency);
|
||||
break;
|
||||
case ASIC_BM1368:
|
||||
success = BM1368_set_frequency(target_frequency);
|
||||
break;
|
||||
case ASIC_BM1370:
|
||||
success = BM1370_set_frequency(target_frequency);
|
||||
break;
|
||||
case ASIC_BM1397:
|
||||
// BM1397 doesn't have a set_frequency function yet
|
||||
ESP_LOGE(TAG, "Frequency transition not implemented for BM1397");
|
||||
success = false;
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE(TAG, "Unknown ASIC model, cannot set frequency");
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (success) {
|
||||
ESP_LOGI(TAG, "Successfully transitioned to new ASIC frequency: %.2f MHz", target_frequency);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed to transition to new ASIC frequency: %.2f MHz", target_frequency);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
esp_err_t ASIC_set_device_model(GlobalState * GLOBAL_STATE) {
|
||||
|
||||
if (GLOBAL_STATE->device_model_str == NULL) {
|
||||
ESP_LOGE(TAG, "No device model string found");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (strcmp(GLOBAL_STATE->device_model_str, "max") == 0) {
|
||||
GLOBAL_STATE->asic_model = ASIC_BM1397;
|
||||
GLOBAL_STATE->valid_model = true;
|
||||
GLOBAL_STATE->asic_job_frequency_ms = (NONCE_SPACE / (double) (GLOBAL_STATE->POWER_MANAGEMENT_MODULE.frequency_value * BM1397_SMALL_CORE_COUNT * 1000)) / (double) ASIC_get_asic_count(GLOBAL_STATE); // no version-rolling so same Nonce Space is splitted between Small Cores
|
||||
GLOBAL_STATE->ASIC_difficulty = BM1397_ASIC_DIFFICULTY;
|
||||
ESP_LOGI(TAG, "DEVICE: bitaxeMax");
|
||||
ESP_LOGI(TAG, "ASIC: %dx BM1397 (%" PRIu64 " cores)", BITAXE_MAX_ASIC_COUNT, BM1397_CORE_COUNT);
|
||||
GLOBAL_STATE->device_model = DEVICE_MAX;
|
||||
|
||||
} else if (strcmp(GLOBAL_STATE->device_model_str, "ultra") == 0) {
|
||||
GLOBAL_STATE->asic_model = ASIC_BM1366;
|
||||
GLOBAL_STATE->valid_model = true;
|
||||
//GLOBAL_STATE.asic_job_frequency_ms = (NONCE_SPACE / (double) (GLOBAL_STATE.POWER_MANAGEMENT_MODULE.frequency_value * BM1366_CORE_COUNT * 1000)) / (double) BITAXE_ULTRA_ASIC_COUNT; // version-rolling so Small Cores have different Nonce Space
|
||||
GLOBAL_STATE->asic_job_frequency_ms = 2000; //ms
|
||||
GLOBAL_STATE->ASIC_difficulty = BM1366_ASIC_DIFFICULTY;
|
||||
ESP_LOGI(TAG, "DEVICE: bitaxeUltra");
|
||||
ESP_LOGI(TAG, "ASIC: %dx BM1366 (%" PRIu64 " cores)", BITAXE_ULTRA_ASIC_COUNT, BM1366_CORE_COUNT);
|
||||
GLOBAL_STATE->device_model = DEVICE_ULTRA;
|
||||
|
||||
} else if (strcmp(GLOBAL_STATE->device_model_str, "supra") == 0) {
|
||||
GLOBAL_STATE->asic_model = ASIC_BM1368;
|
||||
GLOBAL_STATE->valid_model = true;
|
||||
//GLOBAL_STATE.asic_job_frequency_ms = (NONCE_SPACE / (double) (GLOBAL_STATE.POWER_MANAGEMENT_MODULE.frequency_value * BM1368_CORE_COUNT * 1000)) / (double) BITAXE_SUPRA_ASIC_COUNT; // version-rolling so Small Cores have different Nonce Space
|
||||
GLOBAL_STATE->asic_job_frequency_ms = 500; //ms
|
||||
GLOBAL_STATE->ASIC_difficulty = BM1368_ASIC_DIFFICULTY;
|
||||
ESP_LOGI(TAG, "DEVICE: bitaxeSupra");
|
||||
ESP_LOGI(TAG, "ASIC: %dx BM1368 (%" PRIu64 " cores)", BITAXE_SUPRA_ASIC_COUNT, BM1368_CORE_COUNT);
|
||||
GLOBAL_STATE->device_model = DEVICE_SUPRA;
|
||||
|
||||
} else if (strcmp(GLOBAL_STATE->device_model_str, "gamma") == 0) {
|
||||
GLOBAL_STATE->asic_model = ASIC_BM1370;
|
||||
GLOBAL_STATE->valid_model = true;
|
||||
//GLOBAL_STATE.asic_job_frequency_ms = (NONCE_SPACE / (double) (GLOBAL_STATE.POWER_MANAGEMENT_MODULE.frequency_value * BM1370_CORE_COUNT * 1000)) / (double) BITAXE_GAMMA_ASIC_COUNT; // version-rolling so Small Cores have different Nonce Space
|
||||
GLOBAL_STATE->asic_job_frequency_ms = 500; //ms
|
||||
GLOBAL_STATE->ASIC_difficulty = BM1370_ASIC_DIFFICULTY;
|
||||
ESP_LOGI(TAG, "DEVICE: bitaxeGamma");
|
||||
ESP_LOGI(TAG, "ASIC: %dx BM1370 (%" PRIu64 " cores)", BITAXE_GAMMA_ASIC_COUNT, BM1370_CORE_COUNT);
|
||||
GLOBAL_STATE->device_model = DEVICE_GAMMA;
|
||||
|
||||
} else if (strcmp(GLOBAL_STATE->device_model_str, "gammaturbo") == 0) {
|
||||
GLOBAL_STATE->asic_model = ASIC_BM1370;
|
||||
GLOBAL_STATE->valid_model = true;
|
||||
//GLOBAL_STATE.asic_job_frequency_ms = (NONCE_SPACE / (double) (GLOBAL_STATE.POWER_MANAGEMENT_MODULE.frequency_value * BM1370_CORE_COUNT * 1000)) / (double) BITAXE_GAMMATURBO_ASIC_COUNT; // version-rolling so Small Cores have different Nonce Space
|
||||
GLOBAL_STATE->asic_job_frequency_ms = 500; //ms
|
||||
GLOBAL_STATE->ASIC_difficulty = BM1370_ASIC_DIFFICULTY;
|
||||
ESP_LOGI(TAG, "DEVICE: bitaxeGammaTurbo");
|
||||
ESP_LOGI(TAG, "ASIC: %dx BM1370 (%" PRIu64 " cores)", BITAXE_GAMMATURBO_ASIC_COUNT, BM1370_CORE_COUNT);
|
||||
GLOBAL_STATE->device_model = DEVICE_GAMMATURBO;
|
||||
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Invalid DEVICE model");
|
||||
// maybe should return here to now execute anything with a faulty device parameter !
|
||||
// this stops crashes/reboots and allows dev testing without an asic
|
||||
GLOBAL_STATE->device_model = DEVICE_UNKNOWN;
|
||||
GLOBAL_STATE->valid_model = false;
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
@ -8,14 +8,23 @@
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "frequency_transition_bmXX.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
|
||||
|
||||
#ifdef CONFIG_GPIO_ASIC_RESET
|
||||
#define GPIO_ASIC_RESET CONFIG_GPIO_ASIC_RESET
|
||||
#else
|
||||
#define GPIO_ASIC_RESET 1
|
||||
#endif
|
||||
|
||||
#define TYPE_JOB 0x20
|
||||
#define TYPE_CMD 0x40
|
||||
@ -45,23 +54,20 @@
|
||||
#define TICKET_MASK 0x14
|
||||
#define MISC_CONTROL 0x18
|
||||
|
||||
#define BM1366_TIMEOUT_MS 10000
|
||||
#define BM1366_TIMEOUT_THRESHOLD 2
|
||||
typedef struct __attribute__((__packed__))
|
||||
{
|
||||
uint8_t preamble[2];
|
||||
uint16_t preamble;
|
||||
uint32_t nonce;
|
||||
uint8_t midstate_num;
|
||||
uint8_t job_id;
|
||||
uint16_t version;
|
||||
uint8_t crc;
|
||||
} asic_result;
|
||||
} bm1366_asic_result_t;
|
||||
|
||||
static float current_frequency = 56.25;
|
||||
|
||||
static const char * TAG = "bm1366Module";
|
||||
|
||||
static uint8_t asic_response_buffer[SERIAL_BUF_SIZE];
|
||||
static task_result result;
|
||||
|
||||
/// @brief
|
||||
@ -197,38 +203,18 @@ void BM1366_send_hash_frequency(float target_freq)
|
||||
}
|
||||
|
||||
static void do_frequency_ramp_up(float target_frequency) {
|
||||
float step = 6.25;
|
||||
float current = current_frequency;
|
||||
float target = target_frequency;
|
||||
ESP_LOGI(TAG, "Ramping up frequency from %.2f MHz to %.2f MHz", current_frequency, target_frequency);
|
||||
do_frequency_transition(target_frequency, BM1366_send_hash_frequency, 1366);
|
||||
}
|
||||
|
||||
float direction = (target > current) ? step : -step;
|
||||
|
||||
if (fmod(current, step) != 0) {
|
||||
float next_dividable;
|
||||
if (direction > 0) {
|
||||
next_dividable = ceil(current / step) * step;
|
||||
} else {
|
||||
next_dividable = floor(current / step) * step;
|
||||
}
|
||||
current = next_dividable;
|
||||
BM1366_send_hash_frequency(current);
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
while ((direction > 0 && current < target) || (direction < 0 && current > target)) {
|
||||
float next_step = fmin(fabs(direction), fabs(target - current));
|
||||
current += direction > 0 ? next_step : -next_step;
|
||||
BM1366_send_hash_frequency(current);
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
}
|
||||
BM1366_send_hash_frequency(target);
|
||||
return;
|
||||
// Add a public function for external use
|
||||
bool BM1366_set_frequency(float target_freq) {
|
||||
return do_frequency_transition(target_freq, BM1366_send_hash_frequency, 1366);
|
||||
}
|
||||
|
||||
|
||||
static uint8_t _send_init(uint64_t frequency, uint16_t asic_count)
|
||||
{
|
||||
|
||||
// set version mask
|
||||
for (int i = 0; i < 3; i++) {
|
||||
BM1366_set_version_mask(STRATUM_DEFAULT_VERSION_MASK);
|
||||
@ -238,15 +224,11 @@ static uint8_t _send_init(uint64_t frequency, uint16_t asic_count)
|
||||
unsigned char init3[7] = {0x55, 0xAA, 0x52, 0x05, 0x00, 0x00, 0x0A};
|
||||
_send_simple(init3, 7);
|
||||
|
||||
int chip_counter = 0;
|
||||
while (true) {
|
||||
if(SERIAL_rx(asic_response_buffer, 11, 1000) > 0) {
|
||||
chip_counter++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
int chip_counter = count_asic_chips(asic_count, BM1366_CHIP_ID, BM1366_CHIP_ID_RESPONSE_LENGTH);
|
||||
|
||||
if (chip_counter == 0) {
|
||||
return 0;
|
||||
}
|
||||
ESP_LOGI(TAG, "%i chip(s) detected on the chain, expected %i", chip_counter, asic_count);
|
||||
|
||||
unsigned char init4[11] = {0x55, 0xAA, 0x51, 0x09, 0x00, 0xA8, 0x00, 0x07, 0x00, 0x00, 0x03};
|
||||
_send_simple(init4, 11);
|
||||
@ -301,7 +283,7 @@ static uint8_t _send_init(uint64_t frequency, uint16_t asic_count)
|
||||
|
||||
do_frequency_ramp_up((float)frequency);
|
||||
|
||||
//register 10 is still a bit of a mystery. discussion: https://github.com/skot/ESP-Miner/pull/167
|
||||
//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
|
||||
@ -342,8 +324,6 @@ uint8_t BM1366_init(uint64_t frequency, uint16_t asic_count)
|
||||
{
|
||||
ESP_LOGI(TAG, "Initializing BM1366");
|
||||
|
||||
memset(asic_response_buffer, 0, SERIAL_BUF_SIZE);
|
||||
|
||||
esp_rom_gpio_pad_select_gpio(GPIO_ASIC_RESET);
|
||||
gpio_set_direction(GPIO_ASIC_RESET, GPIO_MODE_OUTPUT);
|
||||
|
||||
@ -437,77 +417,31 @@ void BM1366_send_work(void * pvParameters, bm_job * next_bm_job)
|
||||
_send_BM1366((TYPE_JOB | GROUP_SINGLE | CMD_WRITE), (uint8_t *)&job, sizeof(BM1366_job), BM1366_DEBUG_WORK);
|
||||
}
|
||||
|
||||
asic_result * BM1366_receive_work(void)
|
||||
task_result * BM1366_process_work(void * pvParameters)
|
||||
{
|
||||
// wait for a response
|
||||
int received = SERIAL_rx(asic_response_buffer, 11, BM1366_TIMEOUT_MS);
|
||||
bm1366_asic_result_t asic_result = {0};
|
||||
|
||||
bool uart_err = received < 0;
|
||||
bool uart_timeout = received == 0;
|
||||
uint8_t asic_timeout_counter = 0;
|
||||
|
||||
// handle response
|
||||
if (uart_err) {
|
||||
ESP_LOGI(TAG, "UART Error in serial RX");
|
||||
return NULL;
|
||||
} else if (uart_timeout) {
|
||||
if (asic_timeout_counter >= BM1366_TIMEOUT_THRESHOLD) {
|
||||
ESP_LOGE(TAG, "ASIC not sending data");
|
||||
asic_timeout_counter = 0;
|
||||
}
|
||||
asic_timeout_counter++;
|
||||
if (receive_work((uint8_t *)&asic_result, sizeof(asic_result)) == ESP_FAIL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (received != 11 || 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);
|
||||
SERIAL_clear_buffer();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (asic_result *) asic_response_buffer;
|
||||
}
|
||||
|
||||
static uint16_t reverse_uint16(uint16_t num)
|
||||
{
|
||||
return (num >> 8) | (num << 8);
|
||||
}
|
||||
|
||||
static uint32_t reverse_uint32(uint32_t val)
|
||||
{
|
||||
return ((val >> 24) & 0xff) | // Move byte 3 to byte 0
|
||||
((val << 8) & 0xff0000) | // Move byte 1 to byte 2
|
||||
((val >> 8) & 0xff00) | // Move byte 2 to byte 1
|
||||
((val << 24) & 0xff000000); // Move byte 0 to byte 3
|
||||
}
|
||||
|
||||
task_result * BM1366_proccess_work(void * pvParameters)
|
||||
{
|
||||
|
||||
asic_result * asic_result = BM1366_receive_work();
|
||||
|
||||
if (asic_result == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t job_id = asic_result->job_id & 0xf8;
|
||||
uint8_t core_id = (uint8_t)((reverse_uint32(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 = (reverse_uint16(asic_result->version) << 13); // shift the 16 bit value left 13
|
||||
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_LOGE(TAG, "Invalid job found, 0x%02X", job_id);
|
||||
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.nonce = asic_result.nonce;
|
||||
result.rolled_version = rolled_version;
|
||||
|
||||
return &result;
|
||||
|
@ -8,14 +8,23 @@
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "frequency_transition_bmXX.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#define BM1368_CHIP_ID 0x1368
|
||||
#define BM1368_CHIP_ID_RESPONSE_LENGTH 11
|
||||
|
||||
#ifdef CONFIG_GPIO_ASIC_RESET
|
||||
#define GPIO_ASIC_RESET CONFIG_GPIO_ASIC_RESET
|
||||
#else
|
||||
#define GPIO_ASIC_RESET 1
|
||||
#endif
|
||||
|
||||
#define TYPE_JOB 0x20
|
||||
#define TYPE_CMD 0x40
|
||||
@ -45,21 +54,18 @@
|
||||
#define TICKET_MASK 0x14
|
||||
#define MISC_CONTROL 0x18
|
||||
|
||||
#define BM1368_TIMEOUT_MS 10000
|
||||
#define BM1368_TIMEOUT_THRESHOLD 2
|
||||
typedef struct __attribute__((__packed__))
|
||||
{
|
||||
uint8_t preamble[2];
|
||||
uint16_t preamble;
|
||||
uint32_t nonce;
|
||||
uint8_t midstate_num;
|
||||
uint8_t job_id;
|
||||
uint16_t version;
|
||||
uint8_t crc;
|
||||
} asic_result;
|
||||
} bm1368_asic_result_t;
|
||||
|
||||
static const char * TAG = "bm1368Module";
|
||||
|
||||
static uint8_t asic_response_buffer[CHUNK_SIZE];
|
||||
static task_result result;
|
||||
|
||||
static float current_frequency = 56.25;
|
||||
@ -128,7 +134,7 @@ static void _reset(void)
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
bool BM1368_send_hash_frequency(float target_freq) {
|
||||
void BM1368_send_hash_frequency(float target_freq) {
|
||||
float max_diff = 0.001;
|
||||
uint8_t freqbuf[6] = {0x00, 0x08, 0x40, 0xA0, 0x02, 0x41};
|
||||
uint8_t postdiv_min = 255;
|
||||
@ -164,7 +170,7 @@ bool BM1368_send_hash_frequency(float target_freq) {
|
||||
|
||||
if (!found) {
|
||||
ESP_LOGE(TAG, "Didn't find PLL settings for target frequency %.2f", target_freq);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
freqbuf[2] = (best_fbdiv * 25 / best_refdiv >= 2400) ? 0x50 : 0x40;
|
||||
@ -176,73 +182,21 @@ bool BM1368_send_hash_frequency(float target_freq) {
|
||||
|
||||
ESP_LOGI(TAG, "Setting Frequency to %.2fMHz (%.2f)", target_freq, best_freq);
|
||||
current_frequency = target_freq;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool do_frequency_transition(float target_frequency) {
|
||||
float step = 6.25;
|
||||
float current = current_frequency;
|
||||
float target = target_frequency;
|
||||
|
||||
float direction = (target > current) ? step : -step;
|
||||
|
||||
if (fmod(current, step) != 0) {
|
||||
float next_dividable;
|
||||
if (direction > 0) {
|
||||
next_dividable = ceil(current / step) * step;
|
||||
} else {
|
||||
next_dividable = floor(current / step) * step;
|
||||
}
|
||||
current = next_dividable;
|
||||
BM1368_send_hash_frequency(current);
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
while ((direction > 0 && current < target) || (direction < 0 && current > target)) {
|
||||
float next_step = fmin(fabs(direction), fabs(target - current));
|
||||
current += direction > 0 ? next_step : -next_step;
|
||||
BM1368_send_hash_frequency(current);
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
}
|
||||
BM1368_send_hash_frequency(target);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BM1368_set_frequency(float target_freq) {
|
||||
return do_frequency_transition(target_freq);
|
||||
return do_frequency_transition(target_freq, BM1368_send_hash_frequency, 1368);
|
||||
}
|
||||
|
||||
static int count_asic_chips(void) {
|
||||
_send_BM1368(TYPE_CMD | GROUP_ALL | CMD_READ, (uint8_t[]){0x00, 0x00}, 2, false);
|
||||
|
||||
int chip_counter = 0;
|
||||
while (true) {
|
||||
if (SERIAL_rx(asic_response_buffer, 11, 5000) <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (memcmp(asic_response_buffer, "\xaa\x55\x13\x68\x00\x00", 6) == 0) {
|
||||
chip_counter++;
|
||||
}
|
||||
}
|
||||
|
||||
_send_chain_inactive();
|
||||
return chip_counter;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void do_frequency_ramp_up(float target_frequency) {
|
||||
ESP_LOGI(TAG, "Ramping up frequency from %.2f MHz to %.2f MHz", current_frequency, target_frequency);
|
||||
do_frequency_transition(target_frequency);
|
||||
do_frequency_transition(target_frequency, BM1368_send_hash_frequency, 1368);
|
||||
}
|
||||
|
||||
uint8_t BM1368_init(uint64_t frequency, uint16_t asic_count)
|
||||
{
|
||||
ESP_LOGI(TAG, "Initializing BM1368");
|
||||
|
||||
memset(asic_response_buffer, 0, CHUNK_SIZE);
|
||||
|
||||
esp_rom_gpio_pad_select_gpio(GPIO_ASIC_RESET);
|
||||
gpio_set_direction(GPIO_ASIC_RESET, GPIO_MODE_OUTPUT);
|
||||
|
||||
@ -253,13 +207,16 @@ uint8_t BM1368_init(uint64_t frequency, uint16_t asic_count)
|
||||
BM1368_set_version_mask(STRATUM_DEFAULT_VERSION_MASK);
|
||||
}
|
||||
|
||||
int chip_counter = count_asic_chips();
|
||||
_send_BM1368(TYPE_CMD | GROUP_ALL | CMD_READ, (uint8_t[]){0x00, 0x00}, 2, false);
|
||||
|
||||
if (chip_counter != asic_count) {
|
||||
ESP_LOGE(TAG, "Chip count mismatch. Expected: %d, Actual: %d", asic_count, chip_counter);
|
||||
int chip_counter = count_asic_chips(asic_count, BM1368_CHIP_ID, BM1368_CHIP_ID_RESPONSE_LENGTH);
|
||||
|
||||
if (chip_counter == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
_send_chain_inactive();
|
||||
|
||||
uint8_t init_cmds[][6] = {
|
||||
{0x00, 0xA8, 0x00, 0x07, 0x00, 0x00},
|
||||
{0x00, 0x18, 0xFF, 0x0F, 0xC1, 0x00},
|
||||
@ -301,7 +258,6 @@ uint8_t BM1368_init(uint64_t frequency, uint16_t asic_count)
|
||||
_send_BM1368(TYPE_CMD | GROUP_ALL | CMD_WRITE, (uint8_t[]){0x00, 0x10, 0x00, 0x00, 0x15, 0xa4}, 6, false);
|
||||
BM1368_set_version_mask(STRATUM_DEFAULT_VERSION_MASK);
|
||||
|
||||
ESP_LOGI(TAG, "%i chip(s) detected on the chain, expected %i", chip_counter, asic_count);
|
||||
return chip_counter;
|
||||
}
|
||||
|
||||
@ -371,77 +327,32 @@ void BM1368_send_work(void * pvParameters, bm_job * next_bm_job)
|
||||
_send_BM1368((TYPE_JOB | GROUP_SINGLE | CMD_WRITE), (uint8_t *)&job, sizeof(BM1368_job), BM1368_DEBUG_WORK);
|
||||
}
|
||||
|
||||
asic_result * BM1368_receive_work(void)
|
||||
task_result * BM1368_process_work(void * pvParameters)
|
||||
{
|
||||
// wait for a response
|
||||
int received = SERIAL_rx(asic_response_buffer, 11, BM1368_TIMEOUT_MS);
|
||||
bm1368_asic_result_t asic_result = {0};
|
||||
|
||||
bool uart_err = received < 0;
|
||||
bool uart_timeout = received == 0;
|
||||
uint8_t asic_timeout_counter = 0;
|
||||
|
||||
// handle response
|
||||
if (uart_err) {
|
||||
ESP_LOGI(TAG, "UART Error in serial RX");
|
||||
return NULL;
|
||||
} else if (uart_timeout) {
|
||||
if (asic_timeout_counter >= BM1368_TIMEOUT_THRESHOLD) {
|
||||
ESP_LOGE(TAG, "ASIC not sending data");
|
||||
asic_timeout_counter = 0;
|
||||
}
|
||||
asic_timeout_counter++;
|
||||
if (receive_work((uint8_t *)&asic_result, sizeof(asic_result)) == ESP_FAIL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (received != 11 || asic_response_buffer[0] != 0xAA || asic_response_buffer[1] != 0x55) {
|
||||
ESP_LOGE(TAG, "Serial RX invalid %i", received);
|
||||
ESP_LOG_BUFFER_HEX(TAG, asic_response_buffer, received);
|
||||
SERIAL_clear_buffer();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (asic_result *) asic_response_buffer;
|
||||
}
|
||||
|
||||
static uint16_t reverse_uint16(uint16_t num)
|
||||
{
|
||||
return (num >> 8) | (num << 8);
|
||||
}
|
||||
|
||||
static uint32_t reverse_uint32(uint32_t val)
|
||||
{
|
||||
return ((val >> 24) & 0xff) |
|
||||
((val << 8) & 0xff0000) |
|
||||
((val >> 8) & 0xff00) |
|
||||
((val << 24) & 0xff000000);
|
||||
}
|
||||
|
||||
task_result * BM1368_proccess_work(void * pvParameters)
|
||||
{
|
||||
asic_result * asic_result = BM1368_receive_work();
|
||||
|
||||
if (asic_result == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t job_id = (asic_result->job_id & 0xf0) >> 1;
|
||||
uint8_t core_id = (uint8_t)((reverse_uint32(asic_result->nonce) >> 25) & 0x7f);
|
||||
uint8_t small_core_id = asic_result->job_id & 0x0f;
|
||||
uint32_t version_bits = (reverse_uint16(asic_result->version) << 13);
|
||||
uint8_t job_id = (asic_result.job_id & 0xf0) >> 1;
|
||||
uint8_t core_id = (uint8_t)((ntohl(asic_result.nonce) >> 25) & 0x7f);
|
||||
uint8_t small_core_id = asic_result.job_id & 0x0f;
|
||||
uint32_t version_bits = (ntohs(asic_result.version) << 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_LOGE(TAG, "Invalid job found, 0x%02X", job_id);
|
||||
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.nonce = asic_result.nonce;
|
||||
result.rolled_version = rolled_version;
|
||||
|
||||
return &result;
|
||||
}
|
||||
}
|
||||
|
@ -8,14 +8,23 @@
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "frequency_transition_bmXX.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#define BM1370_CHIP_ID 0x1370
|
||||
#define BM1370_CHIP_ID_RESPONSE_LENGTH 11
|
||||
|
||||
#ifdef CONFIG_GPIO_ASIC_RESET
|
||||
#define GPIO_ASIC_RESET CONFIG_GPIO_ASIC_RESET
|
||||
#else
|
||||
#define GPIO_ASIC_RESET 1
|
||||
#endif
|
||||
|
||||
#define TYPE_JOB 0x20
|
||||
#define TYPE_CMD 0x40
|
||||
@ -45,23 +54,18 @@
|
||||
#define TICKET_MASK 0x14
|
||||
#define MISC_CONTROL 0x18
|
||||
|
||||
#define BM1370_TIMEOUT_MS 10000
|
||||
#define BM1370_TIMEOUT_THRESHOLD 2
|
||||
|
||||
typedef struct __attribute__((__packed__))
|
||||
{
|
||||
uint8_t preamble[2];
|
||||
uint16_t preamble;
|
||||
uint32_t nonce;
|
||||
uint8_t midstate_num;
|
||||
uint8_t job_id;
|
||||
uint16_t version;
|
||||
uint8_t crc;
|
||||
} asic_result;
|
||||
} bm1370_asic_result_t;
|
||||
|
||||
static const char * TAG = "bm1370Module";
|
||||
|
||||
|
||||
static uint8_t asic_response_buffer[SERIAL_BUF_SIZE];
|
||||
static task_result result;
|
||||
|
||||
/// @brief
|
||||
@ -141,76 +145,76 @@ void BM1370_set_version_mask(uint32_t version_mask)
|
||||
_send_BM1370(TYPE_CMD | GROUP_ALL | CMD_WRITE, version_cmd, 6, BM1370_SERIALTX_DEBUG);
|
||||
}
|
||||
|
||||
void BM1370_send_hash_frequency(int id, float target_freq, float max_diff) {
|
||||
uint8_t freqbuf[6] = {0x00, 0x08, 0x40, 0xA0, 0x02, 0x41};
|
||||
uint8_t postdiv_min = 255;
|
||||
uint8_t postdiv2_min = 255;
|
||||
float best_freq = 0;
|
||||
uint8_t best_refdiv = 0, best_fbdiv = 0, best_postdiv1 = 0, best_postdiv2 = 0;
|
||||
void BM1370_send_hash_frequency(float target_freq) {
|
||||
// default 200Mhz if it fails
|
||||
unsigned char freqbuf[6] = {0x00, 0x08, 0x40, 0xA0, 0x02, 0x41}; // freqbuf - pll0_parameter
|
||||
float newf = 200.0;
|
||||
|
||||
for (uint8_t refdiv = 2; refdiv > 0; refdiv--) {
|
||||
for (uint8_t postdiv1 = 7; postdiv1 > 0; postdiv1--) {
|
||||
for (uint8_t postdiv2 = 7; postdiv2 > 0; postdiv2--) {
|
||||
uint16_t fb_divider = round(target_freq / 25.0 * (refdiv * postdiv2 * postdiv1));
|
||||
float newf = 25.0 * fb_divider / (refdiv * postdiv2 * postdiv1);
|
||||
|
||||
if (fb_divider >= 0xa0 && fb_divider <= 0xef &&
|
||||
fabs(target_freq - newf) < max_diff &&
|
||||
postdiv1 >= postdiv2 &&
|
||||
postdiv1 * postdiv2 < postdiv_min &&
|
||||
postdiv2 <= postdiv2_min) {
|
||||
|
||||
postdiv2_min = postdiv2;
|
||||
postdiv_min = postdiv1 * postdiv2;
|
||||
best_freq = newf;
|
||||
best_refdiv = refdiv;
|
||||
best_fbdiv = fb_divider;
|
||||
best_postdiv1 = postdiv1;
|
||||
best_postdiv2 = postdiv2;
|
||||
uint8_t fb_divider = 0;
|
||||
uint8_t post_divider1 = 0, post_divider2 = 0;
|
||||
uint8_t ref_divider = 0;
|
||||
float min_difference = 10;
|
||||
float max_diff = 1.0;
|
||||
|
||||
// refdiver is 2 or 1
|
||||
// postdivider 2 is 1 to 7
|
||||
// postdivider 1 is 1 to 7 and greater than or equal to postdivider 2
|
||||
// fbdiv is 0xa0 to 0xef
|
||||
for (uint8_t refdiv_loop = 2; refdiv_loop > 0 && fb_divider == 0; refdiv_loop--) {
|
||||
for (uint8_t postdiv1_loop = 7; postdiv1_loop > 0 && fb_divider == 0; postdiv1_loop--) {
|
||||
for (uint8_t postdiv2_loop = 7; postdiv2_loop > 0 && fb_divider == 0; postdiv2_loop--) {
|
||||
if (postdiv1_loop >= postdiv2_loop) {
|
||||
int temp_fb_divider = round(((float) (postdiv1_loop * postdiv2_loop * target_freq * refdiv_loop) / 25.0));
|
||||
|
||||
if (temp_fb_divider >= 0xa0 && temp_fb_divider <= 0xef) {
|
||||
float temp_freq = 25.0 * (float) temp_fb_divider / (float) (refdiv_loop * postdiv2_loop * postdiv1_loop);
|
||||
float freq_diff = fabs(target_freq - temp_freq);
|
||||
|
||||
if (freq_diff < min_difference && freq_diff < max_diff) {
|
||||
fb_divider = temp_fb_divider;
|
||||
post_divider1 = postdiv1_loop;
|
||||
post_divider2 = postdiv2_loop;
|
||||
ref_divider = refdiv_loop;
|
||||
min_difference = freq_diff;
|
||||
newf = temp_freq;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (best_fbdiv == 0) {
|
||||
if (fb_divider == 0) {
|
||||
ESP_LOGE(TAG, "Failed to find PLL settings for target frequency %.2f", target_freq);
|
||||
return;
|
||||
}
|
||||
|
||||
freqbuf[2] = (best_fbdiv * 25 / best_refdiv >= 2400) ? 0x50 : 0x40;
|
||||
freqbuf[3] = best_fbdiv;
|
||||
freqbuf[4] = best_refdiv;
|
||||
freqbuf[5] = (((best_postdiv1 - 1) & 0xf) << 4) | ((best_postdiv2 - 1) & 0xf);
|
||||
freqbuf[3] = fb_divider;
|
||||
freqbuf[4] = ref_divider;
|
||||
freqbuf[5] = (((post_divider1 - 1) & 0xf) << 4) + ((post_divider2 - 1) & 0xf);
|
||||
|
||||
if (id != -1) {
|
||||
freqbuf[0] = id * 2;
|
||||
_send_BM1370(TYPE_CMD | GROUP_SINGLE | CMD_WRITE, freqbuf, 6, BM1370_SERIALTX_DEBUG);
|
||||
} else {
|
||||
_send_BM1370(TYPE_CMD | GROUP_ALL | CMD_WRITE, freqbuf, 6, BM1370_SERIALTX_DEBUG);
|
||||
if (fb_divider * 25 / (float) ref_divider >= 2400) {
|
||||
freqbuf[2] = 0x50;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Setting Frequency to %.2fMHz (%.2f)", target_freq, best_freq);
|
||||
_send_BM1370(TYPE_CMD | GROUP_ALL | CMD_WRITE, freqbuf, 6, BM1370_SERIALTX_DEBUG);
|
||||
|
||||
ESP_LOGI(TAG, "Setting Frequency to %.2fMHz (%.2f)", target_freq, newf);
|
||||
}
|
||||
|
||||
static void do_frequency_ramp_up(float target_frequency) {
|
||||
float current = 56.25;
|
||||
float step = 6.25;
|
||||
|
||||
if (target_frequency == 0) {
|
||||
ESP_LOGI(TAG, "Skipping frequency ramp");
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Ramping up frequency from %.2f MHz to %.2f MHz with step %.2f MHz", current, target_frequency, step);
|
||||
|
||||
BM1370_send_hash_frequency(-1, current, 0.001);
|
||||
|
||||
while (current < target_frequency) {
|
||||
float next_step = fminf(step, target_frequency - current);
|
||||
current += next_step;
|
||||
BM1370_send_hash_frequency(-1, current, 0.001);
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
}
|
||||
ESP_LOGI(TAG, "Ramping up frequency from 56.25 MHz to %.2f MHz", target_frequency);
|
||||
do_frequency_transition(target_frequency, BM1370_send_hash_frequency, 1370);
|
||||
}
|
||||
|
||||
// Add a public function for external use
|
||||
bool BM1370_set_frequency(float target_freq) {
|
||||
return do_frequency_transition(target_freq, BM1370_send_hash_frequency, 1370);
|
||||
}
|
||||
|
||||
static uint8_t _send_init(uint64_t frequency, uint16_t asic_count)
|
||||
@ -224,15 +228,11 @@ static uint8_t _send_init(uint64_t frequency, uint16_t asic_count)
|
||||
unsigned char init3[7] = {0x55, 0xAA, 0x52, 0x05, 0x00, 0x00, 0x0A};
|
||||
_send_simple(init3, 7);
|
||||
|
||||
int chip_counter = 0;
|
||||
while (true) {
|
||||
if (SERIAL_rx(asic_response_buffer, 11, 1000) > 0) {
|
||||
chip_counter++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
int chip_counter = count_asic_chips(asic_count, BM1370_CHIP_ID, BM1370_CHIP_ID_RESPONSE_LENGTH);
|
||||
|
||||
if (chip_counter == 0) {
|
||||
return 0;
|
||||
}
|
||||
ESP_LOGI(TAG, "%i chip(s) detected on the chain, expected %i", chip_counter, asic_count);
|
||||
|
||||
// set version mask
|
||||
BM1370_set_version_mask(STRATUM_DEFAULT_VERSION_MASK);
|
||||
@ -313,7 +313,7 @@ static uint8_t _send_init(uint64_t frequency, uint16_t asic_count)
|
||||
//ramp up the hash frequency
|
||||
do_frequency_ramp_up(frequency);
|
||||
|
||||
//register 10 is still a bit of a mystery. discussion: https://github.com/skot/ESP-Miner/pull/167
|
||||
//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
|
||||
@ -353,8 +353,6 @@ uint8_t BM1370_init(uint64_t frequency, uint16_t asic_count)
|
||||
{
|
||||
ESP_LOGI(TAG, "Initializing BM1370");
|
||||
|
||||
memset(asic_response_buffer, 0, SERIAL_BUF_SIZE);
|
||||
|
||||
esp_rom_gpio_pad_select_gpio(GPIO_ASIC_RESET);
|
||||
gpio_set_direction(GPIO_ASIC_RESET, GPIO_MODE_OUTPUT);
|
||||
|
||||
@ -449,84 +447,38 @@ void BM1370_send_work(void * pvParameters, bm_job * next_bm_job)
|
||||
_send_BM1370((TYPE_JOB | GROUP_SINGLE | CMD_WRITE), (uint8_t *)&job, sizeof(BM1370_job), BM1370_DEBUG_WORK);
|
||||
}
|
||||
|
||||
asic_result * BM1370_receive_work(void)
|
||||
task_result * BM1370_process_work(void * pvParameters)
|
||||
{
|
||||
// wait for a response
|
||||
int received = SERIAL_rx(asic_response_buffer, 11, BM1370_TIMEOUT_MS);
|
||||
bm1370_asic_result_t asic_result = {0};
|
||||
|
||||
bool uart_err = received < 0;
|
||||
bool uart_timeout = received == 0;
|
||||
uint8_t asic_timeout_counter = 0;
|
||||
|
||||
// handle response
|
||||
if (uart_err) {
|
||||
ESP_LOGI(TAG, "UART Error in serial RX");
|
||||
return NULL;
|
||||
} else if (uart_timeout) {
|
||||
if (asic_timeout_counter >= BM1370_TIMEOUT_THRESHOLD) {
|
||||
ESP_LOGE(TAG, "ASIC not sending data");
|
||||
asic_timeout_counter = 0;
|
||||
}
|
||||
asic_timeout_counter++;
|
||||
if (receive_work((uint8_t *)&asic_result, sizeof(asic_result)) == ESP_FAIL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (received != 11 || 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);
|
||||
SERIAL_clear_buffer();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (asic_result *) asic_response_buffer;
|
||||
}
|
||||
|
||||
static uint16_t reverse_uint16(uint16_t num)
|
||||
{
|
||||
return (num >> 8) | (num << 8);
|
||||
}
|
||||
|
||||
static uint32_t reverse_uint32(uint32_t val)
|
||||
{
|
||||
return ((val >> 24) & 0xff) | // Move byte 3 to byte 0
|
||||
((val << 8) & 0xff0000) | // Move byte 1 to byte 2
|
||||
((val >> 8) & 0xff00) | // Move byte 2 to byte 1
|
||||
((val << 24) & 0xff000000); // Move byte 0 to byte 3
|
||||
}
|
||||
|
||||
task_result * BM1370_proccess_work(void * pvParameters)
|
||||
{
|
||||
|
||||
asic_result * asic_result = BM1370_receive_work();
|
||||
|
||||
if (asic_result == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// uint8_t job_id = asic_result->job_id;
|
||||
// uint8_t job_id = asic_result.job_id;
|
||||
// uint8_t rx_job_id = ((int8_t)job_id & 0xf0) >> 1;
|
||||
// ESP_LOGI(TAG, "Job ID: %02X, RX: %02X", job_id, rx_job_id);
|
||||
|
||||
// uint8_t job_id = asic_result->job_id & 0xf8;
|
||||
// ESP_LOGI(TAG, "Job ID: %02X, Core: %01X", job_id, asic_result->job_id & 0x07);
|
||||
// uint8_t job_id = asic_result.job_id & 0xf8;
|
||||
// ESP_LOGI(TAG, "Job ID: %02X, Core: %01X", job_id, asic_result.job_id & 0x07);
|
||||
|
||||
uint8_t job_id = (asic_result->job_id & 0xf0) >> 1;
|
||||
uint8_t core_id = (uint8_t)((reverse_uint32(asic_result->nonce) >> 25) & 0x7f); // BM1370 has 80 cores, so it should be coded on 7 bits
|
||||
uint8_t small_core_id = asic_result->job_id & 0x0f; // BM1370 has 16 small cores, so it should be coded on 4 bits
|
||||
uint32_t version_bits = (reverse_uint16(asic_result->version) << 13); // shift the 16 bit value left 13
|
||||
uint8_t job_id = (asic_result.job_id & 0xf0) >> 1;
|
||||
uint8_t core_id = (uint8_t)((ntohl(asic_result.nonce) >> 25) & 0x7f); // BM1370 has 80 cores, so it should be coded on 7 bits
|
||||
uint8_t small_core_id = asic_result.job_id & 0x0f; // BM1370 has 16 small cores, so it should be coded on 4 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_LOGE(TAG, "Invalid job nonce found, 0x%02X", job_id);
|
||||
ESP_LOGW(TAG, "Invalid job nonce 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.nonce = asic_result.nonce;
|
||||
result.rolled_version = rolled_version;
|
||||
|
||||
return &result;
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
@ -15,7 +16,14 @@
|
||||
#include "mining.h"
|
||||
#include "global_state.h"
|
||||
|
||||
#define BM1397_CHIP_ID 0x1397
|
||||
#define BM1397_CHIP_ID_RESPONSE_LENGTH 9
|
||||
|
||||
#ifdef CONFIG_GPIO_ASIC_RESET
|
||||
#define GPIO_ASIC_RESET CONFIG_GPIO_ASIC_RESET
|
||||
#else
|
||||
#define GPIO_ASIC_RESET 1
|
||||
#endif
|
||||
|
||||
#define TYPE_JOB 0x20
|
||||
#define TYPE_CMD 0x40
|
||||
@ -45,21 +53,17 @@
|
||||
#define TICKET_MASK 0x14
|
||||
#define MISC_CONTROL 0x18
|
||||
|
||||
#define BM1397_TIMEOUT_MS 10000
|
||||
#define BM1397_TIMEOUT_THRESHOLD 2
|
||||
|
||||
typedef struct __attribute__((__packed__))
|
||||
{
|
||||
uint8_t preamble[2];
|
||||
uint16_t preamble;
|
||||
uint32_t nonce;
|
||||
uint8_t midstate_num;
|
||||
uint8_t job_id;
|
||||
uint8_t crc;
|
||||
} asic_result;
|
||||
} bm1397_asic_result_t;
|
||||
|
||||
static const char *TAG = "bm1397Module";
|
||||
|
||||
static uint8_t asic_response_buffer[SERIAL_BUF_SIZE];
|
||||
static uint32_t prev_nonce = 0;
|
||||
static task_result result;
|
||||
|
||||
@ -137,7 +141,6 @@ void BM1397_set_version_mask(uint32_t version_mask) {
|
||||
// borrowed from cgminer driver-gekko.c calc_gsf_freq()
|
||||
void BM1397_send_hash_frequency(float frequency)
|
||||
{
|
||||
|
||||
unsigned char prefreq1[9] = {0x00, 0x70, 0x0F, 0x0F, 0x0F, 0x00}; // prefreq - pll0_divider
|
||||
|
||||
// default 200Mhz if it fails
|
||||
@ -229,15 +232,11 @@ static uint8_t _send_init(uint64_t frequency, uint16_t asic_count)
|
||||
// send the init command
|
||||
_send_read_address();
|
||||
|
||||
int chip_counter = 0;
|
||||
while (true) {
|
||||
if (SERIAL_rx(asic_response_buffer, 11, 1000) > 0) {
|
||||
chip_counter++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
int chip_counter = count_asic_chips(asic_count, BM1397_CHIP_ID, BM1397_CHIP_ID_RESPONSE_LENGTH);
|
||||
|
||||
if (chip_counter == 0) {
|
||||
return 0;
|
||||
}
|
||||
ESP_LOGI(TAG, "%i chip(s) detected on the chain, expected %i", chip_counter, asic_count);
|
||||
|
||||
// send serial data
|
||||
vTaskDelay(SLEEP_TIME / portTICK_PERIOD_MS);
|
||||
@ -294,8 +293,6 @@ uint8_t BM1397_init(uint64_t frequency, uint16_t asic_count)
|
||||
{
|
||||
ESP_LOGI(TAG, "Initializing BM1397");
|
||||
|
||||
memset(asic_response_buffer, 0, SERIAL_BUF_SIZE);
|
||||
|
||||
esp_rom_gpio_pad_select_gpio(GPIO_ASIC_RESET);
|
||||
gpio_set_direction(GPIO_ASIC_RESET, GPIO_MODE_OUTPUT);
|
||||
|
||||
@ -358,7 +355,6 @@ static uint8_t id = 0;
|
||||
|
||||
void BM1397_send_work(void *pvParameters, bm_job *next_bm_job)
|
||||
{
|
||||
|
||||
GlobalState *GLOBAL_STATE = (GlobalState *)pvParameters;
|
||||
|
||||
job_packet job;
|
||||
@ -400,61 +396,24 @@ void BM1397_send_work(void *pvParameters, bm_job *next_bm_job)
|
||||
_send_BM1397((TYPE_JOB | GROUP_SINGLE | CMD_WRITE), (uint8_t *)&job, sizeof(job_packet), BM1397_DEBUG_WORK);
|
||||
}
|
||||
|
||||
asic_result *BM1397_receive_work(void)
|
||||
task_result *BM1397_process_work(void *pvParameters)
|
||||
{
|
||||
bm1397_asic_result_t asic_result = {0};
|
||||
|
||||
// wait for a response
|
||||
int received = SERIAL_rx(asic_response_buffer, 9, BM1397_TIMEOUT_MS);
|
||||
|
||||
bool uart_err = received < 0;
|
||||
bool uart_timeout = received == 0;
|
||||
uint8_t asic_timeout_counter = 0;
|
||||
|
||||
// handle response
|
||||
if (uart_err) {
|
||||
ESP_LOGI(TAG, "UART Error in serial RX");
|
||||
return NULL;
|
||||
} else if (uart_timeout) {
|
||||
if (asic_timeout_counter >= BM1397_TIMEOUT_THRESHOLD) {
|
||||
ESP_LOGE(TAG, "ASIC not sending data");
|
||||
asic_timeout_counter = 0;
|
||||
}
|
||||
asic_timeout_counter++;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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);
|
||||
SERIAL_clear_buffer();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (asic_result *)asic_response_buffer;
|
||||
}
|
||||
|
||||
task_result *BM1397_proccess_work(void *pvParameters)
|
||||
{
|
||||
|
||||
asic_result *asic_result = BM1397_receive_work();
|
||||
|
||||
if (asic_result == NULL)
|
||||
{
|
||||
ESP_LOGI(TAG, "return null");
|
||||
if (receive_work((uint8_t *)&asic_result, sizeof(asic_result)) == ESP_FAIL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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;
|
||||
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)
|
||||
{
|
||||
ESP_LOGI(TAG, "Invalid job nonce found, id=%d", rx_job_id);
|
||||
ESP_LOGW(TAG, "Invalid job nonce found, id=%d", rx_job_id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -469,26 +428,26 @@ task_result *BM1397_proccess_work(void *pvParameters)
|
||||
// most of the time it behavies however
|
||||
if (nonce_found == 0)
|
||||
{
|
||||
first_nonce = asic_result->nonce;
|
||||
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
|
||||
{
|
||||
prev_nonce = asic_result->nonce;
|
||||
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;
|
||||
|
@ -1,4 +1,14 @@
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "serial.h"
|
||||
#include "esp_log.h"
|
||||
#include "crc.h"
|
||||
|
||||
#define PREAMBLE 0xAA55
|
||||
|
||||
static const char * TAG = "common";
|
||||
|
||||
unsigned char _reverse_bits(unsigned char num)
|
||||
{
|
||||
@ -24,4 +34,95 @@ int _largest_power_of_two(int num)
|
||||
}
|
||||
|
||||
return 1 << power;
|
||||
}
|
||||
|
||||
int count_asic_chips(uint16_t asic_count, uint16_t chip_id, int chip_id_response_length)
|
||||
{
|
||||
uint8_t buffer[11] = {0};
|
||||
|
||||
int chip_counter = 0;
|
||||
while (true) {
|
||||
int received = SERIAL_rx(buffer, chip_id_response_length, 1000);
|
||||
if (received == 0) break;
|
||||
|
||||
if (received == -1) {
|
||||
ESP_LOGE(TAG, "Error reading CHIP_ID");
|
||||
break;
|
||||
}
|
||||
|
||||
if (received != chip_id_response_length) {
|
||||
ESP_LOGE(TAG, "Invalid CHIP_ID response length: expected %d, got %d", chip_id_response_length, received);
|
||||
ESP_LOG_BUFFER_HEX(TAG, buffer, received);
|
||||
break;
|
||||
}
|
||||
|
||||
uint16_t received_preamble = (buffer[0] << 8) | buffer[1];
|
||||
if (received_preamble != PREAMBLE) {
|
||||
ESP_LOGW(TAG, "Preamble mismatch: expected 0x%04x, got 0x%04x", PREAMBLE, received_preamble);
|
||||
ESP_LOG_BUFFER_HEX(TAG, buffer, received);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint16_t received_chip_id = (buffer[2] << 8) | buffer[3];
|
||||
if (received_chip_id != chip_id) {
|
||||
ESP_LOGW(TAG, "CHIP_ID response mismatch: expected 0x%04x, got 0x%04x", chip_id, received_chip_id);
|
||||
ESP_LOG_BUFFER_HEX(TAG, buffer, received);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (crc5(buffer + 2, received - 2) != 0) {
|
||||
ESP_LOGW(TAG, "Checksum failed on CHIP_ID response");
|
||||
ESP_LOG_BUFFER_HEX(TAG, buffer, received);
|
||||
continue;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Chip %d detected: CORE_NUM: 0x%02x ADDR: 0x%02x", chip_counter, buffer[4], buffer[5]);
|
||||
|
||||
chip_counter++;
|
||||
}
|
||||
|
||||
if (chip_counter != asic_count) {
|
||||
ESP_LOGW(TAG, "%i chip(s) detected on the chain, expected %i", chip_counter, asic_count);
|
||||
}
|
||||
|
||||
return chip_counter;
|
||||
}
|
||||
|
||||
esp_err_t receive_work(uint8_t * buffer, int buffer_size)
|
||||
{
|
||||
int received = SERIAL_rx(buffer, buffer_size, 10000);
|
||||
|
||||
if (received < 0) {
|
||||
ESP_LOGE(TAG, "UART error in serial RX");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (received == 0) {
|
||||
ESP_LOGD(TAG, "UART timeout in serial RX");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (received != buffer_size) {
|
||||
ESP_LOGE(TAG, "Invalid response length %i", received);
|
||||
ESP_LOG_BUFFER_HEX(TAG, buffer, received);
|
||||
SERIAL_clear_buffer();
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
uint16_t received_preamble = (buffer[0] << 8) | buffer[1];
|
||||
if (received_preamble != PREAMBLE) {
|
||||
ESP_LOGE(TAG, "Preamble mismatch: got 0x%04x, expected 0x%04x", received_preamble, PREAMBLE);
|
||||
ESP_LOG_BUFFER_HEX(TAG, buffer, received);
|
||||
SERIAL_clear_buffer();
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (crc5(buffer + 2, buffer_size - 2) != 0) {
|
||||
ESP_LOGE(TAG, "Checksum failed on response");
|
||||
ESP_LOG_BUFFER_HEX(TAG, buffer, received);
|
||||
SERIAL_clear_buffer();
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bm1397.h"
|
||||
#define CRC5_MASK 0x1F
|
||||
|
||||
/* compute crc5 over given number of bytes */
|
||||
// adapted from https://mightydevices.com/index.php/2018/02/reverse-engineering-antminer-s1/
|
||||
|
56
components/asic/frequency_transition_bmXX.c
Normal file
56
components/asic/frequency_transition_bmXX.c
Normal file
@ -0,0 +1,56 @@
|
||||
#include "frequency_transition_bmXX.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include <math.h>
|
||||
|
||||
const char *FREQUENCY_TRANSITION_TAG = "frequency_transition";
|
||||
|
||||
static float current_frequency = 56.25;
|
||||
|
||||
bool do_frequency_transition(float target_frequency, set_hash_frequency_fn set_frequency_fn, int asic_type) {
|
||||
if (set_frequency_fn == NULL) {
|
||||
ESP_LOGE(FREQUENCY_TRANSITION_TAG, "Invalid function pointer provided");
|
||||
return false;
|
||||
}
|
||||
|
||||
float step = 6.25;
|
||||
float current = current_frequency;
|
||||
float target = target_frequency;
|
||||
|
||||
float direction = (target > current) ? step : -step;
|
||||
|
||||
// If current frequency is not a multiple of step, adjust to the nearest multiple
|
||||
if (fmod(current, step) != 0) {
|
||||
float next_dividable;
|
||||
if (direction > 0) {
|
||||
next_dividable = ceil(current / step) * step;
|
||||
} else {
|
||||
next_dividable = floor(current / step) * step;
|
||||
}
|
||||
current = next_dividable;
|
||||
|
||||
// Call the provided hash frequency function
|
||||
set_frequency_fn(current);
|
||||
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
// Gradually adjust frequency in steps until target is reached
|
||||
while ((direction > 0 && current < target) || (direction < 0 && current > target)) {
|
||||
float next_step = fmin(fabs(direction), fabs(target - current));
|
||||
current += direction > 0 ? next_step : -next_step;
|
||||
|
||||
// Call the provided hash frequency function
|
||||
set_frequency_fn(current);
|
||||
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
// Set the final target frequency
|
||||
set_frequency_fn(target);
|
||||
current_frequency = target;
|
||||
|
||||
ESP_LOGI(FREQUENCY_TRANSITION_TAG, "Successfully transitioned ASIC type %d to %.2f MHz", asic_type, target);
|
||||
return true;
|
||||
}
|
25
components/asic/include/asic.h
Normal file
25
components/asic/include/asic.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef ASIC_H
|
||||
#define ASIC_H
|
||||
|
||||
#include <esp_err.h>
|
||||
#include "global_state.h"
|
||||
#include "common.h"
|
||||
|
||||
#define BITAXE_MAX_ASIC_COUNT 1
|
||||
#define BITAXE_ULTRA_ASIC_COUNT 1
|
||||
#define BITAXE_SUPRA_ASIC_COUNT 1
|
||||
#define BITAXE_GAMMA_ASIC_COUNT 1
|
||||
#define BITAXE_GAMMATURBO_ASIC_COUNT 2
|
||||
|
||||
uint8_t ASIC_init(GlobalState * GLOBAL_STATE);
|
||||
uint8_t ASIC_get_asic_count(GlobalState * GLOBAL_STATE);
|
||||
uint16_t ASIC_get_small_core_count(GlobalState * GLOBAL_STATE);
|
||||
task_result * ASIC_process_work(GlobalState * GLOBAL_STATE);
|
||||
int ASIC_set_max_baud(GlobalState * GLOBAL_STATE);
|
||||
void ASIC_set_job_difficulty_mask(GlobalState * GLOBAL_STATE, uint8_t mask);
|
||||
void ASIC_send_work(GlobalState * GLOBAL_STATE, void * next_job);
|
||||
void ASIC_set_version_mask(GlobalState * GLOBAL_STATE, uint32_t mask);
|
||||
bool ASIC_set_frequency(GlobalState * GLOBAL_STATE, float target_frequency);
|
||||
esp_err_t ASIC_set_device_model(GlobalState * GLOBAL_STATE);
|
||||
|
||||
#endif // ASIC_H
|
@ -7,7 +7,6 @@
|
||||
|
||||
#define ASIC_BM1366_JOB_FREQUENCY_MS 2000
|
||||
|
||||
#define CRC5_MASK 0x1F
|
||||
#define BM1366_ASIC_DIFFICULTY 256
|
||||
|
||||
#define BM1366_SERIALTX_DEBUG false
|
||||
@ -36,14 +35,13 @@ typedef struct __attribute__((__packed__))
|
||||
} BM1366_job;
|
||||
|
||||
uint8_t BM1366_init(uint64_t frequency, uint16_t asic_count);
|
||||
|
||||
void BM1366_send_init(void);
|
||||
void BM1366_send_work(void * GLOBAL_STATE, bm_job * next_bm_job);
|
||||
void BM1366_set_job_difficulty_mask(int);
|
||||
void BM1366_set_version_mask(uint32_t version_mask);
|
||||
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);
|
||||
bool BM1366_set_frequency(float target_freq);
|
||||
task_result * BM1366_process_work(void * GLOBAL_STATE);
|
||||
|
||||
#endif /* BM1366_H_ */
|
||||
|
@ -7,7 +7,6 @@
|
||||
|
||||
#define ASIC_BM1368_JOB_FREQUENCY_MS 500
|
||||
|
||||
#define CRC5_MASK 0x1F
|
||||
#define BM1368_ASIC_DIFFICULTY 256
|
||||
|
||||
#define BM1368_SERIALTX_DEBUG false
|
||||
@ -36,15 +35,13 @@ typedef struct __attribute__((__packed__))
|
||||
} BM1368_job;
|
||||
|
||||
uint8_t BM1368_init(uint64_t frequency, uint16_t asic_count);
|
||||
|
||||
uint8_t BM1368_send_init(void);
|
||||
void BM1368_send_work(void * GLOBAL_STATE, bm_job * next_bm_job);
|
||||
void BM1368_set_job_difficulty_mask(int);
|
||||
void BM1368_set_version_mask(uint32_t version_mask);
|
||||
int BM1368_set_max_baud(void);
|
||||
int BM1368_set_default_baud(void);
|
||||
bool BM1368_send_hash_frequency(float frequency);
|
||||
bool do_frequency_transition(float target_frequency);
|
||||
task_result * BM1368_proccess_work(void * GLOBAL_STATE);
|
||||
void BM1368_send_hash_frequency(float frequency);
|
||||
bool BM1368_set_frequency(float target_freq);
|
||||
task_result * BM1368_process_work(void * GLOBAL_STATE);
|
||||
|
||||
#endif /* BM1368_H_ */
|
||||
#endif /* BM1368_H_ */
|
||||
|
@ -7,7 +7,6 @@
|
||||
|
||||
#define ASIC_BM1370_JOB_FREQUENCY_MS 500
|
||||
|
||||
#define CRC5_MASK 0x1F
|
||||
#define BM1370_ASIC_DIFFICULTY 256
|
||||
|
||||
#define BM1370_SERIALTX_DEBUG true
|
||||
@ -36,14 +35,13 @@ typedef struct __attribute__((__packed__))
|
||||
} BM1370_job;
|
||||
|
||||
uint8_t BM1370_init(uint64_t frequency, uint16_t asic_count);
|
||||
|
||||
uint8_t BM1370_send_init(void);
|
||||
void BM1370_send_work(void * GLOBAL_STATE, bm_job * next_bm_job);
|
||||
void BM1370_set_job_difficulty_mask(int);
|
||||
void BM1370_set_version_mask(uint32_t version_mask);
|
||||
int BM1370_set_max_baud(void);
|
||||
int BM1370_set_default_baud(void);
|
||||
void BM1370_send_hash_frequency(int, float, float);
|
||||
task_result * BM1370_proccess_work(void * GLOBAL_STATE);
|
||||
void BM1370_send_hash_frequency(float frequency);
|
||||
bool BM1370_set_frequency(float target_freq);
|
||||
task_result * BM1370_process_work(void * GLOBAL_STATE);
|
||||
|
||||
#endif /* BM1370_H_ */
|
||||
|
@ -7,10 +7,9 @@
|
||||
|
||||
#define ASIC_BM1397_JOB_FREQUENCY_MS 20 //not currently used
|
||||
|
||||
#define CRC5_MASK 0x1F
|
||||
#define BM1397_ASIC_DIFFICULTY 256
|
||||
|
||||
#define BM1937_SERIALTX_DEBUG false
|
||||
#define BM1937_SERIALTX_DEBUG true
|
||||
#define BM1937_SERIALRX_DEBUG false
|
||||
#define BM1397_DEBUG_WORK false //causes insane amount of debug output
|
||||
#define BM1397_DEBUG_JOBS false //causes insane amount of debug output
|
||||
@ -50,13 +49,12 @@ typedef struct __attribute__((__packed__))
|
||||
} job_packet;
|
||||
|
||||
uint8_t BM1397_init(uint64_t frequency, uint16_t asic_count);
|
||||
|
||||
void BM1397_send_work(void * GLOBAL_STATE, bm_job * next_bm_job);
|
||||
void BM1397_set_job_difficulty_mask(int);
|
||||
void BM1397_set_version_mask(uint32_t version_mask);
|
||||
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_process_work(void * GLOBAL_STATE);
|
||||
|
||||
#endif /* BM1397_H_ */
|
||||
#endif /* BM1397_H_ */
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define COMMON_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
typedef struct __attribute__((__packed__))
|
||||
{
|
||||
@ -13,4 +14,7 @@ typedef struct __attribute__((__packed__))
|
||||
unsigned char _reverse_bits(unsigned char num);
|
||||
int _largest_power_of_two(int num);
|
||||
|
||||
#endif
|
||||
int count_asic_chips(uint16_t asic_count, uint16_t chip_id, int chip_id_response_length);
|
||||
esp_err_t receive_work(uint8_t * buffer, int buffer_size);
|
||||
|
||||
#endif /* COMMON_H_ */
|
||||
|
31
components/asic/include/frequency_transition_bmXX.h
Normal file
31
components/asic/include/frequency_transition_bmXX.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef FREQUENCY_TRANSITION_H
|
||||
#define FREQUENCY_TRANSITION_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
extern const char *FREQUENCY_TRANSITION_TAG;
|
||||
|
||||
/**
|
||||
* @brief Function pointer type for ASIC hash frequency setting functions
|
||||
*
|
||||
* This type defines the signature for functions that set the hash frequency
|
||||
* for different ASIC types.
|
||||
*
|
||||
* @param frequency The frequency to set in MHz
|
||||
*/
|
||||
typedef void (*set_hash_frequency_fn)(float frequency);
|
||||
|
||||
/**
|
||||
* @brief Transition the ASIC frequency to a target value
|
||||
*
|
||||
* This function gradually adjusts the ASIC frequency to reach the target value,
|
||||
* stepping up or down in increments to ensure stability.
|
||||
*
|
||||
* @param target_frequency The target frequency in MHz
|
||||
* @param set_frequency_fn Function pointer to the appropriate ASIC's set_hash_frequency function
|
||||
* @param asic_type The type of ASIC chip (for logging purposes only)
|
||||
* @return bool True if the transition was successful, false otherwise
|
||||
*/
|
||||
bool do_frequency_transition(float target_frequency, set_hash_frequency_fn set_frequency_fn, int asic_type);
|
||||
|
||||
#endif // FREQUENCY_TRANSITION_H
|
@ -1,8 +1,7 @@
|
||||
#ifndef SERIAL_H_
|
||||
#define SERIAL_H_
|
||||
|
||||
#define SERIAL_BUF_SIZE 16
|
||||
#define CHUNK_SIZE 1024
|
||||
#include "esp_err.h"
|
||||
|
||||
int SERIAL_send(uint8_t *, int, bool);
|
||||
esp_err_t SERIAL_init(void);
|
||||
@ -11,4 +10,4 @@ int16_t SERIAL_rx(uint8_t *, uint16_t, uint16_t);
|
||||
void SERIAL_clear_buffer(void);
|
||||
esp_err_t SERIAL_set_baud(int baud);
|
||||
|
||||
#endif /* SERIAL_H_ */
|
||||
#endif /* SERIAL_H_ */
|
||||
|
@ -15,6 +15,9 @@
|
||||
#include "connect.h"
|
||||
#include "main.h"
|
||||
|
||||
// Maximum number of access points to scan
|
||||
#define MAX_AP_COUNT 20
|
||||
|
||||
#if CONFIG_ESP_WPA3_SAE_PWE_HUNT_AND_PECK
|
||||
#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_HUNT_AND_PECK
|
||||
#define EXAMPLE_H2E_IDENTIFIER ""
|
||||
@ -51,34 +54,114 @@ static EventGroupHandle_t s_wifi_event_group;
|
||||
|
||||
static const char * TAG = "wifi_station";
|
||||
|
||||
static bool is_scanning = false;
|
||||
static uint16_t ap_number = 0;
|
||||
static wifi_ap_record_t ap_info[MAX_AP_COUNT];
|
||||
|
||||
// Function to scan for available WiFi networks
|
||||
esp_err_t wifi_scan(wifi_ap_record_simple_t *ap_records, uint16_t *ap_count)
|
||||
{
|
||||
if (is_scanning) {
|
||||
ESP_LOGW(TAG, "Scan already in progress");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Starting Wi-Fi scan!");
|
||||
is_scanning = true;
|
||||
|
||||
wifi_ap_record_t current_ap_info;
|
||||
if (esp_wifi_sta_get_ap_info(¤t_ap_info) != ESP_OK) {
|
||||
ESP_LOGI(TAG, "Forcing disconnect so that we can scan!");
|
||||
esp_wifi_disconnect();
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
wifi_scan_config_t scan_config = {
|
||||
.ssid = 0,
|
||||
.bssid = 0,
|
||||
.channel = 0,
|
||||
.show_hidden = false
|
||||
};
|
||||
|
||||
esp_err_t err = esp_wifi_scan_start(&scan_config, false);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Wi-Fi scan start failed with error: %s", esp_err_to_name(err));
|
||||
is_scanning = false;
|
||||
return err;
|
||||
}
|
||||
|
||||
uint16_t retries_remaining = 10;
|
||||
while (is_scanning) {
|
||||
retries_remaining--;
|
||||
if (retries_remaining == 0) {
|
||||
is_scanning = false;
|
||||
return ESP_FAIL;
|
||||
}
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Wi-Fi networks found: %d", ap_number);
|
||||
if (ap_number == 0) {
|
||||
ESP_LOGW(TAG, "No Wi-Fi networks found");
|
||||
}
|
||||
|
||||
*ap_count = ap_number;
|
||||
memset(ap_records, 0, (*ap_count) * sizeof(wifi_ap_record_simple_t));
|
||||
for (int i = 0; i < ap_number; i++) {
|
||||
memcpy(ap_records[i].ssid, ap_info[i].ssid, sizeof(ap_records[i].ssid));
|
||||
ap_records[i].rssi = ap_info[i].rssi;
|
||||
ap_records[i].authmode = ap_info[i].authmode;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Finished Wi-Fi scan!");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static int s_retry_num = 0;
|
||||
|
||||
static char * _ip_addr_str;
|
||||
|
||||
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();
|
||||
MINER_set_wifi_status(WIFI_CONNECTING, 0, 0);
|
||||
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||
//lookup the exact reason code
|
||||
wifi_event_sta_disconnected_t* event = (wifi_event_sta_disconnected_t*) event_data;
|
||||
if (event->reason == WIFI_REASON_ROAMING) {
|
||||
ESP_LOGI(TAG, "We are roaming, nothing to do");
|
||||
if (event_base == WIFI_EVENT)
|
||||
{
|
||||
if (event_id == WIFI_EVENT_SCAN_DONE) {
|
||||
esp_wifi_scan_get_ap_num(&ap_number);
|
||||
ESP_LOGI(TAG, "Wi-Fi Scan Done");
|
||||
if (esp_wifi_scan_get_ap_records(&ap_number, ap_info) != ESP_OK) {
|
||||
ESP_LOGI(TAG, "Failed esp_wifi_scan_get_ap_records");
|
||||
}
|
||||
is_scanning = false;
|
||||
}
|
||||
|
||||
if (is_scanning) {
|
||||
ESP_LOGI(TAG, "Still scanning, ignore wifi event.");
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Could not connect to '%s' [rssi %d]: reason %d", event->ssid, event->rssi, event->reason);
|
||||
if (event_id == WIFI_EVENT_STA_START) {
|
||||
esp_wifi_connect();
|
||||
MINER_set_wifi_status(WIFI_CONNECTING, 0, 0);
|
||||
} else if (event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||
wifi_event_sta_disconnected_t* event = (wifi_event_sta_disconnected_t*) event_data;
|
||||
if (event->reason == WIFI_REASON_ROAMING) {
|
||||
ESP_LOGI(TAG, "We are roaming, nothing to do");
|
||||
return;
|
||||
}
|
||||
|
||||
// Wait a little
|
||||
vTaskDelay(2500 / portTICK_PERIOD_MS);
|
||||
esp_wifi_connect();
|
||||
s_retry_num++;
|
||||
ESP_LOGI(TAG, "Retrying WiFi connection...");
|
||||
MINER_set_wifi_status(WIFI_RETRYING, s_retry_num, event->reason);
|
||||
ESP_LOGI(TAG, "Could not connect to '%s' [rssi %d]: reason %d", event->ssid, event->rssi, event->reason);
|
||||
|
||||
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
||||
// Wait a little
|
||||
esp_wifi_connect();
|
||||
s_retry_num++;
|
||||
ESP_LOGI(TAG, "Retrying Wi-Fi connection...");
|
||||
MINER_set_wifi_status(WIFI_RETRYING, s_retry_num, event->reason);
|
||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
snprintf(_ip_addr_str, IP4ADDR_STRLEN_MAX, IPSTR, IP2STR(&event->ip_info.ip));
|
||||
|
||||
@ -160,10 +243,10 @@ esp_netif_t * wifi_init_sta(const char * wifi_ssid, const char * wifi_pass)
|
||||
wifi_auth_mode_t authmode;
|
||||
|
||||
if (strlen(wifi_pass) == 0) {
|
||||
ESP_LOGI(TAG, "No WiFi password provided, using open network");
|
||||
ESP_LOGI(TAG, "No Wi-Fi password provided, using open network");
|
||||
authmode = WIFI_AUTH_OPEN;
|
||||
} else {
|
||||
ESP_LOGI(TAG, "WiFi Password provided, using WPA2");
|
||||
ESP_LOGI(TAG, "Wi-Fi Password provided, using WPA2");
|
||||
authmode = WIFI_AUTH_WPA2_PSK;
|
||||
}
|
||||
|
||||
@ -214,7 +297,7 @@ void wifi_init(const char * wifi_ssid, const char * wifi_pass, const char * host
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL, &instance_any_id));
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL, &instance_got_ip));
|
||||
|
||||
/*Initialize WiFi */
|
||||
/* Initialize Wi-Fi */
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
|
||||
@ -224,27 +307,41 @@ void wifi_init(const char * wifi_ssid, const char * wifi_pass, const char * host
|
||||
ESP_LOGI(TAG, "ESP_WIFI Access Point On");
|
||||
wifi_init_softap();
|
||||
|
||||
/* Initialize STA */
|
||||
ESP_LOGI(TAG, "ESP_WIFI_MODE_STA");
|
||||
esp_netif_t * esp_netif_sta = wifi_init_sta(wifi_ssid, wifi_pass);
|
||||
|
||||
/* Start WiFi */
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
/* Skip connection if SSID is null */
|
||||
if (strlen(wifi_ssid) == 0) {
|
||||
ESP_LOGI(TAG, "No WiFi SSID provided, skipping connection");
|
||||
|
||||
/* Disable power savings for best performance */
|
||||
ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE));
|
||||
/* Start WiFi */
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
|
||||
/* Set Hostname */
|
||||
esp_err_t err = esp_netif_set_hostname(esp_netif_sta, hostname);
|
||||
if (err != ERR_OK) {
|
||||
ESP_LOGW(TAG, "esp_netif_set_hostname failed: %s", esp_err_to_name(err));
|
||||
/* Disable power savings for best performance */
|
||||
ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE));
|
||||
|
||||
return;
|
||||
} else {
|
||||
ESP_LOGI(TAG, "ESP_WIFI setting hostname to: %s", hostname);
|
||||
/* Initialize STA */
|
||||
ESP_LOGI(TAG, "ESP_WIFI_MODE_STA");
|
||||
esp_netif_t * esp_netif_sta = wifi_init_sta(wifi_ssid, wifi_pass);
|
||||
|
||||
/* Start Wi-Fi */
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
|
||||
/* Disable power savings for best performance */
|
||||
ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE));
|
||||
|
||||
/* Set Hostname */
|
||||
esp_err_t err = esp_netif_set_hostname(esp_netif_sta, hostname);
|
||||
if (err != ERR_OK) {
|
||||
ESP_LOGW(TAG, "esp_netif_set_hostname failed: %s", esp_err_to_name(err));
|
||||
} else {
|
||||
ESP_LOGI(TAG, "ESP_WIFI setting hostname to: %s", hostname);
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "wifi_init_sta finished.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "wifi_init_sta finished.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
EventBits_t wifi_connect(void)
|
||||
@ -257,4 +354,4 @@ EventBits_t wifi_connect(void)
|
||||
* happened. */
|
||||
|
||||
return bits;
|
||||
}
|
||||
}
|
@ -5,6 +5,14 @@
|
||||
#include <lwip/netdb.h>
|
||||
|
||||
#include "freertos/event_groups.h"
|
||||
#include "esp_wifi_types.h"
|
||||
|
||||
// Structure to hold WiFi scan results
|
||||
typedef struct {
|
||||
char ssid[33]; // 32 chars + null terminator
|
||||
int8_t rssi;
|
||||
wifi_auth_mode_t authmode;
|
||||
} wifi_ap_record_simple_t;
|
||||
|
||||
#define WIFI_SSID CONFIG_ESP_WIFI_SSID
|
||||
#define WIFI_PASS CONFIG_ESP_WIFI_PASSWORD
|
||||
@ -32,3 +40,4 @@ void wifi_softap_off(void);
|
||||
void wifi_init(const char * wifi_ssid, const char * wifi_pass, const char * hostname, char * ip_addr_str);
|
||||
EventBits_t wifi_connect(void);
|
||||
void generate_ssid(char * ssid);
|
||||
esp_err_t wifi_scan(wifi_ap_record_simple_t *ap_records, uint16_t *ap_count);
|
@ -1,5 +1,5 @@
|
||||
#ifndef MINING_H
|
||||
#define MINING_H
|
||||
#ifndef MINING_H_
|
||||
#define MINING_H_
|
||||
|
||||
#include "stratum_api.h"
|
||||
|
||||
@ -40,4 +40,4 @@ char *extranonce_2_generate(uint32_t extranonce_2, uint32_t length);
|
||||
|
||||
uint32_t increment_bitmask(const uint32_t value, const uint32_t mask);
|
||||
|
||||
#endif // MINING_H
|
||||
#endif /* MINING_H_ */
|
@ -62,25 +62,23 @@ typedef struct
|
||||
char * error_str;
|
||||
} StratumApiV1Message;
|
||||
|
||||
void STRATUM_V1_reset_uid();
|
||||
|
||||
void STRATUM_V1_initialize_buffer();
|
||||
|
||||
char *STRATUM_V1_receive_jsonrpc_line(int sockfd);
|
||||
|
||||
int STRATUM_V1_subscribe(int socket, char * model);
|
||||
int STRATUM_V1_subscribe(int socket, int send_uid, char * model);
|
||||
|
||||
void STRATUM_V1_parse(StratumApiV1Message *message, const char *stratum_json);
|
||||
|
||||
void STRATUM_V1_free_mining_notify(mining_notify *params);
|
||||
|
||||
int STRATUM_V1_authenticate(int socket, const char *username, const char *pass);
|
||||
int STRATUM_V1_authenticate(int socket, int send_uid, const char *username, const char *pass);
|
||||
|
||||
int STRATUM_V1_configure_version_rolling(int socket, uint32_t * version_mask);
|
||||
int STRATUM_V1_configure_version_rolling(int socket, int send_uid, uint32_t * version_mask);
|
||||
|
||||
int STRATUM_V1_suggest_difficulty(int socket, uint32_t difficulty);
|
||||
int STRATUM_V1_suggest_difficulty(int socket, int send_uid, uint32_t difficulty);
|
||||
|
||||
int STRATUM_V1_submit_share(int socket, const char *username, const char *jobid,
|
||||
int STRATUM_V1_submit_share(int socket, int send_uid, const char *username, const char *jobid,
|
||||
const char *extranonce_2, const uint32_t ntime, const uint32_t nonce,
|
||||
const uint32_t version);
|
||||
|
||||
|
@ -115,7 +115,7 @@ char *extranonce_2_generate(uint32_t extranonce_2, uint32_t length)
|
||||
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);
|
||||
bin2hex((uint8_t *)&extranonce_2, length, extranonce_2_str, length * 2 + 1);
|
||||
if (length > 4)
|
||||
{
|
||||
extranonce_2_str[8] = '0';
|
||||
|
@ -19,20 +19,9 @@ 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.
|
||||
// For requests not expecting a response (called notifications), this is null.
|
||||
static int send_uid = 1;
|
||||
|
||||
static void debug_stratum_tx(const char *);
|
||||
int _parse_stratum_subscribe_result_message(const char * result_json_str, char ** extranonce, int * extranonce2_len);
|
||||
|
||||
void STRATUM_V1_reset_uid()
|
||||
{
|
||||
ESP_LOGI(TAG, "Resetting stratum uid");
|
||||
|
||||
send_uid = 1;
|
||||
}
|
||||
|
||||
void STRATUM_V1_initialize_buffer()
|
||||
{
|
||||
json_rpc_buffer = malloc(BUFFER_SIZE);
|
||||
@ -148,12 +137,15 @@ void STRATUM_V1_parse(StratumApiV1Message * message, const char * stratum_json)
|
||||
cJSON * error_json = cJSON_GetObjectItem(json, "error");
|
||||
cJSON * reject_reason_json = cJSON_GetObjectItem(json, "reject-reason");
|
||||
|
||||
//if the result is null, then it's a fail
|
||||
// if the result is null, then it's a fail
|
||||
if (result_json == NULL) {
|
||||
message->response_success = false;
|
||||
|
||||
//if it's an error, then it's a fail
|
||||
message->error_str = strdup("unknown");
|
||||
|
||||
// if it's an error, then it's a fail
|
||||
} else if (!cJSON_IsNull(error_json)) {
|
||||
message->response_success = false;
|
||||
message->error_str = strdup("unknown");
|
||||
if (parsed_id < 5) {
|
||||
result = STRATUM_RESULT_SETUP;
|
||||
} else {
|
||||
@ -168,9 +160,8 @@ void STRATUM_V1_parse(StratumApiV1Message * message, const char * stratum_json)
|
||||
}
|
||||
}
|
||||
}
|
||||
message->response_success = false;
|
||||
|
||||
//if the result is a boolean, then parse it
|
||||
// if the result is a boolean, then parse it
|
||||
} else if (cJSON_IsBool(result_json)) {
|
||||
if (parsed_id < 5) {
|
||||
result = STRATUM_RESULT_SETUP;
|
||||
@ -181,6 +172,7 @@ void STRATUM_V1_parse(StratumApiV1Message * message, const char * stratum_json)
|
||||
message->response_success = true;
|
||||
} else {
|
||||
message->response_success = false;
|
||||
message->error_str = strdup("unknown");
|
||||
if (cJSON_IsString(reject_reason_json)) {
|
||||
message->error_str = strdup(cJSON_GetStringValue(reject_reason_json));
|
||||
}
|
||||
@ -319,31 +311,31 @@ int _parse_stratum_subscribe_result_message(const char * result_json_str, char *
|
||||
return 0;
|
||||
}
|
||||
|
||||
int STRATUM_V1_subscribe(int socket, char * model)
|
||||
int STRATUM_V1_subscribe(int socket, int send_uid, char * model)
|
||||
{
|
||||
// Subscribe
|
||||
char subscribe_msg[BUFFER_SIZE];
|
||||
const esp_app_desc_t *app_desc = esp_app_get_description();
|
||||
const char *version = app_desc->version;
|
||||
sprintf(subscribe_msg, "{\"id\": %d, \"method\": \"mining.subscribe\", \"params\": [\"bitaxe/%s/%s\"]}\n", send_uid++, model, version);
|
||||
sprintf(subscribe_msg, "{\"id\": %d, \"method\": \"mining.subscribe\", \"params\": [\"bitaxe/%s/%s\"]}\n", send_uid, model, version);
|
||||
debug_stratum_tx(subscribe_msg);
|
||||
|
||||
return write(socket, subscribe_msg, strlen(subscribe_msg));
|
||||
}
|
||||
|
||||
int STRATUM_V1_suggest_difficulty(int socket, uint32_t difficulty)
|
||||
int STRATUM_V1_suggest_difficulty(int socket, int send_uid, uint32_t difficulty)
|
||||
{
|
||||
char difficulty_msg[BUFFER_SIZE];
|
||||
sprintf(difficulty_msg, "{\"id\": %d, \"method\": \"mining.suggest_difficulty\", \"params\": [%ld]}\n", send_uid++, difficulty);
|
||||
sprintf(difficulty_msg, "{\"id\": %d, \"method\": \"mining.suggest_difficulty\", \"params\": [%ld]}\n", send_uid, difficulty);
|
||||
debug_stratum_tx(difficulty_msg);
|
||||
|
||||
return write(socket, difficulty_msg, strlen(difficulty_msg));
|
||||
}
|
||||
|
||||
int STRATUM_V1_authenticate(int socket, const char * username, const char * pass)
|
||||
int STRATUM_V1_authenticate(int socket, int send_uid, const char * username, const char * pass)
|
||||
{
|
||||
char authorize_msg[BUFFER_SIZE];
|
||||
sprintf(authorize_msg, "{\"id\": %d, \"method\": \"mining.authorize\", \"params\": [\"%s\", \"%s\"]}\n", send_uid++, username,
|
||||
sprintf(authorize_msg, "{\"id\": %d, \"method\": \"mining.authorize\", \"params\": [\"%s\", \"%s\"]}\n", send_uid, username,
|
||||
pass);
|
||||
debug_stratum_tx(authorize_msg);
|
||||
|
||||
@ -356,25 +348,26 @@ int STRATUM_V1_authenticate(int socket, const char * username, const char * pass
|
||||
/// @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.
|
||||
int 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)
|
||||
int STRATUM_V1_submit_share(int socket, int send_uid, 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];
|
||||
sprintf(submit_msg,
|
||||
"{\"id\": %d, \"method\": \"mining.submit\", \"params\": [\"%s\", \"%s\", \"%s\", \"%08lx\", \"%08lx\", \"%08lx\"]}\n",
|
||||
send_uid++, username, jobid, extranonce_2, ntime, nonce, version);
|
||||
send_uid, username, jobid, extranonce_2, ntime, nonce, version);
|
||||
debug_stratum_tx(submit_msg);
|
||||
|
||||
return write(socket, submit_msg, strlen(submit_msg));
|
||||
}
|
||||
|
||||
int STRATUM_V1_configure_version_rolling(int socket, uint32_t * version_mask)
|
||||
int STRATUM_V1_configure_version_rolling(int socket, int send_uid, uint32_t * version_mask)
|
||||
{
|
||||
char configure_msg[BUFFER_SIZE * 2];
|
||||
sprintf(configure_msg,
|
||||
"{\"id\": %d, \"method\": \"mining.configure\", \"params\": [[\"version-rolling\"], {\"version-rolling.mask\": "
|
||||
"\"ffffffff\"}]}\n",
|
||||
send_uid++);
|
||||
send_uid);
|
||||
debug_stratum_tx(configure_msg);
|
||||
|
||||
return write(socket, configure_msg, strlen(configure_msg));
|
||||
|
@ -138,7 +138,7 @@ TEST_CASE("Test extranonce 2 generation", "[mining extranonce2]")
|
||||
free(fifth);
|
||||
}
|
||||
|
||||
TEST_CASE("Test nonce diff checking", "[mining test_nonce]")
|
||||
TEST_CASE("Test nonce diff checking", "[mining test_nonce][not-on-qemu]")
|
||||
{
|
||||
mining_notify notify_message;
|
||||
notify_message.prev_block_hash = "d02b10fc0d4711eae1a805af50a8a83312a2215e00017f2b0000000000000000";
|
||||
@ -153,7 +153,7 @@ TEST_CASE("Test nonce diff checking", "[mining test_nonce]")
|
||||
TEST_ASSERT_EQUAL_INT(18, (int)diff);
|
||||
}
|
||||
|
||||
TEST_CASE("Test nonce diff checking 2", "[mining test_nonce]")
|
||||
TEST_CASE("Test nonce diff checking 2", "[mining test_nonce][not-on-qemu]")
|
||||
{
|
||||
mining_notify notify_message;
|
||||
notify_message.prev_block_hash = "0c859545a3498373a57452fac22eb7113df2a465000543520000000000000000";
|
||||
|
@ -222,7 +222,7 @@ void midstate_sha256_bin(const uint8_t *data, const size_t data_len, uint8_t *de
|
||||
mbedtls_sha256_update(&midstate, data, 64);
|
||||
|
||||
// memcpy(dest, midstate.state, 32);
|
||||
flip32bytes(dest, midstate.state);
|
||||
flip32bytes(dest, midstate.state);
|
||||
}
|
||||
|
||||
void swap_endian_words(const char *hex_words, uint8_t *output)
|
||||
|
@ -1,8 +1,8 @@
|
||||
key,type,encoding,value
|
||||
main,namespace,,
|
||||
hostname,data,string,bitaxe
|
||||
wifissid,data,string,myssid
|
||||
wifipass,data,string,password
|
||||
wifissid,data,string,
|
||||
wifipass,data,string,
|
||||
stratumurl,data,string,public-pool.io
|
||||
stratumport,data,u16,21496
|
||||
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
||||
|
@ -1,8 +1,8 @@
|
||||
key,type,encoding,value
|
||||
main,namespace,,
|
||||
hostname,data,string,bitaxe
|
||||
wifissid,data,string,myssid
|
||||
wifipass,data,string,password
|
||||
wifissid,data,string,
|
||||
wifipass,data,string,
|
||||
stratumurl,data,string,public-pool.io
|
||||
stratumport,data,u16,21496
|
||||
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
||||
|
@ -1,8 +1,8 @@
|
||||
key,type,encoding,value
|
||||
main,namespace,,
|
||||
hostname,data,string,bitaxe
|
||||
wifissid,data,string,myssid
|
||||
wifipass,data,string,password
|
||||
wifissid,data,string,
|
||||
wifipass,data,string,
|
||||
stratumurl,data,string,public-pool.io
|
||||
stratumport,data,u16,21496
|
||||
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
||||
|
@ -1,8 +1,8 @@
|
||||
key,type,encoding,value
|
||||
main,namespace,,
|
||||
hostname,data,string,bitaxe
|
||||
wifissid,data,string,myssid
|
||||
wifipass,data,string,password
|
||||
wifissid,data,string,
|
||||
wifipass,data,string,
|
||||
stratumurl,data,string,public-pool.io
|
||||
stratumport,data,u16,21496
|
||||
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
||||
|
@ -1,8 +1,8 @@
|
||||
key,type,encoding,value
|
||||
main,namespace,,
|
||||
hostname,data,string,bitaxe
|
||||
wifissid,data,string,myssid
|
||||
wifipass,data,string,password
|
||||
wifissid,data,string,
|
||||
wifipass,data,string,
|
||||
stratumurl,data,string,public-pool.io
|
||||
stratumport,data,u16,21496
|
||||
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
||||
|
@ -1,8 +1,8 @@
|
||||
key,type,encoding,value
|
||||
main,namespace,,
|
||||
hostname,data,string,bitaxe
|
||||
wifissid,data,string,myssid
|
||||
wifipass,data,string,password
|
||||
wifissid,data,string,
|
||||
wifipass,data,string,
|
||||
stratumurl,data,string,public-pool.io
|
||||
stratumport,data,u16,21496
|
||||
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
||||
|
@ -1,8 +1,8 @@
|
||||
key,type,encoding,value
|
||||
main,namespace,,
|
||||
hostname,data,string,bitaxe
|
||||
wifissid,data,string,myssid
|
||||
wifipass,data,string,password
|
||||
wifissid,data,string,
|
||||
wifipass,data,string,
|
||||
stratumurl,data,string,public-pool.io
|
||||
stratumport,data,u16,21496
|
||||
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
||||
|
@ -1,8 +1,8 @@
|
||||
key,type,encoding,value
|
||||
main,namespace,,
|
||||
hostname,data,string,bitaxe
|
||||
wifissid,data,string,myssid
|
||||
wifipass,data,string,password
|
||||
wifissid,data,string,
|
||||
wifipass,data,string,
|
||||
stratumurl,data,string,public-pool.io
|
||||
stratumport,data,u16,21496
|
||||
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
||||
|
@ -1,8 +1,8 @@
|
||||
key,type,encoding,value
|
||||
main,namespace,,
|
||||
hostname,data,string,bitaxe
|
||||
wifissid,data,string,myssid
|
||||
wifipass,data,string,password
|
||||
wifissid,data,string,
|
||||
wifipass,data,string,
|
||||
stratumurl,data,string,public-pool.io
|
||||
stratumport,data,u16,21496
|
||||
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
||||
|
@ -1,8 +1,8 @@
|
||||
key,type,encoding,value
|
||||
main,namespace,,
|
||||
hostname,data,string,bitaxe
|
||||
wifissid,data,string,myssid
|
||||
wifipass,data,string,password
|
||||
wifissid,data,string,
|
||||
wifipass,data,string,
|
||||
stratumurl,data,string,public-pool.io
|
||||
stratumport,data,u16,21496
|
||||
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
||||
|
24
config-800x.cvs
Normal file
24
config-800x.cvs
Normal file
@ -0,0 +1,24 @@
|
||||
key,type,encoding,value
|
||||
main,namespace,,
|
||||
hostname,data,string,bitaxe
|
||||
wifissid,data,string,myssid
|
||||
wifipass,data,string,password
|
||||
stratumurl,data,string,public-pool.io
|
||||
stratumport,data,u16,21496
|
||||
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
||||
stratumpass,data,string,x
|
||||
fbstratumurl,data,string,solo.ckpool.org
|
||||
fbstratumport,data,u16,3333
|
||||
fbstratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
||||
fbstratumpass,data,string,x
|
||||
asicfrequency,data,u16,525
|
||||
asicvoltage,data,u16,1150
|
||||
asicmodel,data,string,BM1370
|
||||
devicemodel,data,string,gammaturbo
|
||||
boardversion,data,string,800
|
||||
flipscreen,data,u16,1
|
||||
invertfanpol,data,u16,1
|
||||
autofanspeed,data,u16,1
|
||||
fanspeed,data,u16,100
|
||||
selftest,data,u16,0
|
||||
overheat_mode,data,u16,0
|
@ -1,5 +1,5 @@
|
||||
## Flashing Factory Image
|
||||
You can flash [factory images](https://github.com/skot/ESP-Miner/releases) to your Bitaxe using generic ESP32 flashing tools such as the [esptool-js website](https://espressif.github.io/esptool-js/)
|
||||
You can flash [factory images](https://github.com/bitaxeorg/ESP-Miner/releases) to your Bitaxe using generic ESP32 flashing tools such as the [esptool-js website](https://espressif.github.io/esptool-js/)
|
||||
|
||||
- Power up your bitaxe via the barrel connector
|
||||
- attach your bitaxe USB to your computer
|
||||
@ -11,7 +11,7 @@ You can flash [factory images](https://github.com/skot/ESP-Miner/releases) to yo
|
||||
- on PC it will prolly be one of those COM ports. Good luck.
|
||||
- Select the proper serial port and then click connect
|
||||
- Once the ESP Tool has connected to your Bitaxe over serial, Set the Flash Address to `0x0`
|
||||
- Under File click "Choose File" and select the [factory image](https://github.com/skot/ESP-Miner/releases) you want to flash. it's called something like `esp-miner-factory-400-v2.1.5d.bin` Be sure to use the image with the same version number as your Bitaxe (400 in this case)
|
||||
- Under File click "Choose File" and select the [factory image](https://github.com/bitaxeorg/ESP-Miner/releases) you want to flash. it's called something like `esp-miner-factory-400-v2.1.5.bin` Be sure to use the image with the same version number as your Bitaxe (400 in this case)
|
||||
- Down below click the "Program" button
|
||||
- Wait paitiently.
|
||||
- Keep waiting until the console on ESP Tool says "Leaving..."
|
||||
|
@ -1,18 +1,13 @@
|
||||
idf_component_register(
|
||||
SRCS
|
||||
"adc.c"
|
||||
"DS4432U.c"
|
||||
"EMC2101.c"
|
||||
"i2c_bitaxe.c"
|
||||
"INA260.c"
|
||||
"main.c"
|
||||
"nvs_config.c"
|
||||
"display.c"
|
||||
"screen.c"
|
||||
"input.c"
|
||||
"system.c"
|
||||
"TPS546.c"
|
||||
"vcore.c"
|
||||
"work_queue.c"
|
||||
"nvs_device.c"
|
||||
"lv_font_portfolio-6x8.c"
|
||||
@ -25,6 +20,15 @@ SRCS
|
||||
"./tasks/asic_task.c"
|
||||
"./tasks/asic_result_task.c"
|
||||
"./tasks/power_management_task.c"
|
||||
"./thermal/EMC2101.c"
|
||||
"./thermal/EMC2103.c"
|
||||
"./thermal/TMP1075.c"
|
||||
"./thermal/thermal.c"
|
||||
"./power/TPS546.c"
|
||||
"./power/DS4432U.c"
|
||||
"./power/INA260.c"
|
||||
"./power/power.c"
|
||||
"./power/vcore.c"
|
||||
|
||||
INCLUDE_DIRS
|
||||
"."
|
||||
@ -35,6 +39,8 @@ INCLUDE_DIRS
|
||||
"../components/connect/include"
|
||||
"../components/dns_server/include"
|
||||
"../components/stratum/include"
|
||||
"thermal"
|
||||
"power"
|
||||
|
||||
PRIV_REQUIRES
|
||||
"app_update"
|
||||
@ -52,6 +58,8 @@ PRIV_REQUIRES
|
||||
"spiffs"
|
||||
"vfs"
|
||||
"esp_driver_i2c"
|
||||
|
||||
EMBED_FILES "http_server/recovery_page.html"
|
||||
)
|
||||
|
||||
idf_build_set_property(COMPILE_OPTIONS "-DLV_CONF_INCLUDE_SIMPLE=1" APPEND)
|
||||
|
@ -27,6 +27,7 @@ typedef enum
|
||||
DEVICE_ULTRA,
|
||||
DEVICE_SUPRA,
|
||||
DEVICE_GAMMA,
|
||||
DEVICE_GAMMATURBO,
|
||||
} DeviceModel;
|
||||
|
||||
typedef enum
|
||||
@ -38,15 +39,20 @@ typedef enum
|
||||
ASIC_BM1370,
|
||||
} AsicModel;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t (*init_fn)(uint64_t, uint16_t);
|
||||
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);
|
||||
void (*set_version_mask)(uint32_t);
|
||||
} AsicFunctions;
|
||||
// typedef struct
|
||||
// {
|
||||
// uint8_t (*init_fn)(uint64_t, uint16_t);
|
||||
// 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);
|
||||
// void (*set_version_mask)(uint32_t);
|
||||
// } AsicFunctions;
|
||||
|
||||
typedef struct {
|
||||
char message[64];
|
||||
uint32_t count;
|
||||
} RejectedReasonStat;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -59,6 +65,8 @@ typedef struct
|
||||
int64_t start_time;
|
||||
uint64_t shares_accepted;
|
||||
uint64_t shares_rejected;
|
||||
RejectedReasonStat rejected_reason_stats[10];
|
||||
int rejected_reason_stats_count;
|
||||
int screen_page;
|
||||
uint64_t best_nonce_diff;
|
||||
char best_diff_string[DIFF_STRING_SIZE];
|
||||
@ -74,10 +82,17 @@ typedef struct
|
||||
char * fallback_pool_url;
|
||||
uint16_t pool_port;
|
||||
uint16_t fallback_pool_port;
|
||||
char * pool_user;
|
||||
char * fallback_pool_user;
|
||||
char * pool_pass;
|
||||
char * fallback_pool_pass;
|
||||
bool is_using_fallback;
|
||||
uint16_t overheat_mode;
|
||||
uint32_t lastClockSync;
|
||||
bool is_screen_active;
|
||||
bool is_firmware_update;
|
||||
char firmware_update_filename[20];
|
||||
char firmware_update_status[20];
|
||||
} SystemModule;
|
||||
|
||||
typedef struct
|
||||
@ -94,10 +109,8 @@ typedef struct
|
||||
char * device_model_str;
|
||||
int board_version;
|
||||
AsicModel asic_model;
|
||||
bool valid_model;
|
||||
char * asic_model_str;
|
||||
uint16_t asic_count;
|
||||
uint16_t voltage_domain;
|
||||
AsicFunctions ASIC_functions;
|
||||
double asic_job_frequency_ms;
|
||||
uint32_t ASIC_difficulty;
|
||||
|
||||
@ -122,7 +135,13 @@ typedef struct
|
||||
bool new_stratum_version_rolling_msg;
|
||||
|
||||
int sock;
|
||||
|
||||
// A message ID that must be unique per request that expects a response.
|
||||
// For requests not expecting a response (called notifications), this is null.
|
||||
int send_uid;
|
||||
|
||||
bool ASIC_initalized;
|
||||
bool psram_is_available;
|
||||
} GlobalState;
|
||||
|
||||
#endif /* GLOBAL_STATE_H_ */
|
||||
|
4692
main/http_server/axe-os/package-lock.json
generated
4692
main/http_server/axe-os/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,9 @@
|
||||
{
|
||||
"name": "axe-os",
|
||||
"version": "0.0.0",
|
||||
"engines": {
|
||||
"node": ">=22.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve",
|
||||
@ -11,31 +14,32 @@
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "17.3.12",
|
||||
"@angular/common": "17.3.12",
|
||||
"@angular/compiler": "17.3.12",
|
||||
"@angular/core": "17.3.12",
|
||||
"@angular/forms": "17.3.12",
|
||||
"@angular/platform-browser": "17.3.12",
|
||||
"@angular/platform-browser-dynamic": "17.3.12",
|
||||
"@angular/router": "17.3.12",
|
||||
"@angular/animations": "18.2.13",
|
||||
"@angular/common": "18.2.13",
|
||||
"@angular/compiler": "18.2.13",
|
||||
"@angular/core": "18.2.13",
|
||||
"@angular/forms": "18.2.13",
|
||||
"@angular/platform-browser": "18.2.13",
|
||||
"@angular/platform-browser-dynamic": "18.2.13",
|
||||
"@angular/router": "18.2.13",
|
||||
"@xterm/xterm": "^5.5.0",
|
||||
"chart.js": "^4.4.7",
|
||||
"chartjs-adapter-moment": "^1.0.1",
|
||||
"moment": "^2.30.1",
|
||||
"ngx-toastr": "^17.0.2",
|
||||
"ngx-toastr": "^19.0.0",
|
||||
"primeflex": "^3.3.1",
|
||||
"primeicons": "^7.0.0",
|
||||
"primeng": "^17.18.15",
|
||||
"rxjs": "~7.8.1",
|
||||
"tslib": "^2.8.1",
|
||||
"xterm": "^5.3.0",
|
||||
"zone.js": "~0.14.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^17.3.11",
|
||||
"@angular/cli": "17.3.11",
|
||||
"@angular/compiler-cli": "17.3.12",
|
||||
"@angular-devkit/build-angular": "^18.2.14",
|
||||
"@angular/cli": "18.2.14",
|
||||
"@angular/compiler-cli": "18.2.13",
|
||||
"@types/jasmine": "~5.1.5",
|
||||
"chokidar": "^3.6.0",
|
||||
"gzipper": "^8.2.0",
|
||||
"jasmine-core": "~5.5.0",
|
||||
"karma": "~6.4.4",
|
||||
@ -43,7 +47,7 @@
|
||||
"karma-coverage": "~2.2.1",
|
||||
"karma-jasmine": "~5.1.0",
|
||||
"karma-jasmine-html-reporter": "~2.1.0",
|
||||
"typescript": "~5.4.5",
|
||||
"typescript": "~5.5.4",
|
||||
"webpack-bundle-analyzer": "^4.10.2"
|
||||
}
|
||||
}
|
||||
|
@ -6,12 +6,26 @@ import { LogsComponent } from './components/logs/logs.component';
|
||||
import { SettingsComponent } from './components/settings/settings.component';
|
||||
import { NetworkComponent } from './components/network/network.component';
|
||||
import { SwarmComponent } from './components/swarm/swarm.component';
|
||||
import { DesignComponent } from './components/design/design.component';
|
||||
import { PoolComponent } from './components/pool/pool.component';
|
||||
import { AppLayoutComponent } from './layout/app.layout.component';
|
||||
import { ApModeGuard } from './guards/ap-mode.guard';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: 'ap',
|
||||
component: AppLayoutComponent,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: NetworkComponent
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
component: AppLayoutComponent,
|
||||
canActivate: [ApModeGuard],
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
@ -32,6 +46,14 @@ const routes: Routes = [
|
||||
{
|
||||
path: 'swarm',
|
||||
component: SwarmComponent
|
||||
},
|
||||
{
|
||||
path: 'design',
|
||||
component: DesignComponent
|
||||
},
|
||||
{
|
||||
path: 'pool',
|
||||
component: PoolComponent
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -11,6 +11,7 @@ import { ToastrModule } from 'ngx-toastr';
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { AppComponent } from './app.component';
|
||||
import { EditComponent } from './components/edit/edit.component';
|
||||
import { PoolComponent } from './components/pool/pool.component';
|
||||
import { NetworkEditComponent } from './components/network-edit/network.edit.component';
|
||||
import { HomeComponent } from './components/home/home.component';
|
||||
import { LoadingComponent } from './components/loading/loading.component';
|
||||
@ -18,7 +19,8 @@ import { LogsComponent } from './components/logs/logs.component';
|
||||
import { NetworkComponent } from './components/network/network.component';
|
||||
import { SettingsComponent } from './components/settings/settings.component';
|
||||
import { SwarmComponent } from './components/swarm/swarm.component';
|
||||
import { ThemeConfigComponent } from './components/settings/theme-config.component';
|
||||
import { ThemeConfigComponent } from './components/design/theme-config.component';
|
||||
import { DesignComponent } from './components/design/design.component';
|
||||
import { AppLayoutModule } from './layout/app.layout.module';
|
||||
import { ANSIPipe } from './pipes/ansi.pipe';
|
||||
import { DateAgoPipe } from './pipes/date-ago.pipe';
|
||||
@ -26,6 +28,9 @@ import { HashSuffixPipe } from './pipes/hash-suffix.pipe';
|
||||
import { PrimeNGModule } from './prime-ng.module';
|
||||
import { MessageModule } from 'primeng/message';
|
||||
import { TooltipModule } from 'primeng/tooltip';
|
||||
import { DialogModule } from 'primeng/dialog';
|
||||
import { DynamicDialogModule, DialogService as PrimeDialogService } from 'primeng/dynamicdialog';
|
||||
import { DialogService, DialogListComponent } from './services/dialog.service';
|
||||
|
||||
const components = [
|
||||
AppComponent,
|
||||
@ -35,7 +40,8 @@ const components = [
|
||||
LoadingComponent,
|
||||
NetworkComponent,
|
||||
SettingsComponent,
|
||||
LogsComponent
|
||||
LogsComponent,
|
||||
PoolComponent
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
@ -47,7 +53,10 @@ const components = [
|
||||
SwarmComponent,
|
||||
SettingsComponent,
|
||||
HashSuffixPipe,
|
||||
ThemeConfigComponent
|
||||
ThemeConfigComponent,
|
||||
DesignComponent,
|
||||
PoolComponent,
|
||||
DialogListComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
@ -63,10 +72,14 @@ const components = [
|
||||
PrimeNGModule,
|
||||
AppLayoutModule,
|
||||
MessageModule,
|
||||
TooltipModule
|
||||
TooltipModule,
|
||||
DialogModule,
|
||||
DynamicDialogModule
|
||||
],
|
||||
providers: [
|
||||
{ provide: LocationStrategy, useClass: HashLocationStrategy },
|
||||
DialogService,
|
||||
PrimeDialogService
|
||||
],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
|
@ -0,0 +1,4 @@
|
||||
<div class="card">
|
||||
<h2>Design</h2>
|
||||
<app-theme-config></app-theme-config>
|
||||
</div>
|
@ -0,0 +1,9 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-design',
|
||||
templateUrl: './design.component.html',
|
||||
})
|
||||
export class DesignComponent {
|
||||
constructor() { }
|
||||
}
|
@ -34,8 +34,8 @@ interface ThemeOption {
|
||||
|
||||
<div class="col-12">
|
||||
<h6>Theme Colors</h6>
|
||||
<div class="grid">
|
||||
<div *ngFor="let theme of themes" class="col-3">
|
||||
<div class="grid gap-2">
|
||||
<div *ngFor="let theme of themes" class="col-2">
|
||||
<button pButton [class]="'p-button-rounded p-button-text color-dot'"
|
||||
[style.backgroundColor]="theme.primaryColor"
|
||||
style="width: 2rem; height: 2rem; border: none;"
|
||||
@ -52,6 +52,38 @@ interface ThemeOption {
|
||||
export class ThemeConfigComponent implements OnInit {
|
||||
selectedScheme: string;
|
||||
themes: ThemeOption[] = [
|
||||
{
|
||||
name: 'Orange',
|
||||
primaryColor: '#F7931A',
|
||||
accentColors: {
|
||||
'--primary-color': '#F7931A',
|
||||
'--primary-color-text': '#ffffff',
|
||||
'--highlight-bg': '#F7931A',
|
||||
'--highlight-text-color': '#ffffff',
|
||||
'--focus-ring': '0 0 0 0.2rem rgba(247,147,26,0.2)',
|
||||
// PrimeNG Slider
|
||||
'--slider-bg': '#dee2e6',
|
||||
'--slider-range-bg': '#F7931A',
|
||||
'--slider-handle-bg': '#F7931A',
|
||||
// Progress Bar
|
||||
'--progressbar-bg': '#dee2e6',
|
||||
'--progressbar-value-bg': '#F7931A',
|
||||
// PrimeNG Checkbox
|
||||
'--checkbox-border': '#F7931A',
|
||||
'--checkbox-bg': '#F7931A',
|
||||
'--checkbox-hover-bg': '#e58617',
|
||||
// PrimeNG Button
|
||||
'--button-bg': '#F7931A',
|
||||
'--button-hover-bg': '#e58617',
|
||||
'--button-focus-shadow': '0 0 0 2px #ffffff, 0 0 0 4px #F7931A',
|
||||
// Toggle button
|
||||
'--togglebutton-bg': '#F7931A',
|
||||
'--togglebutton-border': '1px solid #F7931A',
|
||||
'--togglebutton-hover-bg': '#e58617',
|
||||
'--togglebutton-hover-border': '1px solid #e58617',
|
||||
'--togglebutton-text-color': '#ffffff'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Red',
|
||||
primaryColor: '#F80421',
|
@ -1,73 +1,11 @@
|
||||
<ng-container *ngIf="form != null">
|
||||
<form [formGroup]="form">
|
||||
<div class="field grid p-fluid">
|
||||
<label htmlFor="stratumURL" class="col-12 mb-2 md:col-2 md:mb-0">Stratum Host:</label>
|
||||
<div class="col-12 md:col-10">
|
||||
<input pInputText id="stratumURL" type="text" formControlName="stratumURL"
|
||||
formControlName="stratumURL" />
|
||||
<div>
|
||||
<small>Do not include 'stratum+tcp://' or port.</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field grid p-fluid">
|
||||
<label htmlFor="stratumPort" class="col-12 mb-2 md:col-2 md:mb-0">Stratum Port:</label>
|
||||
<div class="col-12 md:col-10">
|
||||
<input pInputText id="stratumPort" formControlName="stratumPort" type="number" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="field grid p-fluid">
|
||||
<label htmlFor="stratumUser" class="col-12 mb-2 md:col-2 md:mb-0">Stratum User:</label>
|
||||
<div class="col-12 md:col-10">
|
||||
<input pInputText id="stratumUser" formControlName="stratumUser" type="text" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="field grid p-fluid">
|
||||
<label htmlFor="stratumPassword" class="col-12 mb-2 md:col-2 md:mb-0">Stratum Password:</label>
|
||||
<div class="col-12 md:col-10 p-input-icon-right">
|
||||
<i *ngIf="form.get('stratumPassword')?.dirty" class="pi"
|
||||
[ngClass]="{'pi-eye': !showStratumPassword, 'pi-eye-slash': showStratumPassword}"
|
||||
(click)="toggleStratumPasswordVisibility()" style="cursor: pointer;"></i>
|
||||
<input pInputText id="stratumPassword" formControlName="stratumPassword"
|
||||
[type]="showStratumPassword ? 'text' : 'password'"
|
||||
placeholder="Enter stratum password" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="field grid p-fluid">
|
||||
<label htmlFor="stratumURL" class="col-12 mb-2 md:col-2 md:mb-0">Fallback Stratum Host:</label>
|
||||
<div class="col-12 md:col-10">
|
||||
<input pInputText id="fallbackStratumURL" type="text" formControlName="fallbackStratumURL"
|
||||
formControlName="fallbackStratumURL" />
|
||||
<div>
|
||||
<small>Do not include 'stratum+tcp://' or port.</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field grid p-fluid">
|
||||
<label htmlFor="fallbackStratumPort" class="col-12 mb-2 md:col-2 md:mb-0">Fallback Stratum Port:</label>
|
||||
<div class="col-12 md:col-10">
|
||||
<input pInputText id="fallbackStratumPort" formControlName="fallbackStratumPort" type="number" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="field grid p-fluid">
|
||||
<label htmlFor="fallbackStratumUser" class="col-12 mb-2 md:col-2 md:mb-0">Fallback Stratum User:</label>
|
||||
<div class="col-12 md:col-10">
|
||||
<input pInputText id="fallbackStratumUser" formControlName="fallbackStratumUser" type="text" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="field grid p-fluid">
|
||||
<label htmlFor="fallbackStratumPassword" class="col-12 mb-2 md:col-2 md:mb-0">Fallback Stratum Password:</label>
|
||||
<div class="col-12 md:col-10 p-input-icon-right">
|
||||
<i *ngIf="form.get('fallbackStratumPassword')?.dirty" class="pi"
|
||||
[ngClass]="{'pi-eye': !showFallbackStratumPassword, 'pi-eye-slash': showFallbackStratumPassword}"
|
||||
(click)="toggleFallbackStratumPasswordVisibility()" style="cursor: pointer;"></i>
|
||||
<input pInputText id="fallbackStratumPassword" formControlName="fallbackStratumPassword"
|
||||
[type]="showFallbackStratumPassword ? 'text' : 'password'"
|
||||
placeholder="Enter fallback stratum password" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="!devToolsOpen && [eASICModel.BM1366, eASICModel.BM1368, eASICModel.BM1370, eASICModel.BM1397].includes(ASICModel)">
|
||||
<p-message *ngIf="settingsUnlocked" severity="warn" styleClass="w-full mb-3 py-4 border-round-xl"
|
||||
text="Custom settings can cause damage & system instability. Only modify these settings if you understand the risks of running outside designed parameters.">
|
||||
</p-message>
|
||||
|
||||
<ng-container *ngIf="!settingsUnlocked && restrictedModels.includes(ASICModel)">
|
||||
<div class="field grid p-fluid">
|
||||
<label class="col-12 mb-2 md:col-2 md:mb-0" htmlFor="frequency">Frequency</label>
|
||||
<div class="col-12 md:col-10">
|
||||
@ -83,7 +21,7 @@
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="devToolsOpen === true">
|
||||
<ng-container *ngIf="settingsUnlocked === true">
|
||||
|
||||
<div class="field grid p-fluid">
|
||||
<label htmlFor="frequency" class="col-12 mb-2 md:col-2 md:mb-0">Frequency</label>
|
||||
@ -115,7 +53,7 @@
|
||||
<div class="field-checkbox">
|
||||
<p-checkbox name="flipscreen" formControlName="flipscreen" inputId="flipscreen"
|
||||
[binary]="true"></p-checkbox>
|
||||
<label for="flipscreen">Flip Screen</label>
|
||||
<label for="flipscreen">Flip Screen <i class="pi pi-info-circle" style="font-size: 0.8rem; margin-left: 0.2rem;" pTooltip="Rotates the LCD screen by 180 degrees"></i></label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -123,7 +61,7 @@
|
||||
<div class="field-checkbox">
|
||||
<p-checkbox name="invertfanpolarity" formControlName="invertfanpolarity" inputId="invertfanpolarity"
|
||||
[binary]="true"></p-checkbox>
|
||||
<label for="invertfanpolarity">Invert Fan Polarity</label>
|
||||
<label for="invertfanpolarity">Invert Fan Polarity <i class="pi pi-info-circle" style="font-size: 0.8rem; margin-left: 0.2rem;" pTooltip="Inverting the polarity of the fan PWM signal"></i></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
@ -153,6 +91,11 @@
|
||||
|
||||
<div class="mt-2">
|
||||
<button pButton [disabled]="!savedChanges" (click)="restart()">Restart</button>
|
||||
|
||||
<button *ngIf="settingsUnlocked" pButton pButton="p-button-danger" (click)="toggleOverclockMode(false)"
|
||||
class="p-button-danger" pTooltip="Return to safe preset values only">
|
||||
Disable Overclock Mode
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
|
@ -6,6 +6,7 @@ import { startWith, Subject, takeUntil } from 'rxjs';
|
||||
import { LoadingService } from 'src/app/services/loading.service';
|
||||
import { SystemService } from 'src/app/services/system.service';
|
||||
import { eASICModel } from 'src/models/enum/eASICModel';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-edit',
|
||||
@ -20,9 +21,11 @@ export class EditComponent implements OnInit, OnDestroy {
|
||||
public websiteUpdateProgress: number | null = null;
|
||||
|
||||
public savedChanges: boolean = false;
|
||||
public devToolsOpen: boolean = false;
|
||||
public settingsUnlocked: boolean = false;
|
||||
public eASICModel = eASICModel;
|
||||
public ASICModel!: eASICModel;
|
||||
public restrictedModels: eASICModel[] = Object.values(eASICModel)
|
||||
.filter((v): v is eASICModel => typeof v === 'string');
|
||||
|
||||
@Input() uri = '';
|
||||
|
||||
@ -122,10 +125,44 @@ export class EditComponent implements OnInit, OnDestroy {
|
||||
private fb: FormBuilder,
|
||||
private systemService: SystemService,
|
||||
private toastr: ToastrService,
|
||||
private loadingService: LoadingService
|
||||
private loadingService: LoadingService,
|
||||
private route: ActivatedRoute,
|
||||
) {
|
||||
window.addEventListener('resize', this.checkDevTools.bind(this));
|
||||
this.checkDevTools();
|
||||
// Check URL parameter for settings unlock
|
||||
this.route.queryParams.subscribe(params => {
|
||||
const urlOcParam = params['oc'] !== undefined;
|
||||
if (urlOcParam) {
|
||||
// If ?oc is in URL, enable overclock and save to NVS
|
||||
this.settingsUnlocked = true;
|
||||
this.saveOverclockSetting(1);
|
||||
console.log(
|
||||
'🎉 The ancient seals have been broken!\n' +
|
||||
'⚡ Unlimited power flows through your miner...\n' +
|
||||
'🔧 You can now set custom frequency and voltage values.\n' +
|
||||
'⚠️ Remember: with great power comes great responsibility!'
|
||||
);
|
||||
} else {
|
||||
// If ?oc is not in URL, check NVS setting (will be loaded in ngOnInit)
|
||||
console.log('🔒 Here be dragons! Advanced settings are locked for your protection. \n' +
|
||||
'Only the bravest miners dare to venture forth... \n' +
|
||||
'If you wish to unlock dangerous overclocking powers, add: %c?oc',
|
||||
'color: #ff4400; text-decoration: underline; cursor: pointer; font-weight: bold;',
|
||||
'to the current URL'
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private saveOverclockSetting(enabled: number) {
|
||||
this.systemService.updateSystem(this.uri, { overclockEnabled: enabled })
|
||||
.subscribe({
|
||||
next: () => {
|
||||
console.log(`Overclock setting saved: ${enabled === 1 ? 'enabled' : 'disabled'}`);
|
||||
},
|
||||
error: (err) => {
|
||||
console.error(`Failed to save overclock setting: ${err.message}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
@ -136,33 +173,19 @@ export class EditComponent implements OnInit, OnDestroy {
|
||||
)
|
||||
.subscribe(info => {
|
||||
this.ASICModel = info.ASICModel;
|
||||
|
||||
// Check if overclock is enabled in NVS
|
||||
if (info.overclockEnabled === 1) {
|
||||
this.settingsUnlocked = true;
|
||||
console.log(
|
||||
'🎉 Overclock mode is enabled from NVS settings!\n' +
|
||||
'⚡ Custom frequency and voltage values are available.'
|
||||
);
|
||||
}
|
||||
|
||||
this.form = this.fb.group({
|
||||
flipscreen: [info.flipscreen == 1],
|
||||
invertscreen: [info.invertscreen == 1],
|
||||
stratumURL: [info.stratumURL, [
|
||||
Validators.required,
|
||||
Validators.pattern(/^(?!.*stratum\+tcp:\/\/).*$/),
|
||||
Validators.pattern(/^[^:]*$/),
|
||||
]],
|
||||
stratumPort: [info.stratumPort, [
|
||||
Validators.required,
|
||||
Validators.pattern(/^[^:]*$/),
|
||||
Validators.min(0),
|
||||
Validators.max(65353)
|
||||
]],
|
||||
fallbackStratumURL: [info.fallbackStratumURL, [
|
||||
Validators.pattern(/^(?!.*stratum\+tcp:\/\/).*$/),
|
||||
]],
|
||||
fallbackStratumPort: [info.fallbackStratumPort, [
|
||||
Validators.required,
|
||||
Validators.pattern(/^[^:]*$/),
|
||||
Validators.min(0),
|
||||
Validators.max(65353)
|
||||
]],
|
||||
stratumUser: [info.stratumUser, [Validators.required]],
|
||||
stratumPassword: ['*****', [Validators.required]],
|
||||
fallbackStratumUser: [info.fallbackStratumUser, [Validators.required]],
|
||||
fallbackStratumPassword: ['password', [Validators.required]],
|
||||
coreVoltage: [info.coreVoltage, [Validators.required]],
|
||||
frequency: [info.frequency, [Validators.required]],
|
||||
autofanspeed: [info.autofanspeed == 1, [Validators.required]],
|
||||
@ -185,22 +208,10 @@ export class EditComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
window.removeEventListener('resize', this.checkDevTools.bind(this));
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
}
|
||||
|
||||
private checkDevTools(): void {
|
||||
if (
|
||||
window.outerWidth - window.innerWidth > 160 ||
|
||||
window.outerHeight - window.innerHeight > 160
|
||||
) {
|
||||
this.devToolsOpen = true;
|
||||
} else {
|
||||
this.devToolsOpen = false;
|
||||
}
|
||||
}
|
||||
|
||||
public updateSystem() {
|
||||
|
||||
const form = this.form.getRawValue();
|
||||
@ -213,21 +224,18 @@ export class EditComponent implements OnInit, OnDestroy {
|
||||
.pipe(this.loadingService.lockUIUntilComplete())
|
||||
.subscribe({
|
||||
next: () => {
|
||||
this.toastr.success('Success!', 'Saved.');
|
||||
const successMessage = this.uri ? `Saved settings for ${this.uri}` : 'Saved settings';
|
||||
this.toastr.success(successMessage, 'Success!');
|
||||
this.savedChanges = true;
|
||||
},
|
||||
error: (err: HttpErrorResponse) => {
|
||||
this.toastr.error('Error.', `Could not save. ${err.message}`);
|
||||
const errorMessage = this.uri ? `Could not save settings for ${this.uri}. ${err.message}` : `Could not save settings. ${err.message}`;
|
||||
this.toastr.error(errorMessage, 'Error');
|
||||
this.savedChanges = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
showStratumPassword: boolean = false;
|
||||
toggleStratumPasswordVisibility() {
|
||||
this.showStratumPassword = !this.showStratumPassword;
|
||||
}
|
||||
|
||||
showWifiPassword: boolean = false;
|
||||
toggleWifiPasswordVisibility() {
|
||||
this.showWifiPassword = !this.showWifiPassword;
|
||||
@ -238,9 +246,18 @@ export class EditComponent implements OnInit, OnDestroy {
|
||||
this.updateSystem();
|
||||
}
|
||||
|
||||
showFallbackStratumPassword: boolean = false;
|
||||
toggleFallbackStratumPasswordVisibility() {
|
||||
this.showFallbackStratumPassword = !this.showFallbackStratumPassword;
|
||||
toggleOverclockMode(enable: boolean) {
|
||||
this.settingsUnlocked = enable;
|
||||
this.saveOverclockSetting(enable ? 1 : 0);
|
||||
|
||||
if (enable) {
|
||||
console.log(
|
||||
'🎉 Overclock mode enabled!\n' +
|
||||
'⚡ Custom frequency and voltage values are now available.'
|
||||
);
|
||||
} else {
|
||||
console.log('🔒 Overclock mode disabled. Using safe preset values only.');
|
||||
}
|
||||
}
|
||||
|
||||
public restart() {
|
||||
@ -248,10 +265,12 @@ export class EditComponent implements OnInit, OnDestroy {
|
||||
.pipe(this.loadingService.lockUIUntilComplete())
|
||||
.subscribe({
|
||||
next: () => {
|
||||
this.toastr.success('Success!', 'Bitaxe restarted');
|
||||
const successMessage = this.uri ? `Bitaxe at ${this.uri} restarted` : 'Bitaxe restarted';
|
||||
this.toastr.success(successMessage, 'Success');
|
||||
},
|
||||
error: (err: HttpErrorResponse) => {
|
||||
this.toastr.error('Error', `Could not restart. ${err.message}`);
|
||||
const errorMessage = this.uri ? `Failed to restart device at ${this.uri}. ${err.message}` : `Failed to restart device. ${err.message}`;
|
||||
this.toastr.error(errorMessage, 'Error');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -19,15 +19,24 @@
|
||||
<div class="flex justify-content-between mb-3">
|
||||
<div>
|
||||
<span class="block text-500 font-medium mb-3">Hash Rate</span>
|
||||
<div class="text-900 font-medium text-xl">{{info.hashRate * 1000000000 | hashSuffix}}
|
||||
<div class="text-900 font-medium text-2xl flex align-items-center gap-2">
|
||||
<span>
|
||||
{{info.hashRate * 1000000000 | hashSuffix}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ng-container *ngIf="expectedHashRate$ | async as expectedHashRate">
|
||||
<span class="text-green-500 font-medium">{{expectedHashRate * 1000000000 |
|
||||
hashSuffix}}</span>
|
||||
<span class="text-500"> expected</span>
|
||||
|
||||
<ng-container>
|
||||
Average:
|
||||
<span class="text-green-500 font-medium">
|
||||
{{calculateAverage(hashrateData) | hashSuffix}}
|
||||
</span>
|
||||
</ng-container>
|
||||
|
||||
<div class="text-500 text-xs" *ngIf="expectedHashRate$ | async as expectedHashRate">
|
||||
Expected: {{expectedHashRate * 1000000000 | hashSuffix}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 md:col-6 xl:col-3">
|
||||
@ -35,20 +44,24 @@
|
||||
<div class="flex justify-content-between mb-3">
|
||||
<div>
|
||||
<span class="block text-500 font-medium mb-3">Efficiency</span>
|
||||
<div class="text-900 font-medium text-xl">
|
||||
<td>{{info.power / (info.hashRate/1000) | number: '1.2-2'}} <small>J/TH</small>
|
||||
</td>
|
||||
<div class="text-900 font-medium text-2xl flex align-items-center gap-2">
|
||||
<span>
|
||||
{{info.power / (info.hashRate/1000) | number: '1.2-2'}} <small>J/TH</small>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ng-container *ngIf="expectedHashRate$ | async as expectedHashRate">
|
||||
<span class="text-green-500 font-medium">{{info.power / (expectedHashRate/1000) | number:
|
||||
'1.2-2'}} <small>J/TH</small>
|
||||
|
||||
<ng-container>
|
||||
Average:
|
||||
<span class="text-green-500 font-medium">
|
||||
{{calculateEfficiencyAverage(hashrateData, powerData) | number: '1.2-2'}} <small>J/TH</small>
|
||||
</span>
|
||||
<span class="text-500"> expected</span>
|
||||
</ng-container>
|
||||
<!-- <span class="text-green-500 font-medium">%52+ </span>
|
||||
<span class="text-500">since last week</span> -->
|
||||
|
||||
<div class="text-500 text-xs " *ngIf="expectedHashRate$ | async as expectedHashRate" >
|
||||
Expected: {{info.power / (expectedHashRate/1000) | number: '1.2-2'}} J/TH
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 md:col-6 xl:col-3">
|
||||
@ -56,12 +69,21 @@
|
||||
<div class="flex justify-content-between mb-3">
|
||||
<div>
|
||||
<span class="block text-500 font-medium mb-3">Shares</span>
|
||||
<div class="text-900 font-medium text-xl">{{info.sharesAccepted | number: '1.0-0'}}
|
||||
<div class="text-900 font-medium text-2xl">{{info.sharesAccepted | number: '1.0-0'}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="text-red-500 font-medium">{{info.sharesRejected | number: '1.0-0'}} </span>
|
||||
<span class="text-500">rejected</span> <span class="font-medium"> ({{(info.sharesRejected / (info.sharesAccepted + info.sharesRejected) * 100) | number: '1.2-2'}}%)</span>
|
||||
<div *ngIf="info.sharesRejected === 0">
|
||||
<span class="text-red-500 font-medium">0 </span>
|
||||
<span class="text-500">rejected</span>
|
||||
</div>
|
||||
<div *ngIf="info.sharesRejected > 0">
|
||||
<div *ngFor="let sharesRejectedReason of info.sharesRejectedReasons">
|
||||
<span class="text-red-500 font-medium">{{sharesRejectedReason.count | number: '1.0-0'}} </span>
|
||||
<span class="text-500">{{sharesRejectedReason.message}}</span>
|
||||
({{(sharesRejectedReason.count / (info.sharesAccepted + info.sharesRejected) * 100) | number: '1.2-2'}}%)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -70,8 +92,8 @@
|
||||
<div class="flex justify-content-between mb-3">
|
||||
<div>
|
||||
<span class="block text-500 font-medium mb-3">Best Difficulty</span>
|
||||
<div class="text-900 font-medium text-xl">{{info.bestDiff}}
|
||||
<span class="text-500">all-time best</span>
|
||||
<div class="text-900 font-medium text-2xl">{{info.bestDiff}}
|
||||
<span class="text-500 text-lg">all-time best</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -146,7 +168,14 @@
|
||||
<div class="grid">
|
||||
<div class="col-12">
|
||||
|
||||
<h6>ASIC Temperature <span style="float: right;">{{info.temp}}°C</span></h6>
|
||||
<h6>ASIC Temperature
|
||||
<span style="float: right;">
|
||||
<ng-template #noTemp>--</ng-template>
|
||||
<ng-container *ngIf="info.temp > 0; else noTemp">
|
||||
{{info.temp}}°C
|
||||
</ng-container>
|
||||
</span>
|
||||
</h6>
|
||||
<p-progressBar [value]="(info.temp / maxTemp) * 100" [style]="{ height: '6px' }" >
|
||||
<ng-template pTemplate="content" let-value></ng-template>
|
||||
</p-progressBar>
|
||||
|
@ -23,7 +23,7 @@ export class HomeComponent {
|
||||
public dataLabel: number[] = [];
|
||||
public hashrateData: number[] = [];
|
||||
public temperatureData: number[] = [];
|
||||
public dataDataAverage: number[] = [];
|
||||
public powerData: number[] = [];
|
||||
public chartData?: any;
|
||||
|
||||
public maxPower: number = 50;
|
||||
@ -97,19 +97,6 @@ export class HomeComponent {
|
||||
yAxisID: 'y',
|
||||
fill: true,
|
||||
},
|
||||
{
|
||||
type: 'line',
|
||||
label: 'Average Hashrate',
|
||||
data: [],
|
||||
fill: false,
|
||||
backgroundColor: primaryColor + '30',
|
||||
borderColor: primaryColor + '60',
|
||||
tension: 0,
|
||||
pointRadius: 0,
|
||||
borderWidth: 2,
|
||||
borderDash: [5, 5],
|
||||
yAxisID: 'y',
|
||||
},
|
||||
{
|
||||
type: 'line',
|
||||
label: 'ASIC Temp',
|
||||
@ -203,21 +190,20 @@ export class HomeComponent {
|
||||
tap(info => {
|
||||
this.hashrateData.push(info.hashRate * 1000000000);
|
||||
this.temperatureData.push(info.temp);
|
||||
this.powerData.push(info.power);
|
||||
|
||||
this.dataLabel.push(new Date().getTime());
|
||||
|
||||
if (this.hashrateData.length >= 720) {
|
||||
this.hashrateData.shift();
|
||||
this.temperatureData.shift();
|
||||
this.powerData.shift();
|
||||
this.dataLabel.shift();
|
||||
}
|
||||
|
||||
this.chartData.labels = this.dataLabel;
|
||||
this.chartData.datasets[0].data = this.hashrateData;
|
||||
this.chartData.datasets[2].data = this.temperatureData;
|
||||
|
||||
// Calculate average hashrate and fill the array with the same value for the average line
|
||||
const averageHashrate = this.calculateAverage(this.hashrateData);
|
||||
this.chartData.datasets[1].data = Array(this.hashrateData.length).fill(averageHashrate);
|
||||
this.chartData.datasets[1].data = this.temperatureData;
|
||||
|
||||
this.chartData = {
|
||||
...this.chartData
|
||||
@ -255,7 +241,7 @@ export class HomeComponent {
|
||||
|
||||
}
|
||||
|
||||
private calculateAverage(data: number[]): number {
|
||||
public calculateAverage(data: number[]): number {
|
||||
if (data.length === 0) return 0;
|
||||
const sum = data.reduce((sum, value) => sum + value, 0);
|
||||
return sum / data.length;
|
||||
@ -283,4 +269,16 @@ export class HomeComponent {
|
||||
}
|
||||
return stratumURL.startsWith('http') ? stratumURL : `http://${stratumURL}`;
|
||||
}
|
||||
|
||||
public calculateEfficiencyAverage(hashrateData: number[], powerData: number[]): number {
|
||||
if (hashrateData.length === 0 || powerData.length === 0) return 0;
|
||||
|
||||
// Calculate efficiency for each data point and average them
|
||||
const efficiencies = hashrateData.map((hashrate, index) => {
|
||||
const power = powerData[index] || 0;
|
||||
return power / (hashrate/1000000000000); // Convert to J/TH
|
||||
});
|
||||
|
||||
return this.calculateAverage(efficiencies);
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
<td>{{info.uptimeSeconds | dateAgo}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>WiFi Status:</td>
|
||||
<td>Wi-Fi Status:</td>
|
||||
<td>{{info.wifiStatus}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -8,20 +8,21 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="field grid p-fluid">
|
||||
<label htmlFor="ssid" class="col-12 mb-2 md:col-2 md:mb-0">WiFi SSID:</label>
|
||||
<div class="col-12 md:col-10">
|
||||
<label htmlFor="ssid" class="col-12 mb-2 md:col-2 md:mb-0">Wi-Fi SSID:</label>
|
||||
<div class="col-12 md:col-10 p-inputgroup">
|
||||
<input pInputText id="ssid" type="text" formControlName="ssid" />
|
||||
<button pButton type="button" icon="pi pi-search" (click)="scanWifi()" [loading]="scanning"></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field grid p-fluid">
|
||||
<label htmlFor="wifiPass" class="col-12 mb-2 md:col-2 md:mb-0">WiFi Password:</label>
|
||||
<label htmlFor="wifiPass" class="col-12 mb-2 md:col-2 md:mb-0">Wi-Fi Password:</label>
|
||||
<div class="col-12 md:col-10 p-input-icon-right">
|
||||
<i *ngIf="form.get('wifiPass')?.dirty" class="pi"
|
||||
[ngClass]="{'pi-eye': !showWifiPassword, 'pi-eye-slash': showWifiPassword}"
|
||||
(click)="toggleWifiPasswordVisibility()" style="cursor: pointer;"></i>
|
||||
<input pInputText id="wifiPass" formControlName="wifiPass"
|
||||
[type]="showWifiPassword ? 'text' : 'password'"
|
||||
placeholder="Enter WiFi password" />
|
||||
placeholder="Enter Wi-Fi password" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -1,11 +1,18 @@
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
import { startWith } from 'rxjs';
|
||||
import { finalize } from 'rxjs/operators';
|
||||
import { DialogService } from 'src/app/services/dialog.service';
|
||||
import { LoadingService } from 'src/app/services/loading.service';
|
||||
import { SystemService } from 'src/app/services/system.service';
|
||||
|
||||
interface WifiNetwork {
|
||||
ssid: string;
|
||||
rssi: number;
|
||||
authmode: number;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-network-edit',
|
||||
templateUrl: './network.edit.component.html',
|
||||
@ -15,6 +22,7 @@ export class NetworkEditComponent implements OnInit {
|
||||
|
||||
public form!: FormGroup;
|
||||
public savedChanges: boolean = false;
|
||||
public scanning: boolean = false;
|
||||
|
||||
@Input() uri = '';
|
||||
|
||||
@ -23,7 +31,9 @@ export class NetworkEditComponent implements OnInit {
|
||||
private systemService: SystemService,
|
||||
private toastr: ToastrService,
|
||||
private toastrService: ToastrService,
|
||||
private loadingService: LoadingService
|
||||
private loadingService: LoadingService,
|
||||
private http: HttpClient,
|
||||
private dialogService: DialogService
|
||||
) {
|
||||
|
||||
}
|
||||
@ -52,6 +62,11 @@ export class NetworkEditComponent implements OnInit {
|
||||
delete form.wifiPass;
|
||||
}
|
||||
|
||||
// Trim SSID to remove any leading/trailing whitespace
|
||||
if (form.ssid) {
|
||||
form.ssid = form.ssid.trim();
|
||||
}
|
||||
|
||||
this.systemService.updateSystem(this.uri, form)
|
||||
.pipe(this.loadingService.lockUIUntilComplete())
|
||||
.subscribe({
|
||||
@ -71,6 +86,52 @@ export class NetworkEditComponent implements OnInit {
|
||||
this.showWifiPassword = !this.showWifiPassword;
|
||||
}
|
||||
|
||||
public scanWifi() {
|
||||
this.scanning = true;
|
||||
this.http.get<{networks: WifiNetwork[]}>('/api/system/wifi/scan')
|
||||
.pipe(
|
||||
finalize(() => this.scanning = false)
|
||||
)
|
||||
.subscribe({
|
||||
next: (response) => {
|
||||
// Sort networks by signal strength (highest first)
|
||||
const networks = response.networks.sort((a, b) => b.rssi - a.rssi);
|
||||
|
||||
// filter out poor wifi connections
|
||||
const poorNetworks = networks.filter(network => network.rssi >= -80);
|
||||
|
||||
// Remove duplicate Network Names and show highest signal strength only
|
||||
const uniqueNetworks = poorNetworks.reduce((acc, network) => {
|
||||
if (!acc[network.ssid] || acc[network.ssid].rssi < network.rssi) {
|
||||
acc[network.ssid] = network;
|
||||
}
|
||||
return acc;
|
||||
}, {} as { [key: string]: WifiNetwork });
|
||||
|
||||
// Convert the object back to an array
|
||||
const filteredNetworks = Object.values(uniqueNetworks);
|
||||
|
||||
// Create dialog data
|
||||
const dialogData = filteredNetworks.map(n => ({
|
||||
label: `${n.ssid} (${n.rssi}dBm)`,
|
||||
value: n.ssid
|
||||
}));
|
||||
|
||||
// Show dialog with network list
|
||||
this.dialogService.open('Select WiFi Network', dialogData)
|
||||
.subscribe((selectedSsid: string) => {
|
||||
if (selectedSsid) {
|
||||
this.form.patchValue({ ssid: selectedSsid });
|
||||
this.form.markAsDirty();
|
||||
}
|
||||
});
|
||||
},
|
||||
error: (err) => {
|
||||
this.toastr.error('Failed to scan WiFi networks', 'Error');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public restart() {
|
||||
this.systemService.restart()
|
||||
.pipe(this.loadingService.lockUIUntilComplete())
|
||||
|
@ -0,0 +1,83 @@
|
||||
<div class="grid">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<h5>Pool Configuration</h5>
|
||||
<form [formGroup]="form" *ngIf="form != null">
|
||||
<div class="field grid p-fluid">
|
||||
<label htmlFor="stratumURL" class="col-12 mb-2 md:col-2 md:mb-0">Stratum Host:</label>
|
||||
<div class="col-12 md:col-10">
|
||||
<input pInputText id="stratumURL" type="text" formControlName="stratumURL" />
|
||||
<div>
|
||||
<small>Do not include 'stratum+tcp://' or port.</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field grid p-fluid">
|
||||
<label htmlFor="stratumPort" class="col-12 mb-2 md:col-2 md:mb-0">Stratum Port:</label>
|
||||
<div class="col-12 md:col-10">
|
||||
<input pInputText id="stratumPort" formControlName="stratumPort" type="number" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="field grid p-fluid">
|
||||
<label htmlFor="stratumUser" class="col-12 mb-2 md:col-2 md:mb-0">Stratum User:</label>
|
||||
<div class="col-12 md:col-10">
|
||||
<input pInputText id="stratumUser" formControlName="stratumUser" type="text" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="field grid p-fluid">
|
||||
<label htmlFor="stratumPassword" class="col-12 mb-2 md:col-2 md:mb-0">Stratum Password:</label>
|
||||
<div class="col-12 md:col-10 p-input-icon-right">
|
||||
<i *ngIf="form.get('stratumPassword')?.dirty" class="pi"
|
||||
[ngClass]="{'pi-eye': !showStratumPassword, 'pi-eye-slash': showStratumPassword}"
|
||||
(click)="toggleStratumPasswordVisibility()" style="cursor: pointer;"></i>
|
||||
<input pInputText id="stratumPassword" formControlName="stratumPassword"
|
||||
[type]="showStratumPassword ? 'text' : 'password'"
|
||||
placeholder="Enter stratum password" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="field grid p-fluid">
|
||||
<label htmlFor="fallbackStratumURL" class="col-12 mb-2 md:col-2 md:mb-0">Fallback Stratum Host:</label>
|
||||
<div class="col-12 md:col-10">
|
||||
<input pInputText id="fallbackStratumURL" type="text" formControlName="fallbackStratumURL" />
|
||||
<div>
|
||||
<small>Do not include 'stratum+tcp://' or port.</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field grid p-fluid">
|
||||
<label htmlFor="fallbackStratumPort" class="col-12 mb-2 md:col-2 md:mb-0">Fallback Stratum Port:</label>
|
||||
<div class="col-12 md:col-10">
|
||||
<input pInputText id="fallbackStratumPort" formControlName="fallbackStratumPort" type="number" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="field grid p-fluid">
|
||||
<label htmlFor="fallbackStratumUser" class="col-12 mb-2 md:col-2 md:mb-0">Fallback Stratum User:</label>
|
||||
<div class="col-12 md:col-10">
|
||||
<input pInputText id="fallbackStratumUser" formControlName="fallbackStratumUser" type="text" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="field grid p-fluid">
|
||||
<label htmlFor="fallbackStratumPassword" class="col-12 mb-2 md:col-2 md:mb-0">Fallback Stratum Password:</label>
|
||||
<div class="col-12 md:col-10 p-input-icon-right">
|
||||
<i *ngIf="form.get('fallbackStratumPassword')?.dirty" class="pi"
|
||||
[ngClass]="{'pi-eye': !showFallbackStratumPassword, 'pi-eye-slash': showFallbackStratumPassword}"
|
||||
(click)="toggleFallbackStratumPasswordVisibility()" style="cursor: pointer;"></i>
|
||||
<input pInputText id="fallbackStratumPassword" formControlName="fallbackStratumPassword"
|
||||
[type]="showFallbackStratumPassword ? 'text' : 'password'"
|
||||
placeholder="Enter fallback stratum password" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-2">
|
||||
<button pButton [disabled]="!form.dirty || form.invalid" (click)="updateSystem()"
|
||||
class="btn btn-primary mr-2">Save</button>
|
||||
<b style="line-height: 34px;">You must restart this device after saving for changes to take effect.</b>
|
||||
</div>
|
||||
|
||||
<div class="mt-2">
|
||||
<button pButton [disabled]="!savedChanges" (click)="restart()">Restart</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,5 @@
|
||||
.pi {
|
||||
right: 1rem;
|
||||
font-size: 1.5rem;
|
||||
top: 1rem;
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
import { LoadingService } from 'src/app/services/loading.service';
|
||||
import { SystemService } from 'src/app/services/system.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-pool',
|
||||
templateUrl: './pool.component.html',
|
||||
styleUrls: ['./pool.component.scss']
|
||||
})
|
||||
export class PoolComponent implements OnInit {
|
||||
public form!: FormGroup;
|
||||
public savedChanges: boolean = false;
|
||||
|
||||
@Input() uri = '';
|
||||
|
||||
constructor(
|
||||
private fb: FormBuilder,
|
||||
private systemService: SystemService,
|
||||
private toastr: ToastrService,
|
||||
private loadingService: LoadingService
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.systemService.getInfo(this.uri)
|
||||
.pipe(
|
||||
this.loadingService.lockUIUntilComplete()
|
||||
)
|
||||
.subscribe(info => {
|
||||
this.form = this.fb.group({
|
||||
stratumURL: [info.stratumURL, [
|
||||
Validators.required,
|
||||
Validators.pattern(/^(?!.*stratum\+tcp:\/\/).*$/),
|
||||
Validators.pattern(/^[^:]*$/),
|
||||
]],
|
||||
stratumPort: [info.stratumPort, [
|
||||
Validators.required,
|
||||
Validators.pattern(/^[^:]*$/),
|
||||
Validators.min(0),
|
||||
Validators.max(65353)
|
||||
]],
|
||||
fallbackStratumURL: [info.fallbackStratumURL, [
|
||||
Validators.pattern(/^(?!.*stratum\+tcp:\/\/).*$/),
|
||||
]],
|
||||
fallbackStratumPort: [info.fallbackStratumPort, [
|
||||
Validators.required,
|
||||
Validators.pattern(/^[^:]*$/),
|
||||
Validators.min(0),
|
||||
Validators.max(65353)
|
||||
]],
|
||||
stratumUser: [info.stratumUser, [Validators.required]],
|
||||
stratumPassword: ['*****', [Validators.required]],
|
||||
fallbackStratumUser: [info.fallbackStratumUser, [Validators.required]],
|
||||
fallbackStratumPassword: ['password', [Validators.required]]
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public updateSystem() {
|
||||
const form = this.form.getRawValue();
|
||||
|
||||
if (form.stratumPassword === '*****') {
|
||||
delete form.stratumPassword;
|
||||
}
|
||||
|
||||
this.systemService.updateSystem(this.uri, form)
|
||||
.pipe(this.loadingService.lockUIUntilComplete())
|
||||
.subscribe({
|
||||
next: () => {
|
||||
const successMessage = this.uri ? `Saved pool settings for ${this.uri}` : 'Saved pool settings';
|
||||
this.toastr.success(successMessage, 'Success!');
|
||||
this.savedChanges = true;
|
||||
},
|
||||
error: (err: HttpErrorResponse) => {
|
||||
const errorMessage = this.uri ? `Could not save pool settings for ${this.uri}. ${err.message}` : `Could not save pool settings. ${err.message}`;
|
||||
this.toastr.error(errorMessage, 'Error');
|
||||
this.savedChanges = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
showStratumPassword: boolean = false;
|
||||
toggleStratumPasswordVisibility() {
|
||||
this.showStratumPassword = !this.showStratumPassword;
|
||||
}
|
||||
|
||||
showFallbackStratumPassword: boolean = false;
|
||||
toggleFallbackStratumPasswordVisibility() {
|
||||
this.showFallbackStratumPassword = !this.showFallbackStratumPassword;
|
||||
}
|
||||
|
||||
public restart() {
|
||||
this.systemService.restart(this.uri)
|
||||
.pipe(this.loadingService.lockUIUntilComplete())
|
||||
.subscribe({
|
||||
next: () => {
|
||||
const successMessage = this.uri ? `Bitaxe at ${this.uri} restarted` : 'Bitaxe restarted';
|
||||
this.toastr.success(successMessage, 'Success');
|
||||
},
|
||||
error: (err: HttpErrorResponse) => {
|
||||
const errorMessage = this.uri ? `Failed to restart device at ${this.uri}. ${err.message}` : `Failed to restart device. ${err.message}`;
|
||||
this.toastr.error(errorMessage, 'Error');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -3,12 +3,6 @@
|
||||
<app-edit></app-edit>
|
||||
</div>
|
||||
|
||||
<div class="grid">
|
||||
<div class="col-12">
|
||||
<app-theme-config></app-theme-config>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid">
|
||||
<div class="col-12 lg:col-6 xl:col-4">
|
||||
<div class="card" *ngIf="checkLatestRelease == false">
|
||||
@ -34,6 +28,16 @@
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 lg:col-12 xl:col-4">
|
||||
<div class="card">
|
||||
<h2>Update Website <span *ngIf="websiteUpdateProgress != null">{{websiteUpdateProgress}}%</span></h2>
|
||||
|
||||
<p-fileUpload #websiteUpload [customUpload]="true" mode="basic" accept=".bin" (uploadHandler)="otaWWWUpdate($event)"
|
||||
[auto]="true" chooseLabel="Browse"></p-fileUpload>
|
||||
|
||||
<small>(www.bin)</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 lg:col-6 xl:col-4">
|
||||
<div class="card">
|
||||
<h2>Update Firmware <span *ngIf="firmwareUpdateProgress != null">{{firmwareUpdateProgress}}%</span></h2>
|
||||
@ -45,14 +49,4 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="col-12 lg:col-12 xl:col-4">
|
||||
<div class="card">
|
||||
<h2>Update Website <span *ngIf="websiteUpdateProgress != null">{{websiteUpdateProgress}}%</span></h2>
|
||||
|
||||
<p-fileUpload #websiteUpload [customUpload]="true" mode="basic" accept=".bin" (uploadHandler)="otaWWWUpdate($event)"
|
||||
[auto]="true" chooseLabel="Browse"></p-fileUpload>
|
||||
|
||||
<small>(www.bin)</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -22,7 +22,6 @@ export class SettingsComponent {
|
||||
public websiteUpdateProgress: number | null = null;
|
||||
|
||||
|
||||
public devToolsOpen: boolean = false;
|
||||
public eASICModel = eASICModel;
|
||||
public ASICModel!: eASICModel;
|
||||
|
||||
@ -45,9 +44,6 @@ export class SettingsComponent {
|
||||
|
||||
|
||||
|
||||
window.addEventListener('resize', this.checkDevTools);
|
||||
this.checkDevTools();
|
||||
|
||||
this.latestRelease$ = this.githubUpdateService.getReleases().pipe(map(releases => {
|
||||
return releases[0];
|
||||
}));
|
||||
@ -93,17 +89,6 @@ export class SettingsComponent {
|
||||
});
|
||||
|
||||
}
|
||||
private checkDevTools = () => {
|
||||
if (
|
||||
window.outerWidth - window.innerWidth > 160 ||
|
||||
window.outerHeight - window.innerHeight > 160
|
||||
) {
|
||||
this.devToolsOpen = true;
|
||||
} else {
|
||||
this.devToolsOpen = false;
|
||||
}
|
||||
};
|
||||
|
||||
public updateSystem() {
|
||||
|
||||
const form = this.form.getRawValue();
|
||||
@ -136,7 +121,7 @@ export class SettingsComponent {
|
||||
otaUpdate(event: FileUploadHandlerEvent) {
|
||||
const file = event.files[0];
|
||||
this.firmwareUpload.clear(); // clear the file upload component
|
||||
|
||||
|
||||
if (file.name != 'esp-miner.bin') {
|
||||
this.toastrService.error('Incorrect file, looking for esp-miner.bin.', 'Error');
|
||||
return;
|
||||
|
@ -24,8 +24,8 @@
|
||||
<div class="flex align-items-center gap-2">
|
||||
<label for="refresh-interval" class="text-sm md:text-base">Refresh Interval:</label>
|
||||
<p-slider id="refresh-interval" class="pl-2 pr-2"
|
||||
[min]="5"
|
||||
[max]="30"
|
||||
[min]="5"
|
||||
[max]="30"
|
||||
[style]="{'width': '150px'}"
|
||||
[formControl]="refreshIntervalControl">
|
||||
</p-slider>
|
||||
@ -48,7 +48,26 @@
|
||||
<div class="table-container">
|
||||
<table cellspacing="0" cellpadding="0" class="text-sm md:text-base">
|
||||
<tr>
|
||||
<th>IP</th>
|
||||
<th>
|
||||
<div class="flex items-center cursor-pointer select-none h-full" (click)="sortBy('IP')">
|
||||
<span class="flex-1">IP</span>
|
||||
<i class="pi text-xs flex items-center" [ngClass]="{
|
||||
'pi-sort-alt': sortField !== 'IP',
|
||||
'pi-sort-amount-up-alt': sortField === 'IP' && sortDirection === 'asc',
|
||||
'pi-sort-amount-down': sortField === 'IP' && sortDirection === 'desc'
|
||||
}"></i>
|
||||
</div>
|
||||
</th>
|
||||
<th>
|
||||
<div class="flex items-center cursor-pointer select-none h-full" (click)="sortBy('hostname')">
|
||||
<span class="flex-1">Hostname</span>
|
||||
<i class="pi text-xs flex items-center" [ngClass]="{
|
||||
'pi-sort-alt': sortField !== 'hostname',
|
||||
'pi-sort-amount-up-alt': sortField === 'hostname' && sortDirection === 'asc',
|
||||
'pi-sort-amount-down': sortField === 'hostname' && sortDirection === 'desc'
|
||||
}"></i>
|
||||
</div>
|
||||
</th>
|
||||
<th>Hash Rate</th>
|
||||
<th>Uptime</th>
|
||||
<th>Shares</th>
|
||||
@ -63,18 +82,30 @@
|
||||
<ng-container *ngFor="let axe of swarm">
|
||||
<tr>
|
||||
<td>
|
||||
<a class="text-primary" [href]="'http://'+axe.IP" target="_blank">{{axe.IP}}</a>
|
||||
<div class="text-sm">{{axe.hostname}}</div>
|
||||
<a
|
||||
[ngClass]="[
|
||||
axe.asicCount > 1 ? 'text-orange-500' :
|
||||
axe.ASICModel === 'BM1397' ? 'text-red-500' :
|
||||
axe.ASICModel === 'BM1366' ? 'text-purple-500' :
|
||||
axe.ASICModel === 'BM1368' ? 'text-blue-500' :
|
||||
axe.ASICModel === 'BM1370' ? 'text-green-500' :
|
||||
''
|
||||
]"
|
||||
[href]="'http://'+axe.IP"
|
||||
target="_blank"
|
||||
[pTooltip]="axe.ASICModel"
|
||||
tooltipPosition="top">{{axe.IP}}</a>
|
||||
</td>
|
||||
<td>{{axe.hostname}}</td>
|
||||
<td>{{axe.hashRate * 1000000000 | hashSuffix}}</td>
|
||||
<td>{{axe.uptimeSeconds | dateAgo: {intervals: 2} }}</td>
|
||||
<td>
|
||||
<div class="w-min cursor-pointer"
|
||||
<div class="w-min cursor-pointer"
|
||||
pTooltip="Shares Accepted"
|
||||
tooltipPosition="top">
|
||||
{{axe.sharesAccepted | number: '1.0-0'}}
|
||||
</div>
|
||||
<div class="text-sm w-min cursor-pointer"
|
||||
<div class="text-sm w-min cursor-pointer"
|
||||
pTooltip="Shares Rejected"
|
||||
tooltipPosition="top">
|
||||
{{axe.sharesRejected | number: '1.0-0'}}
|
||||
@ -85,8 +116,8 @@
|
||||
<div [ngClass]="{'text-orange-500': axe.temp > 68}">
|
||||
{{axe.temp | number: '1.0-1'}}°<small>C</small>
|
||||
</div>
|
||||
<div class="text-sm w-min cursor-pointer"
|
||||
[ngClass]="{'text-orange-500': axe.vrTemp > 90}"
|
||||
<div class="text-sm w-min cursor-pointer"
|
||||
[ngClass]="{'text-orange-500': axe.vrTemp > 90}"
|
||||
*ngIf="axe.vrTemp"
|
||||
pTooltip="Voltage Regulator Temperature"
|
||||
tooltipPosition="top">
|
||||
@ -95,19 +126,43 @@
|
||||
</td>
|
||||
<td>
|
||||
<div>{{axe.bestDiff}}</div>
|
||||
<div class="text-sm w-min cursor-pointer"
|
||||
<div class="text-sm w-min cursor-pointer"
|
||||
pTooltip="Best Session Diff"
|
||||
tooltipPosition="top">
|
||||
{{axe.bestSessionDiff}}
|
||||
</div>
|
||||
</td>
|
||||
<td>{{axe.version}}</td>
|
||||
<td><p-button icon="pi pi-pencil" pp-button (click)="edit(axe)"></p-button></td>
|
||||
<td><p-button icon="pi pi-pencil" pp-button (click)="edit(axe)"></p-button></td>
|
||||
<td><p-button icon="pi pi-sync" pp-button severity="danger" (click)="restart(axe)"></p-button></td>
|
||||
<td><p-button icon="pi pi-trash" pp-button severity="secondary" (click)="remove(axe)"></p-button></td>
|
||||
</tr>
|
||||
</ng-container>
|
||||
</table>
|
||||
|
||||
<div class="flex flex-wrap gap-2 mt-3 text-sm justify-content-center">
|
||||
<div class="flex align-items-center gap-1" [style.opacity]="hasModel('BM1397')">
|
||||
<span class="text-red-500">●</span>
|
||||
<span>BM1397 (Max)</span>
|
||||
</div>
|
||||
<div class="flex align-items-center gap-1" [style.opacity]="hasModel('BM1366')">
|
||||
<span class="text-purple-500">●</span>
|
||||
<span>BM1366 (Ultra)</span>
|
||||
</div>
|
||||
<div class="flex align-items-center gap-1" [style.opacity]="hasModel('BM1368')">
|
||||
<span class="text-blue-500">●</span>
|
||||
<span>BM1368 (Supra)</span>
|
||||
</div>
|
||||
<div class="flex align-items-center gap-1" [style.opacity]="hasModel('BM1370')">
|
||||
<span class="text-green-500">●</span>
|
||||
<span>BM1370 (Gamma)</span>
|
||||
</div>
|
||||
<div class="flex align-items-center gap-1" [style.opacity]="hasMultipleChips()">
|
||||
<span class="text-orange-500">●</span>
|
||||
<span>Multiple Chip Device</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="modal-backdrop" *ngIf="showEdit" (click)="showEdit = false"></div>
|
||||
@ -115,4 +170,4 @@
|
||||
<div class="close" (click)="showEdit = false">✖</div>
|
||||
<h1>{{selectedAxeOs.IP}}</h1>
|
||||
<app-edit [uri]="'http://' + selectedAxeOs.IP"></app-edit>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -6,15 +6,40 @@ table {
|
||||
th {
|
||||
text-align: left;
|
||||
background-color: #1f2d40;
|
||||
padding: 0;
|
||||
|
||||
> div {
|
||||
height: 100%;
|
||||
padding: 0.5rem 1rem;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.pi {
|
||||
opacity: 0.7;
|
||||
height: 1em;
|
||||
line-height: 1;
|
||||
|
||||
&.pi-sort-amount-up-alt,
|
||||
&.pi-sort-amount-down {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
th,
|
||||
td {
|
||||
padding: 1rem 1rem;
|
||||
border-bottom: 1px solid #304562;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
th > div {
|
||||
min-width: 100px;
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
|
||||
a {
|
||||
color: white;
|
||||
}
|
||||
|
@ -33,6 +33,9 @@ export class SwarmComponent implements OnInit, OnDestroy {
|
||||
|
||||
public refreshIntervalControl: FormControl;
|
||||
|
||||
public sortField: string = '';
|
||||
public sortDirection: 'asc' | 'desc' = 'asc';
|
||||
|
||||
constructor(
|
||||
private fb: FormBuilder,
|
||||
private systemService: SystemService,
|
||||
@ -169,12 +172,12 @@ export class SwarmComponent implements OnInit, OnDestroy {
|
||||
public restart(axe: any) {
|
||||
this.systemService.restart(`http://${axe.IP}`).pipe(
|
||||
catchError(error => {
|
||||
this.toastr.error('Failed to restart device', 'Error');
|
||||
this.toastr.error(`Failed to restart device at ${axe.IP}`, 'Error');
|
||||
return of(null);
|
||||
})
|
||||
).subscribe(res => {
|
||||
if (res !== null) {
|
||||
this.toastr.success('Bitaxe restarted', 'Success');
|
||||
this.toastr.success(`Bitaxe at ${axe.IP} restarted`, 'Success');
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -242,6 +245,35 @@ export class SwarmComponent implements OnInit, OnDestroy {
|
||||
return this.ipToInt(a.IP) - this.ipToInt(b.IP);
|
||||
}
|
||||
|
||||
sortBy(field: string) {
|
||||
// If clicking the same field, toggle direction
|
||||
if (this.sortField === field) {
|
||||
this.sortDirection = this.sortDirection === 'asc' ? 'desc' : 'asc';
|
||||
} else {
|
||||
// New field, set to ascending by default
|
||||
this.sortField = field;
|
||||
this.sortDirection = 'asc';
|
||||
}
|
||||
|
||||
this.swarm.sort((a, b) => {
|
||||
let comparison = 0;
|
||||
if (field === 'IP') {
|
||||
// Split IP into octets and compare numerically
|
||||
const aOctets = a[field].split('.').map(Number);
|
||||
const bOctets = b[field].split('.').map(Number);
|
||||
for (let i = 0; i < 4; i++) {
|
||||
if (aOctets[i] !== bOctets[i]) {
|
||||
comparison = aOctets[i] - bOctets[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
comparison = a[field].localeCompare(b[field], undefined, { numeric: true });
|
||||
}
|
||||
return this.sortDirection === 'asc' ? comparison : -comparison;
|
||||
});
|
||||
}
|
||||
|
||||
private convertBestDiffToNumber(bestDiff: string): number {
|
||||
if (!bestDiff) return 0;
|
||||
const value = parseFloat(bestDiff);
|
||||
@ -270,4 +302,12 @@ export class SwarmComponent implements OnInit, OnDestroy {
|
||||
this.totals.bestDiff = this.formatBestDiff(maxDiff);
|
||||
}
|
||||
|
||||
hasModel(model: string): string {
|
||||
return this.swarm.some(axe => axe.ASICModel === model) ? '1' : '0.5';
|
||||
}
|
||||
|
||||
hasMultipleChips(): string {
|
||||
return this.swarm.some(axe => axe.asicCount > 1) ? '1' : '0.5';
|
||||
}
|
||||
|
||||
}
|
||||
|
20
main/http_server/axe-os/src/app/guards/ap-mode.guard.ts
Normal file
20
main/http_server/axe-os/src/app/guards/ap-mode.guard.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { CanActivateFn, Router } from '@angular/router';
|
||||
import { inject } from '@angular/core';
|
||||
import { Observable, map, catchError, of } from 'rxjs';
|
||||
import { SystemService } from '../services/system.service';
|
||||
|
||||
export const ApModeGuard: CanActivateFn = (): Observable<boolean> => {
|
||||
const systemService = inject(SystemService);
|
||||
const router = inject(Router);
|
||||
|
||||
return systemService.getInfo().pipe(
|
||||
map(info => {
|
||||
if (info.apEnabled) {
|
||||
router.navigate(['/ap']);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}),
|
||||
catchError(() => of(true))
|
||||
);
|
||||
};
|
@ -1,6 +1,6 @@
|
||||
<div class="layout-wrapper" [ngClass]="containerClass">
|
||||
<app-topbar></app-topbar>
|
||||
<div class="layout-sidebar">
|
||||
<app-topbar [isAPMode]="isAPMode"></app-topbar>
|
||||
<div class="layout-sidebar" *ngIf="!isAPMode">
|
||||
<app-sidebar></app-sidebar>
|
||||
</div>
|
||||
<div class="layout-main-container">
|
||||
|
@ -109,6 +109,10 @@ export class AppLayoutComponent implements OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
get isAPMode(): boolean {
|
||||
return this.router.url.startsWith('/ap');
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.overlayMenuOpenSubscription) {
|
||||
this.overlayMenuOpenSubscription.unsubscribe();
|
||||
|
@ -25,6 +25,8 @@ export class AppMenuComponent implements OnInit {
|
||||
{ label: 'Dashboard', icon: 'pi pi-fw pi-home', routerLink: ['/'] },
|
||||
{ label: 'Swarm', icon: 'pi pi-fw pi-share-alt', routerLink: ['swarm'] },
|
||||
{ label: 'Network', icon: 'pi pi-fw pi-wifi', routerLink: ['network'] },
|
||||
{ label: 'Pool Settings', icon: 'pi pi-fw pi-server', routerLink: ['pool'] },
|
||||
{ label: 'Customization', icon: 'pi pi-fw pi-palette', routerLink: ['design'] },
|
||||
{ label: 'Settings', icon: 'pi pi-fw pi-cog', routerLink: ['settings'] },
|
||||
{ label: 'Logs', icon: 'pi pi-fw pi-list', routerLink: ['logs'] },
|
||||
]
|
||||
|
@ -3,7 +3,7 @@
|
||||
<div [routerLink]="['/']" class="header-text"><span style="font-family: Angel Wish; font-size: 4rem;">Axe</span><span class="os" style=" font-size: 3rem;">OS</span></div>
|
||||
</a>
|
||||
|
||||
<button #menubutton class="p-link layout-menu-button layout-topbar-button" (click)="layoutService.onMenuToggle()">
|
||||
<button *ngIf="!isAPMode" #menubutton class="p-link layout-menu-button layout-topbar-button" (click)="layoutService.onMenuToggle()">
|
||||
<i class="pi pi-bars"></i>
|
||||
</button>
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Component, ElementRef, ViewChild } from '@angular/core';
|
||||
import { Component, ElementRef, Input, ViewChild } from '@angular/core';
|
||||
import { MenuItem } from 'primeng/api';
|
||||
|
||||
import { LayoutService } from './service/app.layout.service';
|
||||
@ -11,6 +11,8 @@ export class AppTopBarComponent {
|
||||
|
||||
items!: MenuItem[];
|
||||
|
||||
@Input() isAPMode: boolean = false;
|
||||
|
||||
@ViewChild('menubutton') menuButton!: ElementRef;
|
||||
|
||||
@ViewChild('topbarmenubutton') topbarMenuButton!: ElementRef;
|
||||
|
58
main/http_server/axe-os/src/app/services/dialog.service.ts
Normal file
58
main/http_server/axe-os/src/app/services/dialog.service.ts
Normal file
@ -0,0 +1,58 @@
|
||||
import { Component, Injectable } from '@angular/core';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
import { DialogService as PrimeDialogService, DynamicDialogConfig } from 'primeng/dynamicdialog';
|
||||
|
||||
interface DialogOption {
|
||||
label: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class DialogService {
|
||||
constructor(private primeDialogService: PrimeDialogService) {}
|
||||
|
||||
open(title: string, options: DialogOption[]): Observable<string> {
|
||||
const result = new Subject<string>();
|
||||
|
||||
const ref = this.primeDialogService.open(DialogListComponent, {
|
||||
header: title,
|
||||
width: '400px',
|
||||
data: {
|
||||
options: options,
|
||||
onSelect: (value: string) => {
|
||||
result.next(value);
|
||||
ref.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ref.onClose.subscribe(() => {
|
||||
result.complete();
|
||||
});
|
||||
|
||||
return result.asObservable();
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
<style>
|
||||
::ng-deep .p-button:focus {
|
||||
box-shadow: none !important;
|
||||
background-color: var(--primary-color) !important;
|
||||
}
|
||||
</style>
|
||||
<div class="flex flex-column gap-2">
|
||||
<p-button *ngFor="let option of config.data.options"
|
||||
[label]="option.label"
|
||||
(onClick)="config.data.onSelect(option.value)"
|
||||
styleClass="w-full text-left"
|
||||
></p-button>
|
||||
</div>
|
||||
`
|
||||
})
|
||||
export class DialogListComponent {
|
||||
constructor(public config: DynamicDialogConfig) {}
|
||||
}
|
@ -23,10 +23,10 @@ export class GithubUpdateService {
|
||||
|
||||
public getReleases(): Observable<GithubRelease[]> {
|
||||
return this.httpClient.get<GithubRelease[]>(
|
||||
'https://api.github.com/repos/skot/esp-miner/releases'
|
||||
'https://api.github.com/repos/bitaxeorg/esp-miner/releases'
|
||||
).pipe(
|
||||
map((releases: GithubRelease[]) => releases.filter((release: GithubRelease) => !release.prerelease))
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -37,8 +37,10 @@ export class SystemService {
|
||||
ssid: "default",
|
||||
wifiPass: "password",
|
||||
wifiStatus: "Connected!",
|
||||
apEnabled: 0,
|
||||
sharesAccepted: 1,
|
||||
sharesRejected: 0,
|
||||
sharesRejectedReasons: [],
|
||||
uptimeSeconds: 38,
|
||||
asicCount: 1,
|
||||
smallCoreCount: 672,
|
||||
|
@ -1,6 +1,9 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { environment } from '../../environments/environment';
|
||||
import { of } from 'rxjs';
|
||||
import { catchError, shareReplay } from 'rxjs/operators';
|
||||
|
||||
export interface ThemeSettings {
|
||||
colorScheme: string;
|
||||
@ -14,15 +17,64 @@ export interface ThemeSettings {
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ThemeService {
|
||||
private themeSettings$ = this.http.get<ThemeSettings>('/api/theme').pipe(
|
||||
catchError(() => of(this.mockSettings)),
|
||||
shareReplay({
|
||||
bufferSize: 1,
|
||||
refCount: true,
|
||||
windowTime: 1000 // 1 second cache
|
||||
})
|
||||
);
|
||||
|
||||
private readonly mockSettings: ThemeSettings = {
|
||||
colorScheme: 'dark',
|
||||
theme: 'dark',
|
||||
accentColors: {
|
||||
'--primary-color': '#F80421',
|
||||
'--primary-color-text': '#ffffff',
|
||||
'--highlight-bg': '#F80421',
|
||||
'--highlight-text-color': '#ffffff',
|
||||
'--focus-ring': '0 0 0 0.2rem rgba(255,64,50,0.2)',
|
||||
// PrimeNG Slider
|
||||
'--slider-bg': '#dee2e6',
|
||||
'--slider-range-bg': '#F80421',
|
||||
'--slider-handle-bg': '#F80421',
|
||||
// Progress Bar
|
||||
'--progressbar-bg': '#dee2e6',
|
||||
'--progressbar-value-bg': '#F80421',
|
||||
// PrimeNG Checkbox
|
||||
'--checkbox-border': '#F80421',
|
||||
'--checkbox-bg': '#F80421',
|
||||
'--checkbox-hover-bg': '#e63c2e',
|
||||
// PrimeNG Button
|
||||
'--button-bg': '#F80421',
|
||||
'--button-hover-bg': '#e63c2e',
|
||||
'--button-focus-shadow': '0 0 0 2px #ffffff, 0 0 0 4px #F80421',
|
||||
// Toggle button
|
||||
'--togglebutton-bg': '#F80421',
|
||||
'--togglebutton-border': '1px solid #F80421',
|
||||
'--togglebutton-hover-bg': '#e63c2e',
|
||||
'--togglebutton-hover-border': '1px solid #e63c2e',
|
||||
'--togglebutton-text-color': '#ffffff'
|
||||
}
|
||||
};
|
||||
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
// Get theme settings from NVS storage
|
||||
getThemeSettings(): Observable<ThemeSettings> {
|
||||
return this.http.get<ThemeSettings>('/api/theme');
|
||||
if (!environment.production) {
|
||||
return of(this.mockSettings);
|
||||
}
|
||||
return this.themeSettings$;
|
||||
}
|
||||
|
||||
// Save theme settings to NVS storage
|
||||
saveThemeSettings(settings: ThemeSettings): Observable<void> {
|
||||
return this.http.post<void>('/api/theme', settings);
|
||||
if (environment.production) {
|
||||
return this.http.post<void>('/api/theme', settings);
|
||||
} else {
|
||||
return of(void 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,10 @@
|
||||
import { eASICModel } from './enum/eASICModel';
|
||||
|
||||
interface ISharesRejectedStat {
|
||||
message: string;
|
||||
count: number;
|
||||
}
|
||||
|
||||
export interface ISystemInfo {
|
||||
|
||||
flipscreen: number;
|
||||
@ -18,8 +23,10 @@ export interface ISystemInfo {
|
||||
macAddr: string,
|
||||
ssid: string,
|
||||
wifiStatus: string,
|
||||
apEnabled: number,
|
||||
sharesAccepted: number,
|
||||
sharesRejected: number,
|
||||
sharesRejectedReasons: ISharesRejectedStat[];
|
||||
uptimeSeconds: number,
|
||||
asicCount: number,
|
||||
smallCoreCount: number,
|
||||
@ -43,5 +50,6 @@ export interface ISystemInfo {
|
||||
|
||||
boardtemp1?: number,
|
||||
boardtemp2?: number,
|
||||
overheat_mode: number
|
||||
overheat_mode: number,
|
||||
overclockEnabled?: number
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include "http_server.h"
|
||||
#include "recovery_page.h"
|
||||
#include "theme_api.h" // Add theme API include
|
||||
#include "cJSON.h"
|
||||
#include "esp_chip_info.h"
|
||||
@ -16,6 +15,8 @@
|
||||
#include "global_state.h"
|
||||
#include "nvs_config.h"
|
||||
#include "vcore.h"
|
||||
#include "power.h"
|
||||
#include "connect.h"
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
@ -32,8 +33,50 @@
|
||||
#include "lwip/sockets.h"
|
||||
#include "lwip/sys.h"
|
||||
#include <pthread.h>
|
||||
#include "connect.h"
|
||||
|
||||
#include "asic.h"
|
||||
|
||||
static const char * TAG = "http_server";
|
||||
static const char * CORS_TAG = "CORS";
|
||||
|
||||
/* Handler for WiFi scan endpoint */
|
||||
static esp_err_t GET_wifi_scan(httpd_req_t *req)
|
||||
{
|
||||
httpd_resp_set_type(req, "application/json");
|
||||
|
||||
// Give some time for the connected flag to take effect
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
|
||||
wifi_ap_record_simple_t ap_records[20];
|
||||
uint16_t ap_count = 0;
|
||||
|
||||
esp_err_t err = wifi_scan(ap_records, &ap_count);
|
||||
if (err != ESP_OK) {
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "WiFi scan failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
cJSON *root = cJSON_CreateObject();
|
||||
cJSON *networks = cJSON_CreateArray();
|
||||
|
||||
for (int i = 0; i < ap_count; i++) {
|
||||
cJSON *network = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(network, "ssid", (char *)ap_records[i].ssid);
|
||||
cJSON_AddNumberToObject(network, "rssi", ap_records[i].rssi);
|
||||
cJSON_AddNumberToObject(network, "authmode", ap_records[i].authmode);
|
||||
cJSON_AddItemToArray(networks, network);
|
||||
}
|
||||
|
||||
cJSON_AddItemToObject(root, "networks", networks);
|
||||
|
||||
const char *response = cJSON_Print(root);
|
||||
httpd_resp_sendstr(req, response);
|
||||
|
||||
free((void *)response);
|
||||
cJSON_Delete(root);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static GlobalState * GLOBAL_STATE;
|
||||
static httpd_handle_t server = NULL;
|
||||
@ -61,6 +104,104 @@ typedef struct rest_server_context
|
||||
|
||||
#define CHECK_FILE_EXTENSION(filename, ext) (strcasecmp(&filename[strlen(filename) - strlen(ext)], ext) == 0)
|
||||
|
||||
static esp_err_t ip_in_private_range(uint32_t address) {
|
||||
uint32_t ip_address = ntohl(address);
|
||||
|
||||
// 10.0.0.0 - 10.255.255.255 (Class A)
|
||||
if ((ip_address >= 0x0A000000) && (ip_address <= 0x0AFFFFFF)) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// 172.16.0.0 - 172.31.255.255 (Class B)
|
||||
if ((ip_address >= 0xAC100000) && (ip_address <= 0xAC1FFFFF)) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// 192.168.0.0 - 192.168.255.255 (Class C)
|
||||
if ((ip_address >= 0xC0A80000) && (ip_address <= 0xC0A8FFFF)) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
static uint32_t extract_origin_ip_addr(char *origin)
|
||||
{
|
||||
char ip_str[16];
|
||||
uint32_t origin_ip_addr = 0;
|
||||
|
||||
// Find the start of the IP address in the Origin header
|
||||
const char *prefix = "http://";
|
||||
char *ip_start = strstr(origin, prefix);
|
||||
if (ip_start) {
|
||||
ip_start += strlen(prefix); // Move past "http://"
|
||||
|
||||
// Extract the IP address portion (up to the next '/')
|
||||
char *ip_end = strchr(ip_start, '/');
|
||||
size_t ip_len = ip_end ? (size_t)(ip_end - ip_start) : strlen(ip_start);
|
||||
if (ip_len < sizeof(ip_str)) {
|
||||
strncpy(ip_str, ip_start, ip_len);
|
||||
ip_str[ip_len] = '\0'; // Null-terminate the string
|
||||
|
||||
// Convert the IP address string to uint32_t
|
||||
origin_ip_addr = inet_addr(ip_str);
|
||||
if (origin_ip_addr == INADDR_NONE) {
|
||||
ESP_LOGW(CORS_TAG, "Invalid IP address: %s", ip_str);
|
||||
} else {
|
||||
ESP_LOGD(CORS_TAG, "Extracted IP address %lu", origin_ip_addr);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGW(CORS_TAG, "IP address string is too long: %s", ip_start);
|
||||
}
|
||||
}
|
||||
|
||||
return origin_ip_addr;
|
||||
}
|
||||
|
||||
static esp_err_t is_network_allowed(httpd_req_t * req)
|
||||
{
|
||||
if (GLOBAL_STATE->SYSTEM_MODULE.ap_enabled == true) {
|
||||
ESP_LOGI(CORS_TAG, "Device in AP mode. Allowing CORS.");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
int sockfd = httpd_req_to_sockfd(req);
|
||||
char ipstr[INET6_ADDRSTRLEN];
|
||||
struct sockaddr_in6 addr; // esp_http_server uses IPv6 addressing
|
||||
socklen_t addr_size = sizeof(addr);
|
||||
|
||||
if (getpeername(sockfd, (struct sockaddr *)&addr, &addr_size) < 0) {
|
||||
ESP_LOGE(CORS_TAG, "Error getting client IP");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
uint32_t request_ip_addr = addr.sin6_addr.un.u32_addr[3];
|
||||
|
||||
// // Convert to IPv6 string
|
||||
// inet_ntop(AF_INET, &addr.sin6_addr, ipstr, sizeof(ipstr));
|
||||
|
||||
// Convert to IPv4 string
|
||||
inet_ntop(AF_INET, &request_ip_addr, ipstr, sizeof(ipstr));
|
||||
|
||||
// Attempt to get the Origin header.
|
||||
char origin[128];
|
||||
uint32_t origin_ip_addr;
|
||||
if (httpd_req_get_hdr_value_str(req, "Origin", origin, sizeof(origin)) == ESP_OK) {
|
||||
ESP_LOGD(CORS_TAG, "Origin header: %s", origin);
|
||||
origin_ip_addr = extract_origin_ip_addr(origin);
|
||||
} else {
|
||||
ESP_LOGD(CORS_TAG, "No origin header found.");
|
||||
origin_ip_addr = request_ip_addr;
|
||||
}
|
||||
|
||||
if (ip_in_private_range(origin_ip_addr) == ESP_OK && ip_in_private_range(request_ip_addr) == ESP_OK) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
ESP_LOGI(CORS_TAG, "Client is NOT in the private ip ranges or same range as server.");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
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};
|
||||
@ -118,6 +259,7 @@ static esp_err_t set_content_type_from_file(httpd_req_t * req, const char * file
|
||||
|
||||
static esp_err_t set_cors_headers(httpd_req_t * req)
|
||||
{
|
||||
|
||||
esp_err_t err;
|
||||
|
||||
err = httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
@ -141,7 +283,15 @@ static esp_err_t set_cors_headers(httpd_req_t * req)
|
||||
/* Recovery handler */
|
||||
static esp_err_t rest_recovery_handler(httpd_req_t * req)
|
||||
{
|
||||
httpd_resp_send(req, recovery_page, HTTPD_RESP_USE_STRLEN);
|
||||
if (is_network_allowed(req) != ESP_OK) {
|
||||
return httpd_resp_send_err(req, HTTPD_401_UNAUTHORIZED, "Unauthorized");
|
||||
}
|
||||
|
||||
extern const unsigned char recovery_page_start[] asm("_binary_recovery_page_html_start");
|
||||
extern const unsigned char recovery_page_end[] asm("_binary_recovery_page_html_end");
|
||||
const size_t recovery_page_size = (recovery_page_end - recovery_page_start);
|
||||
httpd_resp_send_chunk(req, (const char*)recovery_page_start, recovery_page_size);
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -209,6 +359,10 @@ static esp_err_t rest_common_get_handler(httpd_req_t * req)
|
||||
|
||||
static esp_err_t handle_options_request(httpd_req_t * req)
|
||||
{
|
||||
if (is_network_allowed(req) != ESP_OK) {
|
||||
return httpd_resp_send_err(req, HTTPD_401_UNAUTHORIZED, "Unauthorized");
|
||||
}
|
||||
|
||||
// Set CORS headers for OPTIONS request
|
||||
if (set_cors_headers(req) != ESP_OK) {
|
||||
httpd_resp_send_500(req);
|
||||
@ -223,6 +377,11 @@ static esp_err_t handle_options_request(httpd_req_t * req)
|
||||
|
||||
static esp_err_t PATCH_update_settings(httpd_req_t * req)
|
||||
{
|
||||
|
||||
if (is_network_allowed(req) != ESP_OK) {
|
||||
return httpd_resp_send_err(req, HTTPD_401_UNAUTHORIZED, "Unauthorized");
|
||||
}
|
||||
|
||||
// Set CORS headers
|
||||
if (set_cors_headers(req) != ESP_OK) {
|
||||
httpd_resp_send_500(req);
|
||||
@ -256,22 +415,22 @@ static esp_err_t PATCH_update_settings(httpd_req_t * req)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
if ((item = cJSON_GetObjectItem(root, "stratumURL")) != NULL) {
|
||||
if (cJSON_IsString(item = cJSON_GetObjectItem(root, "stratumURL"))) {
|
||||
nvs_config_set_string(NVS_CONFIG_STRATUM_URL, item->valuestring);
|
||||
}
|
||||
if ((item = cJSON_GetObjectItem(root, "fallbackStratumURL")) != NULL) {
|
||||
if (cJSON_IsString(item = cJSON_GetObjectItem(root, "fallbackStratumURL"))) {
|
||||
nvs_config_set_string(NVS_CONFIG_FALLBACK_STRATUM_URL, item->valuestring);
|
||||
}
|
||||
if ((item = cJSON_GetObjectItem(root, "stratumUser")) != NULL) {
|
||||
if (cJSON_IsString(item = cJSON_GetObjectItem(root, "stratumUser"))) {
|
||||
nvs_config_set_string(NVS_CONFIG_STRATUM_USER, item->valuestring);
|
||||
}
|
||||
if ((item = cJSON_GetObjectItem(root, "stratumPassword")) != NULL) {
|
||||
if (cJSON_IsString(item = cJSON_GetObjectItem(root, "stratumPassword"))) {
|
||||
nvs_config_set_string(NVS_CONFIG_STRATUM_PASS, item->valuestring);
|
||||
}
|
||||
if ((item = cJSON_GetObjectItem(root, "fallbackStratumUser")) != NULL) {
|
||||
if (cJSON_IsString(item = cJSON_GetObjectItem(root, "fallbackStratumUser"))) {
|
||||
nvs_config_set_string(NVS_CONFIG_FALLBACK_STRATUM_USER, item->valuestring);
|
||||
}
|
||||
if ((item = cJSON_GetObjectItem(root, "fallbackStratumPassword")) != NULL) {
|
||||
if (cJSON_IsString(item = cJSON_GetObjectItem(root, "fallbackStratumPassword"))) {
|
||||
nvs_config_set_string(NVS_CONFIG_FALLBACK_STRATUM_PASS, item->valuestring);
|
||||
}
|
||||
if ((item = cJSON_GetObjectItem(root, "stratumPort")) != NULL) {
|
||||
@ -280,13 +439,13 @@ static esp_err_t PATCH_update_settings(httpd_req_t * req)
|
||||
if ((item = cJSON_GetObjectItem(root, "fallbackStratumPort")) != NULL) {
|
||||
nvs_config_set_u16(NVS_CONFIG_FALLBACK_STRATUM_PORT, item->valueint);
|
||||
}
|
||||
if ((item = cJSON_GetObjectItem(root, "ssid")) != NULL) {
|
||||
if (cJSON_IsString(item = cJSON_GetObjectItem(root, "ssid"))) {
|
||||
nvs_config_set_string(NVS_CONFIG_WIFI_SSID, item->valuestring);
|
||||
}
|
||||
if ((item = cJSON_GetObjectItem(root, "wifiPass")) != NULL) {
|
||||
if (cJSON_IsString(item = cJSON_GetObjectItem(root, "wifiPass"))) {
|
||||
nvs_config_set_string(NVS_CONFIG_WIFI_PASS, item->valuestring);
|
||||
}
|
||||
if ((item = cJSON_GetObjectItem(root, "hostname")) != NULL) {
|
||||
if (cJSON_IsString(item = cJSON_GetObjectItem(root, "hostname"))) {
|
||||
nvs_config_set_string(NVS_CONFIG_HOSTNAME, item->valuestring);
|
||||
}
|
||||
if ((item = cJSON_GetObjectItem(root, "coreVoltage")) != NULL && item->valueint > 0) {
|
||||
@ -313,6 +472,9 @@ static esp_err_t PATCH_update_settings(httpd_req_t * req)
|
||||
if ((item = cJSON_GetObjectItem(root, "fanspeed")) != NULL) {
|
||||
nvs_config_set_u16(NVS_CONFIG_FAN_SPEED, item->valueint);
|
||||
}
|
||||
if ((item = cJSON_GetObjectItem(root, "overclockEnabled")) != NULL) {
|
||||
nvs_config_set_u16(NVS_CONFIG_OVERCLOCK_ENABLED, item->valueint);
|
||||
}
|
||||
|
||||
cJSON_Delete(root);
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
@ -321,6 +483,10 @@ static esp_err_t PATCH_update_settings(httpd_req_t * req)
|
||||
|
||||
static esp_err_t POST_restart(httpd_req_t * req)
|
||||
{
|
||||
if (is_network_allowed(req) != ESP_OK) {
|
||||
return httpd_resp_send_err(req, HTTPD_401_UNAUTHORIZED, "Unauthorized");
|
||||
}
|
||||
|
||||
// Set CORS headers
|
||||
if (set_cors_headers(req) != ESP_OK) {
|
||||
httpd_resp_send_500(req);
|
||||
@ -346,6 +512,10 @@ static esp_err_t POST_restart(httpd_req_t * req)
|
||||
/* Simple handler for getting system handler */
|
||||
static esp_err_t GET_system_info(httpd_req_t * req)
|
||||
{
|
||||
if (is_network_allowed(req) != ESP_OK) {
|
||||
return httpd_resp_send_err(req, HTTPD_401_UNAUTHORIZED, "Unauthorized");
|
||||
}
|
||||
|
||||
httpd_resp_set_type(req, "application/json");
|
||||
|
||||
// Set CORS headers
|
||||
@ -364,6 +534,8 @@ static esp_err_t GET_system_info(httpd_req_t * req)
|
||||
char * stratumUser = nvs_config_get_string(NVS_CONFIG_STRATUM_USER, CONFIG_STRATUM_USER);
|
||||
char * fallbackStratumUser = nvs_config_get_string(NVS_CONFIG_FALLBACK_STRATUM_USER, CONFIG_FALLBACK_STRATUM_USER);
|
||||
char * board_version = nvs_config_get_string(NVS_CONFIG_BOARD_VERSION, "unknown");
|
||||
uint16_t freq = nvs_config_get_u16(NVS_CONFIG_ASIC_FREQ, CONFIG_ASIC_FREQUENCY);
|
||||
float expected_hashrate = freq * ((ASIC_get_small_core_count(GLOBAL_STATE) * ASIC_get_asic_count(GLOBAL_STATE)) / 1000.0);
|
||||
|
||||
esp_wifi_get_mac(WIFI_IF_STA, mac);
|
||||
snprintf(formattedMac, 18, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
@ -371,48 +543,44 @@ static esp_err_t GET_system_info(httpd_req_t * req)
|
||||
cJSON * root = cJSON_CreateObject();
|
||||
cJSON_AddNumberToObject(root, "power", GLOBAL_STATE->POWER_MANAGEMENT_MODULE.power);
|
||||
cJSON_AddNumberToObject(root, "voltage", GLOBAL_STATE->POWER_MANAGEMENT_MODULE.voltage);
|
||||
cJSON_AddNumberToObject(root, "current", GLOBAL_STATE->POWER_MANAGEMENT_MODULE.current);
|
||||
cJSON_AddNumberToObject(root, "current", Power_get_current(GLOBAL_STATE));
|
||||
cJSON_AddNumberToObject(root, "temp", GLOBAL_STATE->POWER_MANAGEMENT_MODULE.chip_temp_avg);
|
||||
cJSON_AddNumberToObject(root, "vrTemp", GLOBAL_STATE->POWER_MANAGEMENT_MODULE.vr_temp);
|
||||
cJSON_AddNumberToObject(root, "hashRate", GLOBAL_STATE->SYSTEM_MODULE.current_hashrate);
|
||||
cJSON_AddNumberToObject(root, "expectedHashrate", expected_hashrate);
|
||||
cJSON_AddStringToObject(root, "bestDiff", GLOBAL_STATE->SYSTEM_MODULE.best_diff_string);
|
||||
cJSON_AddStringToObject(root, "bestSessionDiff", GLOBAL_STATE->SYSTEM_MODULE.best_session_diff_string);
|
||||
cJSON_AddNumberToObject(root, "stratumDiff", GLOBAL_STATE->stratum_difficulty);
|
||||
|
||||
cJSON_AddNumberToObject(root, "isUsingFallbackStratum", GLOBAL_STATE->SYSTEM_MODULE.is_using_fallback);
|
||||
|
||||
cJSON_AddNumberToObject(root, "isPSRAMAvailable", GLOBAL_STATE->psram_is_available);
|
||||
|
||||
cJSON_AddNumberToObject(root, "freeHeap", esp_get_free_heap_size());
|
||||
cJSON_AddNumberToObject(root, "coreVoltage", nvs_config_get_u16(NVS_CONFIG_ASIC_VOLTAGE, CONFIG_ASIC_VOLTAGE));
|
||||
cJSON_AddNumberToObject(root, "coreVoltageActual", VCORE_get_voltage_mv(GLOBAL_STATE));
|
||||
cJSON_AddNumberToObject(root, "frequency", nvs_config_get_u16(NVS_CONFIG_ASIC_FREQ, CONFIG_ASIC_FREQUENCY));
|
||||
cJSON_AddNumberToObject(root, "frequency", freq);
|
||||
cJSON_AddStringToObject(root, "ssid", ssid);
|
||||
cJSON_AddStringToObject(root, "macAddr", formattedMac);
|
||||
cJSON_AddStringToObject(root, "hostname", hostname);
|
||||
cJSON_AddStringToObject(root, "wifiStatus", GLOBAL_STATE->SYSTEM_MODULE.wifi_status);
|
||||
cJSON_AddNumberToObject(root, "apEnabled", GLOBAL_STATE->SYSTEM_MODULE.ap_enabled);
|
||||
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, "asicCount", GLOBAL_STATE->asic_count);
|
||||
uint16_t small_core_count = 0;
|
||||
switch (GLOBAL_STATE->asic_model){
|
||||
case ASIC_BM1397:
|
||||
small_core_count = BM1397_SMALL_CORE_COUNT;
|
||||
break;
|
||||
case ASIC_BM1366:
|
||||
small_core_count = BM1366_SMALL_CORE_COUNT;
|
||||
break;
|
||||
case ASIC_BM1368:
|
||||
small_core_count = BM1368_SMALL_CORE_COUNT;
|
||||
break;
|
||||
case ASIC_BM1370:
|
||||
small_core_count = BM1370_SMALL_CORE_COUNT;
|
||||
break;
|
||||
case ASIC_UNKNOWN:
|
||||
default:
|
||||
small_core_count = -1;
|
||||
break;
|
||||
|
||||
cJSON *error_array = cJSON_CreateArray();
|
||||
cJSON_AddItemToObject(root, "sharesRejectedReasons", error_array);
|
||||
|
||||
for (int i = 0; i < GLOBAL_STATE->SYSTEM_MODULE.rejected_reason_stats_count; i++) {
|
||||
cJSON *error_obj = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(error_obj, "message", GLOBAL_STATE->SYSTEM_MODULE.rejected_reason_stats[i].message);
|
||||
cJSON_AddNumberToObject(error_obj, "count", GLOBAL_STATE->SYSTEM_MODULE.rejected_reason_stats[i].count);
|
||||
cJSON_AddItemToArray(error_array, error_obj);
|
||||
}
|
||||
cJSON_AddNumberToObject(root, "smallCoreCount", small_core_count);
|
||||
|
||||
cJSON_AddNumberToObject(root, "uptimeSeconds", (esp_timer_get_time() - GLOBAL_STATE->SYSTEM_MODULE.start_time) / 1000000);
|
||||
cJSON_AddNumberToObject(root, "asicCount", ASIC_get_asic_count(GLOBAL_STATE));
|
||||
cJSON_AddNumberToObject(root, "smallCoreCount", ASIC_get_small_core_count(GLOBAL_STATE));
|
||||
cJSON_AddStringToObject(root, "ASICModel", GLOBAL_STATE->asic_model_str);
|
||||
cJSON_AddStringToObject(root, "stratumURL", stratumURL);
|
||||
cJSON_AddStringToObject(root, "fallbackStratumURL", fallbackStratumURL);
|
||||
@ -428,6 +596,7 @@ static esp_err_t GET_system_info(httpd_req_t * req)
|
||||
|
||||
cJSON_AddNumberToObject(root, "flipscreen", nvs_config_get_u16(NVS_CONFIG_FLIP_SCREEN, 1));
|
||||
cJSON_AddNumberToObject(root, "overheat_mode", nvs_config_get_u16(NVS_CONFIG_OVERHEAT_MODE, 0));
|
||||
cJSON_AddNumberToObject(root, "overclockEnabled", nvs_config_get_u16(NVS_CONFIG_OVERCLOCK_ENABLED, 0));
|
||||
cJSON_AddNumberToObject(root, "invertscreen", nvs_config_get_u16(NVS_CONFIG_INVERT_SCREEN, 0));
|
||||
|
||||
cJSON_AddNumberToObject(root, "invertfanpolarity", nvs_config_get_u16(NVS_CONFIG_INVERT_FAN_POLARITY, 1));
|
||||
@ -453,6 +622,10 @@ static esp_err_t GET_system_info(httpd_req_t * req)
|
||||
|
||||
esp_err_t POST_WWW_update(httpd_req_t * req)
|
||||
{
|
||||
if (is_network_allowed(req) != ESP_OK) {
|
||||
return httpd_resp_send_err(req, HTTPD_401_UNAUTHORIZED, "Unauthorized");
|
||||
}
|
||||
|
||||
wifi_mode_t mode;
|
||||
esp_wifi_get_mode(&mode);
|
||||
if (mode == WIFI_MODE_AP || mode == WIFI_MODE_APSTA)
|
||||
@ -461,6 +634,10 @@ esp_err_t POST_WWW_update(httpd_req_t * req)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
GLOBAL_STATE->SYSTEM_MODULE.is_firmware_update = true;
|
||||
snprintf(GLOBAL_STATE->SYSTEM_MODULE.firmware_update_filename, 20, "www.bin");
|
||||
snprintf(GLOBAL_STATE->SYSTEM_MODULE.firmware_update_status, 20, "Starting...");
|
||||
|
||||
char buf[1000];
|
||||
int remaining = req->content_len;
|
||||
|
||||
@ -486,19 +663,30 @@ esp_err_t POST_WWW_update(httpd_req_t * req)
|
||||
if (recv_len == HTTPD_SOCK_ERR_TIMEOUT) {
|
||||
continue;
|
||||
} else if (recv_len <= 0) {
|
||||
snprintf(GLOBAL_STATE->SYSTEM_MODULE.firmware_update_status, 20, "Protocol Error");
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Protocol Error");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
if (esp_partition_write(www_partition, www_partition->size - remaining, (const void *) buf, recv_len) != ESP_OK) {
|
||||
snprintf(GLOBAL_STATE->SYSTEM_MODULE.firmware_update_status, 20, "Write Error");
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Write Error");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
uint8_t percentage = 100 - ((remaining * 100 / req->content_len));
|
||||
snprintf(GLOBAL_STATE->SYSTEM_MODULE.firmware_update_status, 20, "Working (%d%%)", percentage);
|
||||
|
||||
remaining -= recv_len;
|
||||
}
|
||||
|
||||
httpd_resp_sendstr(req, "WWW update complete\n");
|
||||
|
||||
snprintf(GLOBAL_STATE->SYSTEM_MODULE.firmware_update_status, 20, "Finished...");
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
GLOBAL_STATE->SYSTEM_MODULE.is_firmware_update = false;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -507,6 +695,10 @@ esp_err_t POST_WWW_update(httpd_req_t * req)
|
||||
*/
|
||||
esp_err_t POST_OTA_update(httpd_req_t * req)
|
||||
{
|
||||
if (is_network_allowed(req) != ESP_OK) {
|
||||
return httpd_resp_send_err(req, HTTPD_401_UNAUTHORIZED, "Unauthorized");
|
||||
}
|
||||
|
||||
wifi_mode_t mode;
|
||||
esp_wifi_get_mode(&mode);
|
||||
if (mode == WIFI_MODE_AP || mode == WIFI_MODE_APSTA)
|
||||
@ -515,6 +707,10 @@ esp_err_t POST_OTA_update(httpd_req_t * req)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
GLOBAL_STATE->SYSTEM_MODULE.is_firmware_update = true;
|
||||
snprintf(GLOBAL_STATE->SYSTEM_MODULE.firmware_update_filename, 20, "esp-miner.bin");
|
||||
snprintf(GLOBAL_STATE->SYSTEM_MODULE.firmware_update_status, 20, "Starting...");
|
||||
|
||||
char buf[1000];
|
||||
esp_ota_handle_t ota_handle;
|
||||
int remaining = req->content_len;
|
||||
@ -531,6 +727,7 @@ esp_err_t POST_OTA_update(httpd_req_t * req)
|
||||
|
||||
// Serious Error: Abort OTA
|
||||
} else if (recv_len <= 0) {
|
||||
snprintf(GLOBAL_STATE->SYSTEM_MODULE.firmware_update_status, 20, "Protocol Error");
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Protocol Error");
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -538,19 +735,27 @@ esp_err_t POST_OTA_update(httpd_req_t * req)
|
||||
// Successful Upload: Flash firmware chunk
|
||||
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");
|
||||
snprintf(GLOBAL_STATE->SYSTEM_MODULE.firmware_update_status, 20, "Write Error");
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Write Error");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
uint8_t percentage = 100 - ((remaining * 100 / req->content_len));
|
||||
|
||||
snprintf(GLOBAL_STATE->SYSTEM_MODULE.firmware_update_status, 20, "Working (%d%%)", percentage);
|
||||
|
||||
remaining -= recv_len;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
snprintf(GLOBAL_STATE->SYSTEM_MODULE.firmware_update_status, 20, "Validation Error");
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Validation / Activation Error");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
snprintf(GLOBAL_STATE->SYSTEM_MODULE.firmware_update_status, 20, "Rebooting...");
|
||||
|
||||
httpd_resp_sendstr(req, "Firmware update complete, rebooting now!\n");
|
||||
ESP_LOGI(TAG, "Restarting System because of Firmware update complete");
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
@ -626,6 +831,10 @@ void send_log_to_websocket(char *message)
|
||||
*/
|
||||
esp_err_t echo_handler(httpd_req_t * req)
|
||||
{
|
||||
if (is_network_allowed(req) != ESP_OK) {
|
||||
return httpd_resp_send_err(req, HTTPD_401_UNAUTHORIZED, "Unauthorized");
|
||||
}
|
||||
|
||||
if (req->method == HTTP_GET) {
|
||||
ESP_LOGI(TAG, "Handshake done, the new connection was opened");
|
||||
fd = httpd_req_to_sockfd(req);
|
||||
@ -693,6 +902,7 @@ esp_err_t start_rest_server(void * pvParameters)
|
||||
|
||||
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
||||
config.uri_match_fn = httpd_uri_match_wildcard;
|
||||
config.stack_size = 8192;
|
||||
config.max_open_sockets = 10;
|
||||
config.max_uri_handlers = 20;
|
||||
|
||||
@ -700,7 +910,11 @@ esp_err_t start_rest_server(void * pvParameters)
|
||||
REST_CHECK(httpd_start(&server, &config) == ESP_OK, "Start server failed", err_start);
|
||||
|
||||
httpd_uri_t recovery_explicit_get_uri = {
|
||||
.uri = "/recovery", .method = HTTP_GET, .handler = rest_recovery_handler, .user_ctx = rest_context};
|
||||
.uri = "/recovery",
|
||||
.method = HTTP_GET,
|
||||
.handler = rest_recovery_handler,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &recovery_explicit_get_uri);
|
||||
|
||||
// Register theme API endpoints
|
||||
@ -708,9 +922,22 @@ esp_err_t start_rest_server(void * pvParameters)
|
||||
|
||||
/* URI handler for fetching system info */
|
||||
httpd_uri_t system_info_get_uri = {
|
||||
.uri = "/api/system/info", .method = HTTP_GET, .handler = GET_system_info, .user_ctx = rest_context};
|
||||
.uri = "/api/system/info",
|
||||
.method = HTTP_GET,
|
||||
.handler = GET_system_info,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &system_info_get_uri);
|
||||
|
||||
/* URI handler for WiFi scan */
|
||||
httpd_uri_t wifi_scan_get_uri = {
|
||||
.uri = "/api/system/wifi/scan",
|
||||
.method = HTTP_GET,
|
||||
.handler = GET_wifi_scan,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &wifi_scan_get_uri);
|
||||
|
||||
httpd_uri_t swarm_options_uri = {
|
||||
.uri = "/api/swarm",
|
||||
.method = HTTP_OPTIONS,
|
||||
@ -720,15 +947,26 @@ esp_err_t start_rest_server(void * pvParameters)
|
||||
httpd_register_uri_handler(server, &swarm_options_uri);
|
||||
|
||||
httpd_uri_t system_restart_uri = {
|
||||
.uri = "/api/system/restart", .method = HTTP_POST, .handler = POST_restart, .user_ctx = rest_context};
|
||||
.uri = "/api/system/restart", .method = HTTP_POST,
|
||||
.handler = POST_restart,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &system_restart_uri);
|
||||
|
||||
httpd_uri_t system_restart_options_uri = {
|
||||
.uri = "/api/system/restart", .method = HTTP_OPTIONS, .handler = handle_options_request, .user_ctx = NULL};
|
||||
.uri = "/api/system/restart",
|
||||
.method = HTTP_OPTIONS,
|
||||
.handler = handle_options_request,
|
||||
.user_ctx = NULL
|
||||
};
|
||||
httpd_register_uri_handler(server, &system_restart_options_uri);
|
||||
|
||||
httpd_uri_t update_system_settings_uri = {
|
||||
.uri = "/api/system", .method = HTTP_PATCH, .handler = PATCH_update_settings, .user_ctx = rest_context};
|
||||
.uri = "/api/system",
|
||||
.method = HTTP_PATCH,
|
||||
.handler = PATCH_update_settings,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &update_system_settings_uri);
|
||||
|
||||
httpd_uri_t system_options_uri = {
|
||||
@ -740,25 +978,47 @@ esp_err_t start_rest_server(void * pvParameters)
|
||||
httpd_register_uri_handler(server, &system_options_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);
|
||||
|
||||
httpd_uri_t ws = {.uri = "/api/ws", .method = HTTP_GET, .handler = echo_handler, .user_ctx = NULL, .is_websocket = true};
|
||||
httpd_uri_t ws = {
|
||||
.uri = "/api/ws",
|
||||
.method = HTTP_GET,
|
||||
.handler = echo_handler,
|
||||
.user_ctx = NULL,
|
||||
.is_websocket = true
|
||||
};
|
||||
httpd_register_uri_handler(server, &ws);
|
||||
|
||||
if (enter_recovery) {
|
||||
/* Make default route serve Recovery */
|
||||
httpd_uri_t recovery_implicit_get_uri = {
|
||||
.uri = "/*", .method = HTTP_GET, .handler = rest_recovery_handler, .user_ctx = rest_context};
|
||||
.uri = "/*", .method = HTTP_GET,
|
||||
.handler = rest_recovery_handler,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &recovery_implicit_get_uri);
|
||||
|
||||
} else {
|
||||
/* 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};
|
||||
httpd_uri_t common_get_uri = {
|
||||
.uri = "/*",
|
||||
.method = HTTP_GET,
|
||||
.handler = rest_common_get_handler,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &common_get_uri);
|
||||
}
|
||||
|
||||
|
@ -1,79 +0,0 @@
|
||||
#ifndef RECOVERY_PAGE
|
||||
#define RECOVERY_PAGE
|
||||
|
||||
const char recovery_page[] = "<html>"
|
||||
"<style>"
|
||||
"body {"
|
||||
" background-color: #000;"
|
||||
" color: #00ff00;"
|
||||
" font-family: courier new;"
|
||||
"}"
|
||||
"</style>"
|
||||
"<head>"
|
||||
"<title>AxeOS Recovery</title>"
|
||||
"</head>"
|
||||
"<body>"
|
||||
"<pre>"
|
||||
" ____ _____\n"
|
||||
" /\\ / __ \\ / ____|\n"
|
||||
" / \\ __ _____| | | | (___\n"
|
||||
" / /\\ \\ \\ \\/ / _ \\ | | |\\___ \\\n"
|
||||
" / ____ \\ > < __/ |__| |____) |\n"
|
||||
" /_/___ \\_\\/_/\\_\\___|\\____/|_____/\n"
|
||||
" | __ \\\n"
|
||||
" | |__) |___ ___ _____ _____ _ __ _ _\n"
|
||||
" | _ // _ \\/ __/ _ \\ \\ / / _ \\ '__| | | |\n"
|
||||
" | | \\ \\ __/ (_| (_) \\ V / __/ | | |_| |\n"
|
||||
" |_| \\_\\___|\\___\\___/ \\_/ \\___|_| \\__, |\n"
|
||||
" __/ |\n"
|
||||
" |___/\n"
|
||||
"</pre>"
|
||||
"<p>Please upload www.bin to recover AxeOS</p>"
|
||||
"<p>After clicking upload, please wait 60 seconds<br>"
|
||||
"DO NOT restart the device until response is received</p>"
|
||||
"<input type=\"file\" id=\"wwwfile\" name=\"wwwfile\"><br>"
|
||||
"<button id=\"upload\">Upload</button>"
|
||||
"<small id=\"status\"></small>"
|
||||
"<br><button id=\"restart\">Restart</button>"
|
||||
"<br><br>Response:<br>"
|
||||
"<small id=\"response\"></small>"
|
||||
"<script>"
|
||||
"document.getElementById('upload').addEventListener('click', handleUpload);"
|
||||
"statusMsg = document.getElementById('status');"
|
||||
"responseMsg = document.getElementById('response');"
|
||||
"function handleUpload() {"
|
||||
" const fileInput = document.getElementById('wwwfile');"
|
||||
" const file = fileInput.files[0];"
|
||||
" const uploadUrl = '/api/system/OTAWWW';"
|
||||
" const upload_xhr = new XMLHttpRequest();"
|
||||
" upload_xhr.open('POST', uploadUrl, true);"
|
||||
" upload_xhr.setRequestHeader('Content-Type', 'application/octet-stream');"
|
||||
" upload_xhr.onload = function() {"
|
||||
" const responseBody = upload_xhr.responseText;"
|
||||
" if (upload_xhr.status === 200) {"
|
||||
" statusMsg.innerHTML = 'Upload successful!';"
|
||||
" } else {"
|
||||
" statusMsg.innerHTML='Error uploading!';"
|
||||
" }"
|
||||
" responseMsg.innerHTML = responseBody;"
|
||||
" };"
|
||||
" statusMsg.innerHTML = 'uploading...';"
|
||||
" upload_xhr.send(file);"
|
||||
"}"
|
||||
"document.getElementById('restart').addEventListener('click', handleRestart);"
|
||||
"function handleRestart() {"
|
||||
" const restartUrl = '/api/system/restart';"
|
||||
" const restart_xhr = new XMLHttpRequest();"
|
||||
" restart_xhr.open('POST', restartUrl, true);"
|
||||
" restart_xhr.setRequestHeader('Content-Type', '');"
|
||||
" restart_xhr.onload = function() {"
|
||||
" const responseBody = restart_xhr.responseText;"
|
||||
" responseMsg.innerHTML = responseBody;"
|
||||
" };"
|
||||
" restart_xhr.send(null);"
|
||||
"}"
|
||||
"</script>"
|
||||
"</body>"
|
||||
"</html>";
|
||||
|
||||
#endif
|
74
main/http_server/recovery_page.html
Normal file
74
main/http_server/recovery_page.html
Normal file
@ -0,0 +1,74 @@
|
||||
<html>
|
||||
<style>
|
||||
body {
|
||||
background-color: #000;
|
||||
color: #00ff00;
|
||||
font-family: courier new;
|
||||
}
|
||||
</style>
|
||||
<head>
|
||||
<title>AxeOS Recovery</title>
|
||||
</head>
|
||||
<body>
|
||||
<pre>
|
||||
____ _____
|
||||
/\ / __ \ / ____|
|
||||
/ \ __ _____| | | | (___
|
||||
/ /\ \ \ \/ / _ \ | | |\___ \
|
||||
/ ____ \ > < __/ |__| |____) |
|
||||
/_/___ \_\/_/\_\___|\____/|_____/
|
||||
| __ \
|
||||
| |__) |___ ___ _____ _____ _ __ _ _
|
||||
| _ // _ \/ __/ _ \ \ / / _ \ '__| | | |
|
||||
| | \ \ __/ (_| (_) \ V / __/ | | |_| |
|
||||
|_| \_\___|\___\___/ \_/ \___|_| \__, |
|
||||
__/ |
|
||||
|___/
|
||||
</pre>
|
||||
<p>Please upload www.bin to recover AxeOS</p>
|
||||
<p>After clicking upload, please wait 60 seconds<br>
|
||||
DO NOT restart the device until response is received</p>
|
||||
<input type="file" id="wwwfile" name="wwwfile"><br>
|
||||
<button id="upload">Upload</button>
|
||||
<small id="status"></small>
|
||||
<br><button id="restart">Restart</button>
|
||||
<br><br>Response:<br>
|
||||
<small id="response"></small>
|
||||
<script>
|
||||
document.getElementById('upload').addEventListener('click', handleUpload);
|
||||
statusMsg = document.getElementById('status');
|
||||
responseMsg = document.getElementById('response');
|
||||
function handleUpload() {
|
||||
const fileInput = document.getElementById('wwwfile');
|
||||
const file = fileInput.files[0];
|
||||
const uploadUrl = '/api/system/OTAWWW';
|
||||
const upload_xhr = new XMLHttpRequest();
|
||||
upload_xhr.open('POST', uploadUrl, true);
|
||||
upload_xhr.setRequestHeader('Content-Type', 'application/octet-stream');
|
||||
upload_xhr.onload = function() {
|
||||
const responseBody = upload_xhr.responseText;
|
||||
if (upload_xhr.status === 200) {
|
||||
statusMsg.innerHTML = 'Upload successful!';
|
||||
} else {
|
||||
statusMsg.innerHTML='Error uploading!';
|
||||
}
|
||||
responseMsg.innerHTML = responseBody;
|
||||
};
|
||||
statusMsg.innerHTML = 'uploading...';
|
||||
upload_xhr.send(file);
|
||||
}
|
||||
document.getElementById('restart').addEventListener('click', handleRestart);
|
||||
function handleRestart() {
|
||||
const restartUrl = '/api/system/restart';
|
||||
const restart_xhr = new XMLHttpRequest();
|
||||
restart_xhr.open('POST', restartUrl, true);
|
||||
restart_xhr.setRequestHeader('Content-Type', '');
|
||||
restart_xhr.onload = function() {
|
||||
const responseBody = restart_xhr.responseText;
|
||||
responseMsg.innerHTML = responseBody;
|
||||
};
|
||||
restart_xhr.send(null);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -114,6 +114,18 @@ esp_err_t i2c_bitaxe_register_read(i2c_master_dev_handle_t dev_handle, uint8_t r
|
||||
return log_on_error(i2c_master_transmit_receive(dev_handle, ®_addr, 1, read_buf, len, I2C_DEFAULT_TIMEOUT), dev_handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Just write a register address to the I2C device
|
||||
*
|
||||
* @param dev_handle
|
||||
* @param reg_addr
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t i2c_bitaxe_register_write_addr(i2c_master_dev_handle_t dev_handle, uint8_t reg_addr)
|
||||
{
|
||||
return log_on_error(i2c_master_transmit(dev_handle, ®_addr, 1, I2C_DEFAULT_TIMEOUT), dev_handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write a byte to a I2C register
|
||||
* @param dev_handle The I2C device handle
|
||||
|
@ -10,6 +10,7 @@ esp_err_t i2c_bitaxe_add_device(uint8_t device_address, i2c_master_dev_handle_t
|
||||
esp_err_t i2c_bitaxe_get_master_bus_handle(i2c_master_bus_handle_t * dev_handle);
|
||||
|
||||
esp_err_t i2c_bitaxe_register_read(i2c_master_dev_handle_t dev_handle, uint8_t reg_addr, uint8_t * read_buf, size_t len);
|
||||
esp_err_t i2c_bitaxe_register_write_addr(i2c_master_dev_handle_t dev_handle, uint8_t reg_addr);
|
||||
esp_err_t i2c_bitaxe_register_write_byte(i2c_master_dev_handle_t dev_handle, uint8_t reg_addr, uint8_t data);
|
||||
esp_err_t i2c_bitaxe_register_write_bytes(i2c_master_dev_handle_t dev_handle, uint8_t * data, uint8_t len);
|
||||
esp_err_t i2c_bitaxe_register_write_word(i2c_master_dev_handle_t dev_handle, uint8_t reg_addr, uint16_t data);
|
||||
|
@ -4,4 +4,4 @@ dependencies:
|
||||
espressif/esp_lvgl_port: "^2.4.3"
|
||||
## Required IDF version
|
||||
idf:
|
||||
version: ">=5.2.0"
|
||||
version: ">=5.4.0"
|
||||
|
21
main/main.c
21
main/main.c
@ -1,6 +1,7 @@
|
||||
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_psram.h"
|
||||
#include "nvs_flash.h"
|
||||
|
||||
// #include "protocol_examples_common.h"
|
||||
@ -19,6 +20,7 @@
|
||||
#include "adc.h"
|
||||
#include "nvs_device.h"
|
||||
#include "self_test.h"
|
||||
#include "asic.h"
|
||||
|
||||
static GlobalState GLOBAL_STATE = {
|
||||
.extranonce_str = NULL,
|
||||
@ -32,7 +34,14 @@ static const char * TAG = "bitaxe";
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Welcome to the bitaxe - hack the planet!");
|
||||
ESP_LOGI(TAG, "Welcome to the bitaxe - FOSS || GTFO!");
|
||||
|
||||
if (!esp_psram_is_initialized()) {
|
||||
ESP_LOGE(TAG, "No PSRAM available on ESP32 device!");
|
||||
GLOBAL_STATE.psram_is_available = false;
|
||||
} else {
|
||||
GLOBAL_STATE.psram_is_available = true;
|
||||
}
|
||||
|
||||
// Init I2C
|
||||
ESP_ERROR_CHECK(i2c_bitaxe_init());
|
||||
@ -75,7 +84,7 @@ void app_main(void)
|
||||
strncpy(GLOBAL_STATE.SYSTEM_MODULE.ssid, wifi_ssid, sizeof(GLOBAL_STATE.SYSTEM_MODULE.ssid));
|
||||
GLOBAL_STATE.SYSTEM_MODULE.ssid[sizeof(GLOBAL_STATE.SYSTEM_MODULE.ssid)-1] = 0;
|
||||
|
||||
// init and connect to wifi
|
||||
// init AP and connect to wifi
|
||||
wifi_init(wifi_ssid, wifi_pass, hostname, GLOBAL_STATE.SYSTEM_MODULE.ip_addr_str);
|
||||
|
||||
generate_ssid(GLOBAL_STATE.SYSTEM_MODULE.ap_ssid);
|
||||
@ -116,15 +125,15 @@ void app_main(void)
|
||||
|
||||
GLOBAL_STATE.new_stratum_version_rolling_msg = false;
|
||||
|
||||
if (GLOBAL_STATE.ASIC_functions.init_fn != NULL) {
|
||||
wifi_softap_off();
|
||||
wifi_softap_off();
|
||||
|
||||
if (GLOBAL_STATE.valid_model) {
|
||||
queue_init(&GLOBAL_STATE.stratum_queue);
|
||||
queue_init(&GLOBAL_STATE.ASIC_jobs_queue);
|
||||
|
||||
SERIAL_init();
|
||||
(*GLOBAL_STATE.ASIC_functions.init_fn)(GLOBAL_STATE.POWER_MANAGEMENT_MODULE.frequency_value, GLOBAL_STATE.asic_count);
|
||||
SERIAL_set_baud((*GLOBAL_STATE.ASIC_functions.set_max_baud_fn)());
|
||||
ASIC_init(&GLOBAL_STATE);
|
||||
SERIAL_set_baud(ASIC_set_max_baud(&GLOBAL_STATE));
|
||||
SERIAL_clear_buffer();
|
||||
|
||||
GLOBAL_STATE.ASIC_initalized = true;
|
||||
|
@ -29,6 +29,7 @@
|
||||
#define NVS_CONFIG_BEST_DIFF "bestdiff"
|
||||
#define NVS_CONFIG_SELF_TEST "selftest"
|
||||
#define NVS_CONFIG_OVERHEAT_MODE "overheat_mode"
|
||||
#define NVS_CONFIG_OVERCLOCK_ENABLED "oc_enabled"
|
||||
#define NVS_CONFIG_SWARM "swarmconfig"
|
||||
|
||||
// Theme configuration
|
||||
|
@ -1,16 +1,17 @@
|
||||
#include <string.h>
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_check.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "nvs_config.h"
|
||||
#include "nvs_device.h"
|
||||
|
||||
#include "connect.h"
|
||||
#include "global_state.h"
|
||||
#include "asic.h"
|
||||
|
||||
static const char * TAG = "nvs_device";
|
||||
static const double NONCE_SPACE = 4294967296.0; // 2^32
|
||||
|
||||
|
||||
esp_err_t NVSDevice_init(void) {
|
||||
esp_err_t err = nvs_flash_init();
|
||||
@ -39,109 +40,15 @@ esp_err_t NVSDevice_parse_config(GlobalState * GLOBAL_STATE) {
|
||||
GLOBAL_STATE->POWER_MANAGEMENT_MODULE.frequency_value = nvs_config_get_u16(NVS_CONFIG_ASIC_FREQ, CONFIG_ASIC_FREQUENCY);
|
||||
ESP_LOGI(TAG, "NVS_CONFIG_ASIC_FREQ %f", (float)GLOBAL_STATE->POWER_MANAGEMENT_MODULE.frequency_value);
|
||||
|
||||
GLOBAL_STATE->device_model_str = nvs_config_get_string(NVS_CONFIG_DEVICE_MODEL, "");
|
||||
if (strcmp(GLOBAL_STATE->device_model_str, "max") == 0) {
|
||||
ESP_LOGI(TAG, "DEVICE: Max");
|
||||
GLOBAL_STATE->device_model = DEVICE_MAX;
|
||||
GLOBAL_STATE->asic_count = 1;
|
||||
GLOBAL_STATE->voltage_domain = 1;
|
||||
} else if (strcmp(GLOBAL_STATE->device_model_str, "ultra") == 0) {
|
||||
ESP_LOGI(TAG, "DEVICE: Ultra");
|
||||
GLOBAL_STATE->device_model = DEVICE_ULTRA;
|
||||
GLOBAL_STATE->asic_count = 1;
|
||||
GLOBAL_STATE->voltage_domain = 1;
|
||||
} else if (strcmp(GLOBAL_STATE->device_model_str, "supra") == 0) {
|
||||
ESP_LOGI(TAG, "DEVICE: Supra");
|
||||
GLOBAL_STATE->device_model = DEVICE_SUPRA;
|
||||
GLOBAL_STATE->asic_count = 1;
|
||||
GLOBAL_STATE->voltage_domain = 1;
|
||||
} else if (strcmp(GLOBAL_STATE->device_model_str, "gamma") == 0) {
|
||||
ESP_LOGI(TAG, "DEVICE: Gamma");
|
||||
GLOBAL_STATE->device_model = DEVICE_GAMMA;
|
||||
GLOBAL_STATE->asic_count = 1;
|
||||
GLOBAL_STATE->voltage_domain = 1;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Invalid DEVICE model");
|
||||
// maybe should return here to now execute anything with a faulty device parameter !
|
||||
// this stops crashes/reboots and allows dev testing without an asic
|
||||
GLOBAL_STATE->device_model = DEVICE_UNKNOWN;
|
||||
GLOBAL_STATE->asic_count = -1;
|
||||
GLOBAL_STATE->voltage_domain = 1;
|
||||
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
GLOBAL_STATE->board_version = atoi(nvs_config_get_string(NVS_CONFIG_BOARD_VERSION, "000"));
|
||||
GLOBAL_STATE->asic_model_str = nvs_config_get_string(NVS_CONFIG_ASIC_MODEL, "");
|
||||
GLOBAL_STATE->device_model_str = nvs_config_get_string(NVS_CONFIG_DEVICE_MODEL, "invalid");
|
||||
char * board_version = nvs_config_get_string(NVS_CONFIG_BOARD_VERSION, "000");
|
||||
GLOBAL_STATE->board_version = atoi(board_version);
|
||||
free(board_version);
|
||||
ESP_LOGI(TAG, "Found Device Model: %s", GLOBAL_STATE->device_model_str);
|
||||
ESP_LOGI(TAG, "Found Board Version: %d", GLOBAL_STATE->board_version);
|
||||
|
||||
GLOBAL_STATE->asic_model_str = nvs_config_get_string(NVS_CONFIG_ASIC_MODEL, "");
|
||||
if (strcmp(GLOBAL_STATE->asic_model_str, "BM1366") == 0) {
|
||||
ESP_LOGI(TAG, "ASIC: %dx BM1366 (%" PRIu64 " cores)", GLOBAL_STATE->asic_count, BM1366_CORE_COUNT);
|
||||
GLOBAL_STATE->asic_model = ASIC_BM1366;
|
||||
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,
|
||||
.set_version_mask = BM1366_set_version_mask};
|
||||
//GLOBAL_STATE.asic_job_frequency_ms = (NONCE_SPACE / (double) (GLOBAL_STATE.POWER_MANAGEMENT_MODULE.frequency_value * BM1366_CORE_COUNT * 1000)) / (double) GLOBAL_STATE.asic_count; // version-rolling so Small Cores have different Nonce Space
|
||||
GLOBAL_STATE->asic_job_frequency_ms = 2000; //ms
|
||||
GLOBAL_STATE->ASIC_difficulty = BM1366_ASIC_DIFFICULTY;
|
||||
|
||||
GLOBAL_STATE->ASIC_functions = ASIC_functions;
|
||||
} else if (strcmp(GLOBAL_STATE->asic_model_str, "BM1370") == 0) {
|
||||
ESP_LOGI(TAG, "ASIC: %dx BM1370 (%" PRIu64 " cores)", GLOBAL_STATE->asic_count, BM1370_CORE_COUNT);
|
||||
GLOBAL_STATE->asic_model = ASIC_BM1370;
|
||||
AsicFunctions ASIC_functions = {.init_fn = BM1370_init,
|
||||
.receive_result_fn = BM1370_proccess_work,
|
||||
.set_max_baud_fn = BM1370_set_max_baud,
|
||||
.set_difficulty_mask_fn = BM1370_set_job_difficulty_mask,
|
||||
.send_work_fn = BM1370_send_work,
|
||||
.set_version_mask = BM1370_set_version_mask};
|
||||
//GLOBAL_STATE.asic_job_frequency_ms = (NONCE_SPACE / (double) (GLOBAL_STATE.POWER_MANAGEMENT_MODULE.frequency_value * BM1370_CORE_COUNT * 1000)) / (double) GLOBAL_STATE.asic_count; // version-rolling so Small Cores have different Nonce Space
|
||||
GLOBAL_STATE->asic_job_frequency_ms = 500; //ms
|
||||
GLOBAL_STATE->ASIC_difficulty = BM1370_ASIC_DIFFICULTY;
|
||||
|
||||
GLOBAL_STATE->ASIC_functions = ASIC_functions;
|
||||
} else if (strcmp(GLOBAL_STATE->asic_model_str, "BM1368") == 0) {
|
||||
ESP_LOGI(TAG, "ASIC: %dx BM1368 (%" PRIu64 " cores)", GLOBAL_STATE->asic_count, BM1368_CORE_COUNT);
|
||||
GLOBAL_STATE->asic_model = ASIC_BM1368;
|
||||
AsicFunctions ASIC_functions = {.init_fn = BM1368_init,
|
||||
.receive_result_fn = BM1368_proccess_work,
|
||||
.set_max_baud_fn = BM1368_set_max_baud,
|
||||
.set_difficulty_mask_fn = BM1368_set_job_difficulty_mask,
|
||||
.send_work_fn = BM1368_send_work,
|
||||
.set_version_mask = BM1368_set_version_mask};
|
||||
//GLOBAL_STATE.asic_job_frequency_ms = (NONCE_SPACE / (double) (GLOBAL_STATE.POWER_MANAGEMENT_MODULE.frequency_value * BM1368_CORE_COUNT * 1000)) / (double) GLOBAL_STATE.asic_count; // version-rolling so Small Cores have different Nonce Space
|
||||
GLOBAL_STATE->asic_job_frequency_ms = 500; //ms
|
||||
GLOBAL_STATE->ASIC_difficulty = BM1368_ASIC_DIFFICULTY;
|
||||
|
||||
GLOBAL_STATE->ASIC_functions = ASIC_functions;
|
||||
} else if (strcmp(GLOBAL_STATE->asic_model_str, "BM1397") == 0) {
|
||||
ESP_LOGI(TAG, "ASIC: %dx BM1397 (%" PRIu64 " cores)", GLOBAL_STATE->asic_count, BM1397_SMALL_CORE_COUNT);
|
||||
GLOBAL_STATE->asic_model = ASIC_BM1397;
|
||||
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,
|
||||
.set_version_mask = BM1397_set_version_mask};
|
||||
GLOBAL_STATE->asic_job_frequency_ms = (NONCE_SPACE / (double) (GLOBAL_STATE->POWER_MANAGEMENT_MODULE.frequency_value * BM1397_SMALL_CORE_COUNT * 1000)) / (double) GLOBAL_STATE->asic_count; // no version-rolling so same Nonce Space is splitted between Small Cores
|
||||
GLOBAL_STATE->ASIC_difficulty = BM1397_ASIC_DIFFICULTY;
|
||||
|
||||
GLOBAL_STATE->ASIC_functions = ASIC_functions;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Invalid ASIC model");
|
||||
AsicFunctions ASIC_functions = {.init_fn = NULL,
|
||||
.receive_result_fn = NULL,
|
||||
.set_max_baud_fn = NULL,
|
||||
.set_difficulty_mask_fn = NULL,
|
||||
.send_work_fn = NULL};
|
||||
GLOBAL_STATE->ASIC_functions = ASIC_functions;
|
||||
// maybe should return here to not execute anything with a faulty device parameter !
|
||||
return ESP_FAIL;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(ASIC_set_device_model(GLOBAL_STATE), TAG, "Failed to get device model");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
@ -10,6 +10,18 @@
|
||||
#define DS4432U_OUT0_REG 0xF8 // register for current output 0
|
||||
#define DS4432U_OUT1_REG 0xF9 // register for current output 1
|
||||
|
||||
// DS4432U Transfer function constants for Bitaxe board
|
||||
// #define BITAXE_RFS 80000.0 // R16
|
||||
// #define BITAXE_IFS ((DS4432_VRFS * 127.0) / (BITAXE_RFS * 16))
|
||||
#define BITAXE_IFS 0.000098921 // (Vrfs / Rfs) x (127/16) -> Vrfs = 0.997, Rfs = 80000
|
||||
#define BITAXE_RA 4750.0 // R14
|
||||
#define BITAXE_RB 3320.0 // R15
|
||||
#define BITAXE_VNOM 1.451 // this is with the current DAC set to 0. Should be pretty close to (VFB*(RA+RB))/RB
|
||||
#define BITAXE_VMAX 2.39
|
||||
#define BITAXE_VMIN 0.046
|
||||
|
||||
#define TPS40305_VFB 0.6
|
||||
|
||||
static const char *TAG = "DS4432U";
|
||||
|
||||
static i2c_master_dev_handle_t ds4432u_dev_handle;
|
||||
@ -35,6 +47,29 @@ esp_err_t DS4432U_set_current_code(uint8_t output, uint8_t code) {
|
||||
return i2c_bitaxe_register_write_byte(ds4432u_dev_handle, reg, code);
|
||||
}
|
||||
|
||||
esp_err_t DS4432U_set_voltage(float vout) {
|
||||
float change;
|
||||
uint8_t reg;
|
||||
|
||||
// make sure the requested voltage is in within range of BITAXE_VMIN and BITAXE_VMAX
|
||||
if (vout > BITAXE_VMAX || vout < BITAXE_VMIN) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// this is the transfer function. comes from the DS4432U+ datasheet
|
||||
change = fabs((((TPS40305_VFB / BITAXE_RB) - ((vout - TPS40305_VFB) / BITAXE_RA)) / BITAXE_IFS) * 127);
|
||||
reg = (uint8_t)ceil(change);
|
||||
|
||||
// Set the MSB high if the requested voltage is BELOW nominal
|
||||
if (vout < BITAXE_VNOM) {
|
||||
reg |= 0x80;
|
||||
}
|
||||
|
||||
ESP_RETURN_ON_ERROR(DS4432U_set_current_code(0, reg), TAG, "DS4432U set current code failed!");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the current DAC code value for a specific DS4432U output.
|
||||
*
|
@ -10,5 +10,6 @@ esp_err_t DS4432U_test(void);
|
||||
esp_err_t DS4432U_init(void);
|
||||
esp_err_t DS4432U_set_current_code(uint8_t output, uint8_t code);
|
||||
esp_err_t DS4432U_get_current_code(uint8_t output, uint8_t *code);
|
||||
esp_err_t DS4432U_set_voltage(float vout);
|
||||
|
||||
#endif /* DS4432U_H_ */
|
@ -3,6 +3,7 @@
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include "esp_log.h"
|
||||
#include "esp_err.h"
|
||||
#include "pmbus_commands.h"
|
||||
|
||||
#include "i2c_bitaxe.h"
|
||||
@ -35,6 +36,8 @@ static uint8_t MFR_REVISION[] = {0x00, 0x00, 0x01};
|
||||
|
||||
static i2c_master_dev_handle_t tps546_dev_handle;
|
||||
|
||||
static TPS546_CONFIG tps546_config;
|
||||
|
||||
/**
|
||||
* @brief SMBus read byte
|
||||
* @param command The command to read
|
||||
@ -55,6 +58,15 @@ static esp_err_t smb_write_byte(uint8_t command, uint8_t data)
|
||||
return i2c_bitaxe_register_write_byte(tps546_dev_handle, command, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SMBus write addr
|
||||
* @param command The command to write
|
||||
*/
|
||||
static esp_err_t smb_write_addr(uint8_t command)
|
||||
{
|
||||
return i2c_bitaxe_register_write_addr(tps546_dev_handle, command);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SMBus read word
|
||||
* @param command The command to read
|
||||
@ -318,7 +330,7 @@ static uint16_t float_2_ulinear16(float value)
|
||||
/**
|
||||
* @brief Set up the TPS546 regulator and turn it on
|
||||
*/
|
||||
int TPS546_init(void)
|
||||
esp_err_t TPS546_init(TPS546_CONFIG config)
|
||||
{
|
||||
uint8_t data[7];
|
||||
uint8_t u8_value;
|
||||
@ -328,11 +340,13 @@ int TPS546_init(void)
|
||||
uint8_t comp_config[5];
|
||||
uint8_t voutmode;
|
||||
|
||||
tps546_config = config;
|
||||
|
||||
ESP_LOGI(TAG, "Initializing the core voltage regulator");
|
||||
|
||||
if (i2c_bitaxe_add_device(TPS546_I2CADDR, &tps546_dev_handle, TAG) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to add I2C device");
|
||||
return -1;
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* Establish communication with regulator */
|
||||
@ -342,7 +356,7 @@ int TPS546_init(void)
|
||||
if ( (memcmp(data, DEVICE_ID1, 6) != 0) && (memcmp(data, DEVICE_ID2, 6) != 0) && (memcmp(data, DEVICE_ID3, 6) != 0))
|
||||
{
|
||||
ESP_LOGE(TAG, "Cannot find TPS546 regulator - Device ID mismatch");
|
||||
return -1;
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* Make sure power is turned off until commanded */
|
||||
@ -375,46 +389,77 @@ int TPS546_init(void)
|
||||
/* Show voltage settings */
|
||||
TPS546_show_voltage_settings();
|
||||
|
||||
//TPS546_print_status();
|
||||
uint16_t status;
|
||||
TPS546_check_status(&status);
|
||||
|
||||
// ESP_LOGI(TAG, "-----------VOLTAGE/CURRENT---------------------");
|
||||
// /* Get voltage input (SLINEAR11) */
|
||||
// ESP_LOGI(TAG, "READ_VIN: %.2fV", TPS546_get_vin());
|
||||
// /* Get output current (SLINEAR11) */
|
||||
// ESP_LOGI(TAG, "READ_IOUT: %.2fA", TPS546_get_iout());
|
||||
// /* Get voltage output (ULINEAR16) */
|
||||
// ESP_LOGI(TAG, "READ_VOUT: %.2fV", TPS546_get_vout());
|
||||
if (status != 0) {
|
||||
ESP_LOGE(TAG, "Status error: %04x", status);
|
||||
TPS546_parse_status(status);
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "-----------VOLTAGE/CURRENT---------------------");
|
||||
smb_read_word(PMBUS_READ_VIN, &u16_value);
|
||||
ESP_LOGI(TAG, "read READ_VIN: %.2fV", slinear11_2_float(u16_value));
|
||||
smb_read_word(PMBUS_READ_IOUT, &u16_value);
|
||||
ESP_LOGI(TAG, "read READ_IOUT: %.2fA", slinear11_2_float(u16_value));
|
||||
smb_read_word(PMBUS_READ_VOUT, &u16_value);
|
||||
ESP_LOGI(TAG, "read READ_VOUT: %.2fV", ulinear16_2_float(u16_value));
|
||||
|
||||
ESP_LOGI(TAG, "-----------TIMING---------------------");
|
||||
smb_read_word(PMBUS_TON_DELAY, &u16_value);
|
||||
temp = slinear11_2_int(u16_value);
|
||||
ESP_LOGI(TAG, "TON_DELAY: %d", temp);
|
||||
ESP_LOGI(TAG, "read TON_DELAY: %dms", temp);
|
||||
smb_read_word(PMBUS_TON_RISE, &u16_value);
|
||||
temp = slinear11_2_int(u16_value);
|
||||
ESP_LOGI(TAG, "TON_RISE: %d", temp);
|
||||
ESP_LOGI(TAG, "read TON_RISE: %dms", temp);
|
||||
smb_read_word(PMBUS_TON_MAX_FAULT_LIMIT, &u16_value);
|
||||
temp = slinear11_2_int(u16_value);
|
||||
ESP_LOGI(TAG, "TON_MAX_FAULT_LIMIT: %d", temp);
|
||||
ESP_LOGI(TAG, "read TON_MAX_FAULT_LIMIT: %dms", temp);
|
||||
smb_read_byte(PMBUS_TON_MAX_FAULT_RESPONSE, &u8_value);
|
||||
ESP_LOGI(TAG, "TON_MAX_FAULT_RESPONSE: %02x", u8_value);
|
||||
ESP_LOGI(TAG, "read TON_MAX_FAULT_RESPONSE: %02x", u8_value);
|
||||
smb_read_word(PMBUS_TOFF_DELAY, &u16_value);
|
||||
temp = slinear11_2_int(u16_value);
|
||||
ESP_LOGI(TAG, "TOFF_DELAY: %d", temp);
|
||||
ESP_LOGI(TAG, "read TOFF_DELAY: %dms", temp);
|
||||
smb_read_word(PMBUS_TOFF_FALL, &u16_value);
|
||||
temp = slinear11_2_int(u16_value);
|
||||
ESP_LOGI(TAG, "TOFF_FALL: %d", temp);
|
||||
ESP_LOGI(TAG, "--------------------------------------");
|
||||
ESP_LOGI(TAG, "read TOFF_FALL: %dms", temp);
|
||||
ESP_LOGI(TAG, "---------CONFIG--------------------");
|
||||
smb_read_byte(PMBUS_PHASE, &u8_value);
|
||||
ESP_LOGI(TAG, "read PHASE: %02x", u8_value);
|
||||
smb_read_word(PMBUS_STACK_CONFIG, &u16_value);
|
||||
ESP_LOGI(TAG, "read STACK_CONFIG: %04x", u16_value);
|
||||
smb_read_byte(PMBUS_SYNC_CONFIG, &u8_value);
|
||||
ESP_LOGI(TAG, "read SYNC_CONFIG: %02x", u8_value);
|
||||
smb_read_word(PMBUS_INTERLEAVE, &u16_value);
|
||||
ESP_LOGI(TAG, "read INTERLEAVE: %04x", u16_value);
|
||||
smb_read_byte(PMBUS_CAPABILITY, &u8_value);
|
||||
ESP_LOGI(TAG, "read CAPABILITY: %02x", u8_value);
|
||||
|
||||
|
||||
// Read the compensation config registers
|
||||
if (smb_read_block(PMBUS_COMPENSATION_CONFIG, comp_config, 5) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to read COMPENSATION CONFIG");
|
||||
return -1;
|
||||
return ESP_FAIL;
|
||||
}
|
||||
ESP_LOGI(TAG, "COMPENSATION CONFIG");
|
||||
ESP_LOGI(TAG, "read COMPENSATION CONFIG");
|
||||
ESP_LOGI(TAG, "%02x %02x %02x %02x %02x", comp_config[0], comp_config[1],
|
||||
comp_config[2], comp_config[3], comp_config[4]);
|
||||
|
||||
return 0;
|
||||
|
||||
ESP_LOGI(TAG, "Clearing faults");
|
||||
TPS546_clear_faults();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t TPS546_clear_faults(void) {
|
||||
// if (smb_write_byte(PMBUS_CLEAR_FAULTS, 0xFF) != ESP_OK) {
|
||||
if (smb_write_addr(PMBUS_CLEAR_FAULTS) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to clear faults");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -442,10 +487,9 @@ void TPS546_read_mfr_info(uint8_t *read_mfr_revision)
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "MFR_ID: %s", read_mfr_id);
|
||||
ESP_LOGI(TAG, "MFR_MODEL: %s", read_mfr_model);
|
||||
ESP_LOGI(TAG, "MFR_REVISION: %d%d%d ", read_mfr_revision[0],
|
||||
read_mfr_revision[1], read_mfr_revision[2]);
|
||||
ESP_LOGI(TAG, "MFR_ID: %02X %02X %02X", read_mfr_id[0], read_mfr_id[1], read_mfr_id[2]);
|
||||
ESP_LOGI(TAG, "MFR_MODEL: %02X %02X %02X", read_mfr_model[0], read_mfr_model[1], read_mfr_model[2]);
|
||||
ESP_LOGI(TAG, "MFR_REVISION: %02X %02X %02X", read_mfr_revision[0], read_mfr_revision[1], read_mfr_revision[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -453,9 +497,12 @@ void TPS546_read_mfr_info(uint8_t *read_mfr_revision)
|
||||
*/
|
||||
void TPS546_set_mfr_info(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Setting MFR info");
|
||||
ESP_LOGI(TAG, "----- Manufacturer Info");
|
||||
ESP_LOGI(TAG, "Setting MFR_ID: %02X %02X %02X", MFR_ID[0], MFR_ID[1], MFR_ID[2]);
|
||||
smb_write_block(PMBUS_MFR_ID, MFR_ID, 3);
|
||||
ESP_LOGI(TAG, "Setting MFR_MODEL: %02X %02X %02X", MFR_MODEL[0], MFR_MODEL[1], MFR_MODEL[2]);
|
||||
smb_write_block(PMBUS_MFR_MODEL, MFR_MODEL, 3);
|
||||
ESP_LOGI(TAG, "Setting MFR_REVISION: %02X %02X %02X", MFR_REVISION[0], MFR_REVISION[1], MFR_REVISION[2]);
|
||||
smb_write_block(PMBUS_MFR_REVISION, MFR_REVISION, 3);
|
||||
}
|
||||
|
||||
@ -466,78 +513,104 @@ void TPS546_write_entire_config(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "---Writing new config values to TPS546---");
|
||||
/* set up the ON_OFF_CONFIG */
|
||||
ESP_LOGI(TAG, "Setting ON_OFF_CONFIG");
|
||||
ESP_LOGI(TAG, "Setting ON_OFF_CONFIG: %02X", TPS546_INIT_ON_OFF_CONFIG);
|
||||
if (smb_write_byte(PMBUS_ON_OFF_CONFIG, TPS546_INIT_ON_OFF_CONFIG) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to write ON_OFF_CONFIG");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Phase */
|
||||
ESP_LOGI(TAG, "Setting PHASE: %02X", TPS546_INIT_PHASE);
|
||||
smb_write_byte(PMBUS_PHASE, TPS546_INIT_PHASE);
|
||||
|
||||
/* Switch frequency */
|
||||
ESP_LOGI(TAG, "Setting FREQUENCY");
|
||||
ESP_LOGI(TAG, "Setting FREQUENCY: %dMHz", TPS546_INIT_FREQUENCY);
|
||||
smb_write_word(PMBUS_FREQUENCY_SWITCH, int_2_slinear11(TPS546_INIT_FREQUENCY));
|
||||
|
||||
/* vin voltage */
|
||||
ESP_LOGI(TAG, "Setting VIN_ON: %.2f", TPS546_INIT_VIN_ON);
|
||||
smb_write_word(PMBUS_VIN_ON, float_2_slinear11(TPS546_INIT_VIN_ON));
|
||||
ESP_LOGI(TAG, "Setting VIN_OFF: %.2f", TPS546_INIT_VIN_OFF);
|
||||
smb_write_word(PMBUS_VIN_OFF, float_2_slinear11(TPS546_INIT_VIN_OFF));
|
||||
ESP_LOGI(TAG, "Setting VIN_UV_WARN_LIMIT: %.2f", TPS546_INIT_VIN_UV_WARN_LIMIT);
|
||||
smb_write_word(PMBUS_VIN_UV_WARN_LIMIT, float_2_slinear11(TPS546_INIT_VIN_UV_WARN_LIMIT));
|
||||
ESP_LOGI(TAG, "Setting VIN_OV_FAULT_LIMIT: %.2f", TPS546_INIT_VIN_OV_FAULT_LIMIT);
|
||||
smb_write_word(PMBUS_VIN_OV_FAULT_LIMIT, float_2_slinear11(TPS546_INIT_VIN_OV_FAULT_LIMIT));
|
||||
|
||||
//deal with the UV_WARN_LIMIT bug
|
||||
if (tps546_config.TPS546_INIT_VIN_UV_WARN_LIMIT > 0) {
|
||||
ESP_LOGI(TAG, "Setting VIN_UV_WARN_LIMIT: %.2f", tps546_config.TPS546_INIT_VIN_UV_WARN_LIMIT);
|
||||
smb_write_word(PMBUS_VIN_UV_WARN_LIMIT, float_2_slinear11(tps546_config.TPS546_INIT_VIN_UV_WARN_LIMIT));
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Setting VIN_ON: %.2fV", tps546_config.TPS546_INIT_VIN_ON);
|
||||
smb_write_word(PMBUS_VIN_ON, float_2_slinear11(tps546_config.TPS546_INIT_VIN_ON));
|
||||
|
||||
ESP_LOGI(TAG, "Setting VIN_OFF: %.2fV", tps546_config.TPS546_INIT_VIN_OFF);
|
||||
smb_write_word(PMBUS_VIN_OFF, float_2_slinear11(tps546_config.TPS546_INIT_VIN_OFF));
|
||||
|
||||
ESP_LOGI(TAG, "Setting VIN_OV_FAULT_LIMIT: %.2fV", tps546_config.TPS546_INIT_VIN_OV_FAULT_LIMIT);
|
||||
smb_write_word(PMBUS_VIN_OV_FAULT_LIMIT, float_2_slinear11(tps546_config.TPS546_INIT_VIN_OV_FAULT_LIMIT));
|
||||
|
||||
ESP_LOGI(TAG, "Setting VIN_OV_FAULT_RESPONSE: %02X", TPS546_INIT_VIN_OV_FAULT_RESPONSE);
|
||||
smb_write_byte(PMBUS_VIN_OV_FAULT_RESPONSE, TPS546_INIT_VIN_OV_FAULT_RESPONSE);
|
||||
|
||||
/* vout voltage */
|
||||
ESP_LOGI(TAG, "Setting VOUT SCALE: %.2f", TPS546_INIT_SCALE_LOOP);
|
||||
smb_write_word(PMBUS_VOUT_SCALE_LOOP, float_2_slinear11(TPS546_INIT_SCALE_LOOP));
|
||||
ESP_LOGI(TAG, "VOUT_COMMAND: %.2f", TPS546_INIT_VOUT_COMMAND);
|
||||
smb_write_word(PMBUS_VOUT_COMMAND, float_2_ulinear16(TPS546_INIT_VOUT_COMMAND));
|
||||
ESP_LOGI(TAG, "VOUT_MAX: %d", TPS546_INIT_VOUT_MAX);
|
||||
smb_write_word(PMBUS_VOUT_MAX, float_2_ulinear16(TPS546_INIT_VOUT_MAX));
|
||||
ESP_LOGI(TAG, "VOUT_OV_FAULT_LIMIT: %.2f", TPS546_INIT_VOUT_OV_FAULT_LIMIT);
|
||||
ESP_LOGI(TAG, "Setting VOUT SCALE: %.2f", tps546_config.TPS546_INIT_SCALE_LOOP);
|
||||
smb_write_word(PMBUS_VOUT_SCALE_LOOP, float_2_slinear11(tps546_config.TPS546_INIT_SCALE_LOOP));
|
||||
|
||||
ESP_LOGI(TAG, "Setting VOUT_COMMAND: %.2fV", tps546_config.TPS546_INIT_VOUT_COMMAND);
|
||||
smb_write_word(PMBUS_VOUT_COMMAND, float_2_ulinear16(tps546_config.TPS546_INIT_VOUT_COMMAND));
|
||||
|
||||
ESP_LOGI(TAG, "Setting VOUT_MAX: %.2fV", tps546_config.TPS546_INIT_VOUT_MAX);
|
||||
smb_write_word(PMBUS_VOUT_MAX, float_2_ulinear16(tps546_config.TPS546_INIT_VOUT_MAX));
|
||||
|
||||
ESP_LOGI(TAG, "Setting VOUT_MIN: %.2fV", tps546_config.TPS546_INIT_VOUT_MIN);
|
||||
smb_write_word(PMBUS_VOUT_MIN, float_2_ulinear16(tps546_config.TPS546_INIT_VOUT_MIN));
|
||||
|
||||
ESP_LOGI(TAG, "Setting VOUT_OV_FAULT_LIMIT: %.2f", TPS546_INIT_VOUT_OV_FAULT_LIMIT);
|
||||
smb_write_word(PMBUS_VOUT_OV_FAULT_LIMIT, float_2_ulinear16(TPS546_INIT_VOUT_OV_FAULT_LIMIT));
|
||||
ESP_LOGI(TAG, "VOUT_OV_WARN_LIMIT: %.2f", TPS546_INIT_VOUT_OV_WARN_LIMIT);
|
||||
|
||||
ESP_LOGI(TAG, "Setting VOUT_OV_WARN_LIMIT: %.2f", TPS546_INIT_VOUT_OV_WARN_LIMIT);
|
||||
smb_write_word(PMBUS_VOUT_OV_WARN_LIMIT, float_2_ulinear16(TPS546_INIT_VOUT_OV_WARN_LIMIT));
|
||||
ESP_LOGI(TAG, "VOUT_MARGIN_HIGH: %.2f", TPS546_INIT_VOUT_MARGIN_HIGH);
|
||||
|
||||
ESP_LOGI(TAG, "Setting VOUT_MARGIN_HIGH: %.2f", TPS546_INIT_VOUT_MARGIN_HIGH);
|
||||
smb_write_word(PMBUS_VOUT_MARGIN_HIGH, float_2_ulinear16(TPS546_INIT_VOUT_MARGIN_HIGH));
|
||||
ESP_LOGI(TAG, "VOUT_MARGIN_LOW: %.2f", TPS546_INIT_VOUT_MARGIN_LOW);
|
||||
|
||||
ESP_LOGI(TAG, "Setting VOUT_MARGIN_LOW: %.2f", TPS546_INIT_VOUT_MARGIN_LOW);
|
||||
smb_write_word(PMBUS_VOUT_MARGIN_LOW, float_2_ulinear16(TPS546_INIT_VOUT_MARGIN_LOW));
|
||||
ESP_LOGI(TAG, "VOUT_UV_WARN_LIMIT: %.2f", TPS546_INIT_VOUT_UV_WARN_LIMIT);
|
||||
|
||||
ESP_LOGI(TAG, "Setting VOUT_UV_WARN_LIMIT: %.2f", TPS546_INIT_VOUT_UV_WARN_LIMIT);
|
||||
smb_write_word(PMBUS_VOUT_UV_WARN_LIMIT, float_2_ulinear16(TPS546_INIT_VOUT_UV_WARN_LIMIT));
|
||||
ESP_LOGI(TAG, "VOUT_UV_FAULT_LIMIT: %.2f", TPS546_INIT_VOUT_UV_FAULT_LIMIT);
|
||||
|
||||
ESP_LOGI(TAG, "Setting VOUT_UV_FAULT_LIMIT: %.2f", TPS546_INIT_VOUT_UV_FAULT_LIMIT);
|
||||
smb_write_word(PMBUS_VOUT_UV_FAULT_LIMIT, float_2_ulinear16(TPS546_INIT_VOUT_UV_FAULT_LIMIT));
|
||||
ESP_LOGI(TAG, "VOUT_MIN: %d", TPS546_INIT_VOUT_MIN);
|
||||
smb_write_word(PMBUS_VOUT_MIN, float_2_ulinear16(TPS546_INIT_VOUT_MIN));
|
||||
|
||||
/* iout current */
|
||||
ESP_LOGI(TAG, "Setting IOUT");
|
||||
smb_write_word(PMBUS_IOUT_OC_WARN_LIMIT, float_2_slinear11(TPS546_INIT_IOUT_OC_WARN_LIMIT));
|
||||
smb_write_word(PMBUS_IOUT_OC_FAULT_LIMIT, float_2_slinear11(TPS546_INIT_IOUT_OC_FAULT_LIMIT));
|
||||
ESP_LOGI(TAG, "----- IOUT");
|
||||
ESP_LOGI(TAG, "Setting IOUT_OC_WARN_LIMIT: %.2fA", tps546_config.TPS546_INIT_IOUT_OC_WARN_LIMIT);
|
||||
smb_write_word(PMBUS_IOUT_OC_WARN_LIMIT, float_2_slinear11(tps546_config.TPS546_INIT_IOUT_OC_WARN_LIMIT));
|
||||
|
||||
ESP_LOGI(TAG, "Setting IOUT_OC_FAULT_LIMIT: %.2fA", tps546_config.TPS546_INIT_IOUT_OC_FAULT_LIMIT);
|
||||
smb_write_word(PMBUS_IOUT_OC_FAULT_LIMIT, float_2_slinear11(tps546_config.TPS546_INIT_IOUT_OC_FAULT_LIMIT));
|
||||
|
||||
ESP_LOGI(TAG, "Setting IOUT_OC_FAULT_RESPONSE: %02x", TPS546_INIT_IOUT_OC_FAULT_RESPONSE);
|
||||
smb_write_byte(PMBUS_IOUT_OC_FAULT_RESPONSE, TPS546_INIT_IOUT_OC_FAULT_RESPONSE);
|
||||
|
||||
/* temperature */
|
||||
ESP_LOGI(TAG, "Setting TEMPERATURE");
|
||||
ESP_LOGI(TAG, "OT_WARN_LIMIT: %d", TPS546_INIT_OT_WARN_LIMIT);
|
||||
ESP_LOGI(TAG, "----- TEMPERATURE");
|
||||
ESP_LOGI(TAG, "Setting OT_WARN_LIMIT: %dC", TPS546_INIT_OT_WARN_LIMIT);
|
||||
smb_write_word(PMBUS_OT_WARN_LIMIT, int_2_slinear11(TPS546_INIT_OT_WARN_LIMIT));
|
||||
ESP_LOGI(TAG, "OT_FAULT_LIMIT: %d", TPS546_INIT_OT_FAULT_LIMIT);
|
||||
ESP_LOGI(TAG, "Setting OT_FAULT_LIMIT: %dC", TPS546_INIT_OT_FAULT_LIMIT);
|
||||
smb_write_word(PMBUS_OT_FAULT_LIMIT, int_2_slinear11(TPS546_INIT_OT_FAULT_LIMIT));
|
||||
ESP_LOGI(TAG, "OT_FAULT_RESPONSE: %02x", TPS546_INIT_OT_FAULT_RESPONSE);
|
||||
ESP_LOGI(TAG, "Setting OT_FAULT_RESPONSE: %02x", TPS546_INIT_OT_FAULT_RESPONSE);
|
||||
smb_write_byte(PMBUS_OT_FAULT_RESPONSE, TPS546_INIT_OT_FAULT_RESPONSE);
|
||||
|
||||
/* timing */
|
||||
ESP_LOGI(TAG, "Setting TIMING");
|
||||
ESP_LOGI(TAG, "TON_DELAY: %d", TPS546_INIT_TON_DELAY);
|
||||
ESP_LOGI(TAG, "----- TIMING");
|
||||
ESP_LOGI(TAG, "Setting TON_DELAY: %dms", TPS546_INIT_TON_DELAY);
|
||||
smb_write_word(PMBUS_TON_DELAY, int_2_slinear11(TPS546_INIT_TON_DELAY));
|
||||
ESP_LOGI(TAG, "TON_RISE: %d", TPS546_INIT_TON_RISE);
|
||||
ESP_LOGI(TAG, "Setting TON_RISE: %dms", TPS546_INIT_TON_RISE);
|
||||
smb_write_word(PMBUS_TON_RISE, int_2_slinear11(TPS546_INIT_TON_RISE));
|
||||
ESP_LOGI(TAG, "TON_MAX_FAULT_LIMIT: %d", TPS546_INIT_TON_MAX_FAULT_LIMIT);
|
||||
ESP_LOGI(TAG, "Setting TON_MAX_FAULT_LIMIT: %dms", TPS546_INIT_TON_MAX_FAULT_LIMIT);
|
||||
smb_write_word(PMBUS_TON_MAX_FAULT_LIMIT, int_2_slinear11(TPS546_INIT_TON_MAX_FAULT_LIMIT));
|
||||
ESP_LOGI(TAG, "TON_MAX_FAULT_RESPONSE: %02x", TPS546_INIT_TON_MAX_FAULT_RESPONSE);
|
||||
ESP_LOGI(TAG, "Setting TON_MAX_FAULT_RESPONSE: %02x", TPS546_INIT_TON_MAX_FAULT_RESPONSE);
|
||||
smb_write_byte(PMBUS_TON_MAX_FAULT_RESPONSE, TPS546_INIT_TON_MAX_FAULT_RESPONSE);
|
||||
ESP_LOGI(TAG, "TOFF_DELAY: %d", TPS546_INIT_TOFF_DELAY);
|
||||
ESP_LOGI(TAG, "Setting TOFF_DELAY: %dms", TPS546_INIT_TOFF_DELAY);
|
||||
smb_write_word(PMBUS_TOFF_DELAY, int_2_slinear11(TPS546_INIT_TOFF_DELAY));
|
||||
ESP_LOGI(TAG, "TOFF_FALL: %d", TPS546_INIT_TOFF_FALL);
|
||||
ESP_LOGI(TAG, "Setting TOFF_FALL: %dms", TPS546_INIT_TOFF_FALL);
|
||||
smb_write_word(PMBUS_TOFF_FALL, int_2_slinear11(TPS546_INIT_TOFF_FALL));
|
||||
|
||||
/* Compensation config */
|
||||
@ -549,11 +622,11 @@ void TPS546_write_entire_config(void)
|
||||
smb_write_word(PMBUS_PIN_DETECT_OVERRIDE, INIT_PIN_DETECT_OVERRIDE);
|
||||
|
||||
/* TODO write new MFR_REVISION number to reflect these parameters */
|
||||
ESP_LOGI(TAG, "Writing MFR ID");
|
||||
ESP_LOGI(TAG, "Setting MFR ID");
|
||||
smb_write_block(PMBUS_MFR_ID, MFR_ID, 3);
|
||||
ESP_LOGI(TAG, "Writing MFR MODEL");
|
||||
ESP_LOGI(TAG, "Setting MFR MODEL");
|
||||
smb_write_block(PMBUS_MFR_ID, MFR_MODEL, 3);
|
||||
ESP_LOGI(TAG, "Writing MFR REVISION");
|
||||
ESP_LOGI(TAG, "Setting MFR REVISION");
|
||||
smb_write_block(PMBUS_MFR_ID, MFR_REVISION, 3);
|
||||
|
||||
/*
|
||||
@ -659,27 +732,123 @@ float TPS546_get_vout(void)
|
||||
}
|
||||
}
|
||||
|
||||
void TPS546_print_status(void) {
|
||||
uint16_t u16_value;
|
||||
esp_err_t TPS546_check_status(uint16_t *status) {
|
||||
|
||||
if (smb_read_word(PMBUS_STATUS_WORD, status) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Could not read STATUS_WORD");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t TPS546_parse_status(uint16_t status) {
|
||||
uint8_t u8_value;
|
||||
|
||||
if (smb_read_word(PMBUS_STATUS_WORD, &u16_value) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Could not read STATUS_WORD");
|
||||
if (status & TPS546_STATUS_BUSY) {
|
||||
ESP_LOGI(TAG, "TPS546 is busy");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
if (status & TPS546_STATUS_OFF) {
|
||||
ESP_LOGI(TAG, "TPS546 is off");
|
||||
}
|
||||
|
||||
if (status & TPS546_STATUS_VOUT_OV) {
|
||||
ESP_LOGI(TAG, "TPS546 VOUT is out of range");
|
||||
}
|
||||
|
||||
if (status & TPS546_STATUS_IOUT_OC) {
|
||||
ESP_LOGI(TAG, "TPS546 IOUT is out of range");
|
||||
}
|
||||
|
||||
if (status & TPS546_STATUS_VIN_UV) {
|
||||
ESP_LOGI(TAG, "TPS546 VIN is out of range");
|
||||
}
|
||||
|
||||
if (status & TPS546_STATUS_TEMP) {
|
||||
ESP_LOGI(TAG, "TPS546 TEMP Status Error");
|
||||
//the host should check STATUS_TEMPERATURE for more information.
|
||||
if (smb_read_byte(PMBUS_STATUS_TEMPERATURE, &u8_value) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Could not read STATUS_TEMPERATURE");
|
||||
} else {
|
||||
ESP_LOGI(TAG, "TPS546 Temperature Status: %02X", u8_value);
|
||||
}
|
||||
}
|
||||
|
||||
if (status & TPS546_STATUS_CML) {
|
||||
ESP_LOGI(TAG, "TPS546 CML Status Error");
|
||||
//the host should check STATUS_CML for more information.
|
||||
if (smb_read_byte(PMBUS_STATUS_CML, &u8_value) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Could not read STATUS_CML");
|
||||
} else {
|
||||
ESP_LOGI(TAG, "TPS546 CML Status: %02X", u8_value);
|
||||
}
|
||||
}
|
||||
|
||||
if (status & TPS546_STATUS_NONE) {
|
||||
ESP_LOGI(TAG, "TPS546 Status Word Error");
|
||||
//The host should check the STATUS_WORD for more information.
|
||||
} else {
|
||||
ESP_LOGI(TAG, "TPS546 Status: %04X", u16_value);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
if (smb_read_byte(PMBUS_STATUS_VOUT, &u8_value) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Could not read STATUS_VOUT");
|
||||
} else {
|
||||
ESP_LOGI(TAG, "TPS546 VOUT Status: %02X", u8_value);
|
||||
//STATUS_WORD bits
|
||||
|
||||
if (status & TPS546_STATUS_VOUT) {
|
||||
ESP_LOGI(TAG, "TPS546 VOUT Status Error");
|
||||
//the host should check STATUS_VOUT for more information.
|
||||
if (smb_read_byte(PMBUS_STATUS_VOUT, &u8_value) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Could not read STATUS_VOUT");
|
||||
} else {
|
||||
ESP_LOGI(TAG, "TPS546 VOUT Status: %02X", u8_value);
|
||||
}
|
||||
}
|
||||
|
||||
if (smb_read_byte(PMBUS_STATUS_INPUT, &u8_value) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Could not read STATUS_INPUT");
|
||||
} else {
|
||||
ESP_LOGI(TAG, "TPS546 INPUT Status: %02X", u8_value);
|
||||
if (status & TPS546_STATUS_IOUT) {
|
||||
ESP_LOGI(TAG, "TPS546 IOUT Status Error");
|
||||
//the host should check STATUS_IOUT for more information.
|
||||
if (smb_read_byte(PMBUS_STATUS_IOUT, &u8_value) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Could not read STATUS_IOUT");
|
||||
} else {
|
||||
ESP_LOGI(TAG, "TPS546 IOUT Status: %02X", u8_value);
|
||||
}
|
||||
}
|
||||
|
||||
if (status & TPS546_STATUS_INPUT) {
|
||||
ESP_LOGI(TAG, "TPS546 INPUT Status Error");
|
||||
//the host should check STATUS_INPUT for more information.
|
||||
if (smb_read_byte(PMBUS_STATUS_INPUT, &u8_value) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Could not read STATUS_INPUT");
|
||||
} else {
|
||||
ESP_LOGI(TAG, "TPS546 INPUT Status: %02X", u8_value);
|
||||
}
|
||||
}
|
||||
|
||||
if (status & TPS546_STATUS_MFR) {
|
||||
ESP_LOGI(TAG, "TPS546 MFR_SPECIFIC Status Error");
|
||||
//the host should check STATUS_MFR_SPECIFIC for more information.
|
||||
if (smb_read_byte(PMBUS_STATUS_MFR_SPECIFIC, &u8_value) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Could not read STATUS_MFR_SPECIFIC");
|
||||
} else {
|
||||
ESP_LOGI(TAG, "TPS546 MFR_SPECIFIC Status: %02X", u8_value);
|
||||
}
|
||||
}
|
||||
|
||||
if (status & TPS546_STATUS_PGOOD) {
|
||||
ESP_LOGI(TAG, "TPS546 PGOOD Status Error");
|
||||
}
|
||||
|
||||
if (status & TPS546_STATUS_OTHER) {
|
||||
ESP_LOGI(TAG, "TPS546 OTHER Status Error");
|
||||
//the host should check STATUS_OTHER for more information.
|
||||
if (smb_read_byte(PMBUS_STATUS_OTHER, &u8_value) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Could not read STATUS_OTHER");
|
||||
} else {
|
||||
ESP_LOGI(TAG, "TPS546 OTHER Status: %02X", u8_value);
|
||||
}
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -690,24 +859,26 @@ void TPS546_print_status(void) {
|
||||
* send a 0 to turn off the output
|
||||
* @param volts The desired output voltage
|
||||
**/
|
||||
void TPS546_set_vout(float volts)
|
||||
{
|
||||
esp_err_t TPS546_set_vout(float volts) {
|
||||
uint16_t value;
|
||||
|
||||
if (volts == 0) {
|
||||
/* turn off output */
|
||||
if (smb_write_byte(PMBUS_OPERATION, OPERATION_OFF) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Could not turn off Vout");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
} else {
|
||||
/* make sure we're in range */
|
||||
if ((volts < TPS546_INIT_VOUT_MIN) || (volts > TPS546_INIT_VOUT_MAX)) {
|
||||
if ((volts < tps546_config.TPS546_INIT_VOUT_MIN) || (volts > tps546_config.TPS546_INIT_VOUT_MAX)) {
|
||||
ESP_LOGE(TAG, "Voltage requested (%f V) is out of range", volts);
|
||||
return ESP_FAIL;
|
||||
} else {
|
||||
/* set the output voltage */
|
||||
value = float_2_ulinear16(volts);
|
||||
if (smb_write_word(PMBUS_VOUT_COMMAND, value) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Could not set Vout to %1.2f V", volts);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Vout changed to %1.2f V", volts);
|
||||
@ -715,70 +886,88 @@ void TPS546_set_vout(float volts)
|
||||
/* turn on output */
|
||||
if (smb_write_byte(PMBUS_OPERATION, OPERATION_ON) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Could not turn on Vout");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void TPS546_show_voltage_settings(void)
|
||||
{
|
||||
uint16_t u16_value;
|
||||
uint8_t u8_value;
|
||||
float f_value;
|
||||
|
||||
ESP_LOGI(TAG, "-----------VOLTAGE---------------------");
|
||||
/* VIN_ON SLINEAR11 */
|
||||
smb_read_word(PMBUS_VIN_ON, &u16_value);
|
||||
f_value = slinear11_2_float(u16_value);
|
||||
ESP_LOGI(TAG, "VIN ON set to: %.2f", f_value);
|
||||
ESP_LOGI(TAG, "read VIN_ON: %.2fV", f_value);
|
||||
|
||||
/* VIN_OFF SLINEAR11 */
|
||||
smb_read_word(PMBUS_VIN_OFF, &u16_value);
|
||||
f_value = slinear11_2_float(u16_value);
|
||||
ESP_LOGI(TAG, "VIN OFF set to: %.2f", f_value);
|
||||
ESP_LOGI(TAG, "read VIN_OFF: %.2fV", f_value);
|
||||
|
||||
/* VIN_OV_FAULT_LIMIT SLINEAR11 */
|
||||
smb_read_word(PMBUS_VIN_OV_FAULT_LIMIT, &u16_value);
|
||||
f_value = slinear11_2_float(u16_value);
|
||||
ESP_LOGI(TAG, "read VIN_OV_FAULT_LIMIT: %.2fV", f_value);
|
||||
|
||||
/* VIN_UV_WARN_LIMIT SLINEAR11 */
|
||||
smb_read_word(PMBUS_VIN_UV_WARN_LIMIT, &u16_value);
|
||||
f_value = slinear11_2_float(u16_value);
|
||||
ESP_LOGI(TAG, "read VIN_UV_WARN_LIMIT: %.2fV", f_value);
|
||||
|
||||
/* VIN_OV_FAULT_RESPONSE */
|
||||
smb_read_byte(PMBUS_VIN_OV_FAULT_RESPONSE, &u8_value);
|
||||
ESP_LOGI(TAG, "read VIN_OV_FAULT_RESPONSE: %02X", u8_value);
|
||||
|
||||
/* VOUT_MAX */
|
||||
smb_read_word(PMBUS_VOUT_MAX, &u16_value);
|
||||
f_value = ulinear16_2_float(u16_value);
|
||||
ESP_LOGI(TAG, "Vout Max set to: %.2f V", f_value);
|
||||
ESP_LOGI(TAG, "read VOUT_MAX: %.2fV", f_value);
|
||||
|
||||
/* VOUT_OV_FAULT_LIMIT */
|
||||
smb_read_word(PMBUS_VOUT_OV_FAULT_LIMIT, &u16_value);
|
||||
f_value = ulinear16_2_float(u16_value);
|
||||
ESP_LOGI(TAG, "Vout OV Fault Limit: %.2f V", f_value);
|
||||
ESP_LOGI(TAG, "read VOUT_OV_FAULT_LIMIT: %.2fV", f_value * tps546_config.TPS546_INIT_VOUT_COMMAND);
|
||||
|
||||
/* VOUT_OV_WARN_LIMIT */
|
||||
smb_read_word(PMBUS_VOUT_OV_WARN_LIMIT, &u16_value);
|
||||
f_value = ulinear16_2_float(u16_value);
|
||||
ESP_LOGI(TAG, "Vout OV Warn Limit: %.2f V", f_value);
|
||||
ESP_LOGI(TAG, "read VOUT_OV_WARN_LIMIT: %.2fV", f_value * tps546_config.TPS546_INIT_VOUT_COMMAND);
|
||||
|
||||
/* VOUT_MARGIN_HIGH */
|
||||
smb_read_word(PMBUS_VOUT_MARGIN_HIGH, &u16_value);
|
||||
f_value = ulinear16_2_float(u16_value);
|
||||
ESP_LOGI(TAG, "Vout Margin HIGH: %.2f V", f_value);
|
||||
ESP_LOGI(TAG, "read VOUT_MARGIN_HIGH: %.2fV", f_value * tps546_config.TPS546_INIT_VOUT_COMMAND);
|
||||
|
||||
/* --- VOUT_COMMAND --- */
|
||||
smb_read_word(PMBUS_VOUT_COMMAND, &u16_value);
|
||||
f_value = ulinear16_2_float(u16_value);
|
||||
ESP_LOGI(TAG, "Vout set to: %.2f V", f_value);
|
||||
ESP_LOGI(TAG, "read VOUT_COMMAND: %.2fV", f_value);
|
||||
|
||||
/* VOUT_MARGIN_LOW */
|
||||
smb_read_word(PMBUS_VOUT_MARGIN_LOW, &u16_value);
|
||||
f_value = ulinear16_2_float(u16_value);
|
||||
ESP_LOGI(TAG, "Vout Margin LOW: %.2f V", f_value);
|
||||
ESP_LOGI(TAG, "read VOUT_MARGIN_LOW: %.2fV", f_value * tps546_config.TPS546_INIT_VOUT_COMMAND);
|
||||
|
||||
/* VOUT_UV_WARN_LIMIT */
|
||||
smb_read_word(PMBUS_VOUT_UV_WARN_LIMIT, &u16_value);
|
||||
f_value = ulinear16_2_float(u16_value);
|
||||
ESP_LOGI(TAG, "Vout UV Warn Limit: %.2f V", f_value);
|
||||
ESP_LOGI(TAG, "read VOUT_UV_WARN_LIMIT: %.2fV", f_value * tps546_config.TPS546_INIT_VOUT_COMMAND);
|
||||
|
||||
/* VOUT_UV_FAULT_LIMIT */
|
||||
smb_read_word(PMBUS_VOUT_UV_FAULT_LIMIT, &u16_value);
|
||||
f_value = ulinear16_2_float(u16_value);
|
||||
ESP_LOGI(TAG, "Vout UV Fault Limit: %.2f V", f_value);
|
||||
ESP_LOGI(TAG, "read VOUT_UV_FAULT_LIMIT: %.2fV", f_value * tps546_config.TPS546_INIT_VOUT_COMMAND);
|
||||
|
||||
/* VOUT_MIN */
|
||||
smb_read_word(PMBUS_VOUT_MIN, &u16_value);
|
||||
f_value = ulinear16_2_float(u16_value);
|
||||
ESP_LOGI(TAG, "Vout Min set to: %.2f V", f_value);
|
||||
ESP_LOGI(TAG, "read VOUT_MIN: %.2f V", f_value);
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
#ifndef TPS546_H_
|
||||
#define TPS546_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <esp_err.h>
|
||||
|
||||
#define TPS546_I2CADDR 0x24 //< TPS546 i2c address
|
||||
#define TPS546_MANUFACTURER_ID 0xFE //< Manufacturer ID
|
||||
#define TPS546_REVISION 0xFF //< Chip revision
|
||||
@ -14,30 +17,49 @@
|
||||
#define OPERATION_OFF 0x00
|
||||
#define OPERATION_ON 0x80
|
||||
|
||||
#define TPS546_INIT_PHASE 0x00 /* phase */
|
||||
|
||||
#define TPS546_INIT_FREQUENCY 650 /* KHz */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* vin voltage */
|
||||
float TPS546_INIT_VIN_ON; /* V */
|
||||
float TPS546_INIT_VIN_OFF; /* V */
|
||||
float TPS546_INIT_VIN_UV_WARN_LIMIT; /* V */
|
||||
float TPS546_INIT_VIN_OV_FAULT_LIMIT; /* V */
|
||||
/* vout voltage */
|
||||
float TPS546_INIT_SCALE_LOOP; /* Voltage Scale factor */
|
||||
float TPS546_INIT_VOUT_MIN; /* V */
|
||||
float TPS546_INIT_VOUT_MAX; /* V */
|
||||
float TPS546_INIT_VOUT_COMMAND; /* V absolute value */
|
||||
/* iout current */
|
||||
float TPS546_INIT_IOUT_OC_WARN_LIMIT; /* A */
|
||||
float TPS546_INIT_IOUT_OC_FAULT_LIMIT; /* A */
|
||||
} TPS546_CONFIG;
|
||||
|
||||
/* vin voltage */
|
||||
#define TPS546_INIT_VIN_ON 4.8 /* V */
|
||||
#define TPS546_INIT_VIN_OFF 4.5 /* V */
|
||||
#define TPS546_INIT_VIN_UV_WARN_LIMIT 5.8 /* V */
|
||||
#define TPS546_INIT_VIN_OV_FAULT_LIMIT 6.0 /* V */
|
||||
// #define TPS546_INIT_VIN_ON 11.0 /* V */
|
||||
// #define TPS546_INIT_VIN_OFF 10.5 /* V */
|
||||
// #define TPS546_INIT_VIN_UV_WARN_LIMIT 14.0 /* V */
|
||||
// #define TPS546_INIT_VIN_OV_FAULT_LIMIT 15.0 /* V */
|
||||
#define TPS546_INIT_VIN_OV_FAULT_RESPONSE 0xB7 /* retry 6 times */
|
||||
|
||||
/* vout voltage */
|
||||
#define TPS546_INIT_SCALE_LOOP 0.25 /* Voltage Scale factor */
|
||||
#define TPS546_INIT_VOUT_MAX 3 /* V */
|
||||
//#define TPS546_INIT_SCALE_LOOP 0.25 /* Voltage Scale factor */
|
||||
//#define TPS546_INIT_VOUT_MAX 3 /* V */
|
||||
#define TPS546_INIT_VOUT_OV_FAULT_LIMIT 1.25 /* %/100 above VOUT_COMMAND */
|
||||
#define TPS546_INIT_VOUT_OV_WARN_LIMIT 1.1 /* %/100 above VOUT_COMMAND */
|
||||
#define TPS546_INIT_VOUT_MARGIN_HIGH 1.1 /* %/100 above VOUT */
|
||||
#define TPS546_INIT_VOUT_COMMAND 1.2 /* V absolute value */
|
||||
//#define TPS546_INIT_VOUT_COMMAND 1.2 /* V absolute value */
|
||||
#define TPS546_INIT_VOUT_MARGIN_LOW 0.90 /* %/100 below VOUT */
|
||||
#define TPS546_INIT_VOUT_UV_WARN_LIMIT 0.90 /* %/100 below VOUT_COMMAND */
|
||||
#define TPS546_INIT_VOUT_UV_FAULT_LIMIT 0.75 /* %/100 below VOUT_COMMAND */
|
||||
#define TPS546_INIT_VOUT_MIN 1 /* v */
|
||||
//#define TPS546_INIT_VOUT_MIN 1 /* v */
|
||||
|
||||
/* iout current */
|
||||
#define TPS546_INIT_IOUT_OC_WARN_LIMIT 25.00 /* A */
|
||||
#define TPS546_INIT_IOUT_OC_FAULT_LIMIT 30.00 /* A */
|
||||
// #define TPS546_INIT_IOUT_OC_WARN_LIMIT 50.00 /* A */
|
||||
// #define TPS546_INIT_IOUT_OC_FAULT_LIMIT 55.00 /* A */
|
||||
#define TPS546_INIT_IOUT_OC_FAULT_RESPONSE 0xC0 /* shut down, no retries */
|
||||
|
||||
/* temperature */
|
||||
@ -54,9 +76,9 @@
|
||||
#define TPS546_INIT_TOFF_DELAY 0
|
||||
#define TPS546_INIT_TOFF_FALL 0
|
||||
|
||||
#define INIT_STACK_CONFIG 0x0000
|
||||
#define INIT_SYNC_CONFIG 0x0010
|
||||
#define INIT_PIN_DETECT_OVERRIDE 0x0000
|
||||
#define INIT_STACK_CONFIG 0x0001 //One-Slave, 2-phase
|
||||
#define INIT_SYNC_CONFIG 0x00D0 //Enable Auto Detect SYNC
|
||||
#define INIT_PIN_DETECT_OVERRIDE 0xFFFF //use pin values
|
||||
|
||||
/*-------------------------*/
|
||||
|
||||
@ -67,9 +89,26 @@
|
||||
#define ON_OFF_CONFIG_POLARITY 0x00 // turn off POLARITY bit
|
||||
#define ON_OFF_CONFIG_DELAY 0x00 // turn off DELAY bit
|
||||
|
||||
//// STATUS_WORD Offsets
|
||||
#define TPS546_STATUS_VOUT 0x8000 //bit 15
|
||||
#define TPS546_STATUS_IOUT 0x4000
|
||||
#define TPS546_STATUS_INPUT 0x2000
|
||||
#define TPS546_STATUS_MFR 0x1000
|
||||
#define TPS546_STATUS_PGOOD 0x0800
|
||||
#define TPS546_STATUS_OTHER 0x0200
|
||||
|
||||
#define TPS546_STATUS_BUSY 0x0080
|
||||
#define TPS546_STATUS_OFF 0x0040
|
||||
#define TPS546_STATUS_VOUT_OV 0x0020
|
||||
#define TPS546_STATUS_IOUT_OC 0x0010
|
||||
#define TPS546_STATUS_VIN_UV 0x0008
|
||||
#define TPS546_STATUS_TEMP 0x0004
|
||||
#define TPS546_STATUS_CML 0x0002
|
||||
#define TPS546_STATUS_NONE 0x0001
|
||||
|
||||
|
||||
/* public functions */
|
||||
int TPS546_init(void);
|
||||
esp_err_t TPS546_init(TPS546_CONFIG config);
|
||||
void TPS546_read_mfr_info(uint8_t *);
|
||||
void TPS546_set_mfr_info(void);
|
||||
void TPS546_write_entire_config(void);
|
||||
@ -79,8 +118,12 @@ int TPS546_get_temperature(void);
|
||||
float TPS546_get_vin(void);
|
||||
float TPS546_get_iout(void);
|
||||
float TPS546_get_vout(void);
|
||||
void TPS546_set_vout(float volts);
|
||||
esp_err_t TPS546_set_vout(float volts);
|
||||
void TPS546_show_voltage_settings(void);
|
||||
void TPS546_print_status(void);
|
||||
|
||||
esp_err_t TPS546_check_status(uint16_t *);
|
||||
esp_err_t TPS546_parse_status(uint16_t status);
|
||||
esp_err_t TPS546_clear_faults(void);
|
||||
|
||||
#endif /* TPS546_H_ */
|
147
main/power/power.c
Normal file
147
main/power/power.c
Normal file
@ -0,0 +1,147 @@
|
||||
#include "TPS546.h"
|
||||
#include "INA260.h"
|
||||
#include "DS4432U.h"
|
||||
|
||||
#include "power.h"
|
||||
#include "vcore.h"
|
||||
|
||||
#define GPIO_ASIC_ENABLE CONFIG_GPIO_ASIC_ENABLE
|
||||
|
||||
#define SUPRA_POWER_OFFSET 5 //Watts
|
||||
#define GAMMA_POWER_OFFSET 5 //Watts
|
||||
#define GAMMATURBO_POWER_OFFSET 5 //Watts
|
||||
|
||||
esp_err_t Power_disable(GlobalState * GLOBAL_STATE) {
|
||||
|
||||
switch (GLOBAL_STATE->device_model) {
|
||||
case DEVICE_MAX:
|
||||
case DEVICE_ULTRA:
|
||||
case DEVICE_SUPRA:
|
||||
if (GLOBAL_STATE->board_version >= 402 && GLOBAL_STATE->board_version <= 499) {
|
||||
// Turn off core voltage
|
||||
VCORE_set_voltage(0.0, GLOBAL_STATE);
|
||||
} else if (GLOBAL_STATE->board_version == 202 || GLOBAL_STATE->board_version == 203 || GLOBAL_STATE->board_version == 204) {
|
||||
gpio_set_level(GPIO_ASIC_ENABLE, 1);
|
||||
}
|
||||
break;
|
||||
case DEVICE_GAMMA:
|
||||
case DEVICE_GAMMATURBO:
|
||||
// Turn off core voltage
|
||||
VCORE_set_voltage(0.0, GLOBAL_STATE);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
return ESP_OK;
|
||||
|
||||
}
|
||||
|
||||
float Power_get_current(GlobalState * GLOBAL_STATE) {
|
||||
float current = 0.0;
|
||||
|
||||
switch (GLOBAL_STATE->device_model) {
|
||||
case DEVICE_MAX:
|
||||
case DEVICE_ULTRA:
|
||||
case DEVICE_SUPRA:
|
||||
if (GLOBAL_STATE->board_version >= 402 && GLOBAL_STATE->board_version <= 499) {
|
||||
current = TPS546_get_iout() * 1000.0;
|
||||
} else {
|
||||
if (INA260_installed() == true) {
|
||||
current = INA260_read_current();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DEVICE_GAMMA:
|
||||
case DEVICE_GAMMATURBO:
|
||||
current = TPS546_get_iout() * 1000.0;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
float Power_get_power(GlobalState * GLOBAL_STATE) {
|
||||
float power = 0.0;
|
||||
float current = 0.0;
|
||||
|
||||
switch (GLOBAL_STATE->device_model) {
|
||||
case DEVICE_MAX:
|
||||
case DEVICE_ULTRA:
|
||||
case DEVICE_SUPRA:
|
||||
if (GLOBAL_STATE->board_version >= 402 && GLOBAL_STATE->board_version <= 499) {
|
||||
current = TPS546_get_iout() * 1000.0;
|
||||
// calculate regulator power (in milliwatts)
|
||||
power = (TPS546_get_vout() * current) / 1000.0;
|
||||
// The power reading from the TPS546 is only it's output power. So the rest of the Bitaxe power is not accounted for.
|
||||
power += SUPRA_POWER_OFFSET; // Add offset for the rest of the Bitaxe power. TODO: this better.
|
||||
} else {
|
||||
if (INA260_installed() == true) {
|
||||
power = INA260_read_power() / 1000.0;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case DEVICE_GAMMA:
|
||||
case DEVICE_GAMMATURBO:
|
||||
current = TPS546_get_iout() * 1000.0;
|
||||
// calculate regulator power (in milliwatts)
|
||||
power = (TPS546_get_vout() * current) / 1000.0;
|
||||
// The power reading from the TPS546 is only it's output power. So the rest of the Bitaxe power is not accounted for.
|
||||
power += GAMMATURBO_POWER_OFFSET; // Add offset for the rest of the Bitaxe power. TODO: this better.
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
return power;
|
||||
}
|
||||
|
||||
|
||||
float Power_get_input_voltage(GlobalState * GLOBAL_STATE) {
|
||||
|
||||
switch (GLOBAL_STATE->device_model) {
|
||||
case DEVICE_MAX:
|
||||
case DEVICE_ULTRA:
|
||||
case DEVICE_SUPRA:
|
||||
if (GLOBAL_STATE->board_version >= 402 && GLOBAL_STATE->board_version <= 499) {
|
||||
return TPS546_get_vin() * 1000.0;
|
||||
} else {
|
||||
if (INA260_installed() == true) {
|
||||
return INA260_read_voltage();
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case DEVICE_GAMMA:
|
||||
case DEVICE_GAMMATURBO:
|
||||
return TPS546_get_vin() * 1000.0;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
float Power_get_vreg_temp(GlobalState * GLOBAL_STATE) {
|
||||
|
||||
switch (GLOBAL_STATE->device_model) {
|
||||
case DEVICE_MAX:
|
||||
case DEVICE_ULTRA:
|
||||
case DEVICE_SUPRA:
|
||||
if (GLOBAL_STATE->board_version >= 402 && GLOBAL_STATE->board_version <= 499) {
|
||||
return TPS546_get_temperature();
|
||||
} else {
|
||||
if (INA260_installed() == true) {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case DEVICE_GAMMA:
|
||||
case DEVICE_GAMMATURBO:
|
||||
return TPS546_get_temperature();
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
15
main/power/power.h
Normal file
15
main/power/power.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef POWER_H
|
||||
#define POWER_H
|
||||
|
||||
#include <esp_err.h>
|
||||
#include "global_state.h"
|
||||
|
||||
|
||||
esp_err_t Power_disable(GlobalState * GLOBAL_STATE);
|
||||
|
||||
float Power_get_current(GlobalState * GLOBAL_STATE);
|
||||
float Power_get_power(GlobalState * GLOBAL_STATE);
|
||||
float Power_get_input_voltage(GlobalState * GLOBAL_STATE);
|
||||
float Power_get_vreg_temp(GlobalState * GLOBAL_STATE);
|
||||
|
||||
#endif // POWER_H
|
146
main/power/vcore.c
Normal file
146
main/power/vcore.c
Normal file
@ -0,0 +1,146 @@
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "vcore.h"
|
||||
#include "adc.h"
|
||||
#include "DS4432U.h"
|
||||
#include "TPS546.h"
|
||||
#include "INA260.h"
|
||||
|
||||
#define GPIO_ASIC_ENABLE CONFIG_GPIO_ASIC_ENABLE
|
||||
#define GPIO_ASIC_RESET CONFIG_GPIO_ASIC_RESET
|
||||
#define GPIO_PLUG_SENSE CONFIG_GPIO_PLUG_SENSE
|
||||
|
||||
static TPS546_CONFIG TPS546_CONFIG_GAMMATURBO = {
|
||||
/* vin voltage */
|
||||
.TPS546_INIT_VIN_ON = 11.0,
|
||||
.TPS546_INIT_VIN_OFF = 10.5,
|
||||
.TPS546_INIT_VIN_UV_WARN_LIMIT = 11.0,
|
||||
.TPS546_INIT_VIN_OV_FAULT_LIMIT = 14.0,
|
||||
/* vout voltage */
|
||||
.TPS546_INIT_SCALE_LOOP = 0.25,
|
||||
.TPS546_INIT_VOUT_MIN = 1,
|
||||
.TPS546_INIT_VOUT_MAX = 3,
|
||||
.TPS546_INIT_VOUT_COMMAND = 1.2,
|
||||
/* iout current */
|
||||
.TPS546_INIT_IOUT_OC_WARN_LIMIT = 50.00, /* A */
|
||||
.TPS546_INIT_IOUT_OC_FAULT_LIMIT = 55.00 /* A */
|
||||
};
|
||||
|
||||
static TPS546_CONFIG TPS546_CONFIG_GAMMA = {
|
||||
/* vin voltage */
|
||||
.TPS546_INIT_VIN_ON = 4.8,
|
||||
.TPS546_INIT_VIN_OFF = 4.5,
|
||||
.TPS546_INIT_VIN_UV_WARN_LIMIT = 0, //Set to 0 to ignore. TI Bug in this register
|
||||
.TPS546_INIT_VIN_OV_FAULT_LIMIT = 5.5,
|
||||
/* vout voltage */
|
||||
.TPS546_INIT_SCALE_LOOP = 0.25,
|
||||
.TPS546_INIT_VOUT_MIN = 1,
|
||||
.TPS546_INIT_VOUT_MAX = 2,
|
||||
.TPS546_INIT_VOUT_COMMAND = 1.2,
|
||||
/* iout current */
|
||||
.TPS546_INIT_IOUT_OC_WARN_LIMIT = 25.00, /* A */
|
||||
.TPS546_INIT_IOUT_OC_FAULT_LIMIT = 30.00 /* A */
|
||||
};
|
||||
|
||||
static const char *TAG = "vcore.c";
|
||||
|
||||
esp_err_t VCORE_init(GlobalState * GLOBAL_STATE) {
|
||||
switch (GLOBAL_STATE->device_model) {
|
||||
case DEVICE_MAX:
|
||||
case DEVICE_ULTRA:
|
||||
case DEVICE_SUPRA:
|
||||
if (GLOBAL_STATE->board_version >= 402 && GLOBAL_STATE->board_version <= 499) {
|
||||
if (TPS546_init(TPS546_CONFIG_GAMMA) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "TPS546 init failed!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
} else {
|
||||
ESP_RETURN_ON_ERROR(DS4432U_init(), TAG, "DS4432 init failed!");
|
||||
ESP_RETURN_ON_ERROR(INA260_init(), TAG, "INA260 init failed!");
|
||||
}
|
||||
break;
|
||||
case DEVICE_GAMMA:
|
||||
ESP_RETURN_ON_ERROR(TPS546_init(TPS546_CONFIG_GAMMA), TAG, "TPS546 init failed!");
|
||||
break;
|
||||
case DEVICE_GAMMATURBO:
|
||||
ESP_RETURN_ON_ERROR(TPS546_init(TPS546_CONFIG_GAMMATURBO), TAG, "TPS546 init failed!");
|
||||
break;
|
||||
// case DEVICE_HEX:
|
||||
default:
|
||||
}
|
||||
|
||||
//configure plug sense, if present
|
||||
switch (GLOBAL_STATE->device_model) {
|
||||
case DEVICE_MAX:
|
||||
case DEVICE_ULTRA:
|
||||
case DEVICE_SUPRA:
|
||||
if (GLOBAL_STATE->board_version < 402 || GLOBAL_STATE->board_version > 499) {
|
||||
// Configure plug sense pin as input(barrel jack) 1 is plugged in
|
||||
gpio_config_t barrel_jack_conf = {
|
||||
.pin_bit_mask = (1ULL << GPIO_PLUG_SENSE),
|
||||
.mode = GPIO_MODE_INPUT,
|
||||
};
|
||||
gpio_config(&barrel_jack_conf);
|
||||
int barrel_jack_plugged_in = gpio_get_level(GPIO_PLUG_SENSE);
|
||||
|
||||
gpio_set_direction(GPIO_ASIC_ENABLE, GPIO_MODE_OUTPUT);
|
||||
if (barrel_jack_plugged_in == 1 || GLOBAL_STATE->board_version != 204) {
|
||||
// turn ASIC on
|
||||
gpio_set_level(GPIO_ASIC_ENABLE, 0);
|
||||
} else {
|
||||
// turn ASIC off
|
||||
gpio_set_level(GPIO_ASIC_ENABLE, 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DEVICE_GAMMA:
|
||||
case DEVICE_GAMMATURBO:
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t VCORE_set_voltage(float core_voltage, GlobalState * global_state)
|
||||
{
|
||||
switch (global_state->device_model) {
|
||||
case DEVICE_MAX:
|
||||
case DEVICE_ULTRA:
|
||||
case DEVICE_SUPRA:
|
||||
if (global_state->board_version >= 402 && global_state->board_version <= 499) {
|
||||
ESP_LOGI(TAG, "Set ASIC voltage = %.3fV", core_voltage);
|
||||
ESP_RETURN_ON_ERROR(TPS546_set_vout(core_voltage), TAG, "TPS546 set voltage failed!");
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Set ASIC voltage = %.3fV", core_voltage);
|
||||
ESP_RETURN_ON_ERROR(DS4432U_set_voltage(core_voltage), TAG, "DS4432U set voltage failed!");
|
||||
}
|
||||
break;
|
||||
case DEVICE_GAMMA:
|
||||
case DEVICE_GAMMATURBO:
|
||||
ESP_LOGI(TAG, "Set ASIC voltage = %.3fV", core_voltage);
|
||||
ESP_RETURN_ON_ERROR(TPS546_set_vout(core_voltage), TAG, "TPS546 set voltage failed!");
|
||||
break;
|
||||
// case DEVICE_HEX:
|
||||
default:
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
int16_t VCORE_get_voltage_mv(GlobalState * global_state) {
|
||||
|
||||
switch (global_state->device_model) {
|
||||
case DEVICE_MAX:
|
||||
case DEVICE_ULTRA:
|
||||
case DEVICE_SUPRA:
|
||||
case DEVICE_GAMMA:
|
||||
case DEVICE_GAMMATURBO:
|
||||
return ADC_get_vcore();
|
||||
// case DEVICE_HEX:
|
||||
default:
|
||||
}
|
||||
return -1;
|
||||
}
|
@ -5,6 +5,6 @@
|
||||
|
||||
esp_err_t VCORE_init(GlobalState * global_state);
|
||||
esp_err_t VCORE_set_voltage(float core_voltage, GlobalState * global_state);
|
||||
uint16_t VCORE_get_voltage_mv(GlobalState * global_state);
|
||||
int16_t VCORE_get_voltage_mv(GlobalState * global_state);
|
||||
|
||||
#endif /* VCORE_H_ */
|
@ -23,6 +23,8 @@ static lv_obj_t *efficiency_label;
|
||||
static lv_obj_t *difficulty_label;
|
||||
static lv_obj_t *chip_temp_label;
|
||||
|
||||
static lv_obj_t *firmware_update_scr_filename_label;
|
||||
static lv_obj_t *firmware_update_scr_status_label;
|
||||
static lv_obj_t *ip_addr_scr_overheat_label;
|
||||
static lv_obj_t *ip_addr_scr_urls_label;
|
||||
static lv_obj_t *mining_url_scr_urls_label;
|
||||
@ -35,7 +37,7 @@ static lv_obj_t *self_test_finished_label;
|
||||
static double current_hashrate;
|
||||
static float current_power;
|
||||
static uint64_t current_difficulty;
|
||||
static float curreny_chip_temp;
|
||||
static float current_chip_temp;
|
||||
static bool found_block;
|
||||
|
||||
#define SCREEN_UPDATE_MS 500
|
||||
@ -59,7 +61,7 @@ static lv_obj_t * create_scr_self_test() {
|
||||
lv_obj_set_width(self_test_finished_label, LV_HOR_RES);
|
||||
lv_obj_add_flag(self_test_finished_label, LV_OBJ_FLAG_HIDDEN);
|
||||
lv_label_set_long_mode(self_test_finished_label, LV_LABEL_LONG_SCROLL_CIRCULAR);
|
||||
lv_label_set_text(self_test_finished_label, "Self test finished. Press BOOT button for 2 seconds to reset self test status and reboot the device.");
|
||||
lv_label_set_text(self_test_finished_label, "Hold BOOT button for 2 seconds to cancel self test, or press RESET to run again.");
|
||||
|
||||
return scr;
|
||||
}
|
||||
@ -97,7 +99,7 @@ static lv_obj_t * create_scr_invalid_asic(SystemModule * module) {
|
||||
lv_label_set_text(label1, "ASIC MODEL INVALID");
|
||||
|
||||
lv_obj_t *label2 = lv_label_create(scr);
|
||||
lv_label_set_text(label2, "Configuration SSID:");
|
||||
lv_label_set_text(label2, "Wi-Fi (for setup):");
|
||||
|
||||
lv_obj_t *label3 = lv_label_create(scr);
|
||||
lv_label_set_text(label3, module->ap_ssid);
|
||||
@ -113,11 +115,15 @@ static lv_obj_t * create_scr_configure(SystemModule * module) {
|
||||
|
||||
lv_obj_t *label1 = lv_label_create(scr);
|
||||
lv_obj_set_width(label1, LV_HOR_RES);
|
||||
lv_obj_set_style_anim_duration(label1, 15000, LV_PART_MAIN);
|
||||
lv_label_set_long_mode(label1, LV_LABEL_LONG_SCROLL_CIRCULAR);
|
||||
lv_label_set_text(label1, "Welcome to your new Bitaxe! Connect to the configuration Wifi and connect the Bitaxe to your network.");
|
||||
lv_label_set_text(label1, "Welcome to your new Bitaxe! Connect to the configuration Wi-Fi and connect the Bitaxe to your network.");
|
||||
|
||||
// skip a line, it looks nicer this way
|
||||
lv_label_create(scr);
|
||||
|
||||
lv_obj_t *label2 = lv_label_create(scr);
|
||||
lv_label_set_text(label2, "Configuration SSID:");
|
||||
lv_label_set_text(label2, "Wi-Fi (for setup):");
|
||||
|
||||
lv_obj_t *label3 = lv_label_create(scr);
|
||||
lv_label_set_text(label3, module->ap_ssid);
|
||||
@ -125,6 +131,23 @@ static lv_obj_t * create_scr_configure(SystemModule * module) {
|
||||
return scr;
|
||||
}
|
||||
|
||||
static lv_obj_t * create_scr_ota(SystemModule * module) {
|
||||
lv_obj_t * scr = lv_obj_create(NULL);
|
||||
|
||||
lv_obj_set_flex_flow(scr, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_flex_align(scr, LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
|
||||
|
||||
lv_obj_t *label1 = lv_label_create(scr);
|
||||
lv_obj_set_width(label1, LV_HOR_RES);
|
||||
lv_label_set_text(label1, "Firmware update");
|
||||
|
||||
firmware_update_scr_filename_label = lv_label_create(scr);
|
||||
|
||||
firmware_update_scr_status_label = lv_label_create(scr);
|
||||
|
||||
return scr;
|
||||
}
|
||||
|
||||
static lv_obj_t * create_scr_connection(SystemModule * module) {
|
||||
lv_obj_t * scr = lv_obj_create(NULL);
|
||||
|
||||
@ -134,13 +157,13 @@ static lv_obj_t * create_scr_connection(SystemModule * module) {
|
||||
lv_obj_t *label1 = lv_label_create(scr);
|
||||
lv_obj_set_width(label1, LV_HOR_RES);
|
||||
lv_label_set_long_mode(label1, LV_LABEL_LONG_SCROLL_CIRCULAR);
|
||||
lv_label_set_text_fmt(label1, "SSID: %s", module->ssid);
|
||||
lv_label_set_text_fmt(label1, "Wi-Fi: %s", module->ssid);
|
||||
|
||||
wifi_status_label = lv_label_create(scr);
|
||||
lv_label_set_text(wifi_status_label, module->wifi_status);
|
||||
|
||||
lv_obj_t *label3 = lv_label_create(scr);
|
||||
lv_label_set_text(label3, "Configuration SSID:");
|
||||
lv_label_set_text(label3, "Wi-Fi (for setup):");
|
||||
|
||||
lv_obj_t *label4 = lv_label_create(scr);
|
||||
lv_label_set_text(label4, module->ap_ssid);
|
||||
@ -188,16 +211,16 @@ static lv_obj_t * create_scr_stats() {
|
||||
lv_obj_set_flex_align(scr, LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
|
||||
|
||||
hashrate_label = lv_label_create(scr);
|
||||
lv_label_set_text(hashrate_label, "Gh/s: n/a");
|
||||
lv_label_set_text(hashrate_label, "Gh/s: --");
|
||||
|
||||
efficiency_label = lv_label_create(scr);
|
||||
lv_label_set_text(efficiency_label, "J/Th: n/a");
|
||||
lv_label_set_text(efficiency_label, "J/Th: --");
|
||||
|
||||
difficulty_label = lv_label_create(scr);
|
||||
lv_label_set_text(difficulty_label, "Best: n/a");
|
||||
lv_label_set_text(difficulty_label, "Best: --");
|
||||
|
||||
chip_temp_label = lv_label_create(scr);
|
||||
lv_label_set_text(chip_temp_label, "Temp: n/a");
|
||||
lv_label_set_text(chip_temp_label, "Temp: --");
|
||||
|
||||
return scr;
|
||||
}
|
||||
@ -236,7 +259,18 @@ static void screen_update_cb(lv_timer_t * timer)
|
||||
return;
|
||||
}
|
||||
|
||||
if (GLOBAL_STATE->ASIC_functions.init_fn == NULL) {
|
||||
if (GLOBAL_STATE->SYSTEM_MODULE.is_firmware_update) {
|
||||
if (strcmp(GLOBAL_STATE->SYSTEM_MODULE.firmware_update_filename, lv_label_get_text(firmware_update_scr_filename_label)) != 0) {
|
||||
lv_label_set_text(firmware_update_scr_filename_label, GLOBAL_STATE->SYSTEM_MODULE.firmware_update_filename);
|
||||
}
|
||||
if (strcmp(GLOBAL_STATE->SYSTEM_MODULE.firmware_update_status, lv_label_get_text(firmware_update_scr_status_label)) != 0) {
|
||||
lv_label_set_text(firmware_update_scr_status_label, GLOBAL_STATE->SYSTEM_MODULE.firmware_update_status);
|
||||
}
|
||||
screen_show(SCR_FIRMWARE_UPDATE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GLOBAL_STATE->valid_model == false) {
|
||||
screen_show(SCR_INVALID_ASIC);
|
||||
return;
|
||||
}
|
||||
@ -319,14 +353,14 @@ static void screen_update_cb(lv_timer_t * timer)
|
||||
}
|
||||
}
|
||||
|
||||
if (curreny_chip_temp != power_management->chip_temp_avg) {
|
||||
if (current_chip_temp != power_management->chip_temp_avg && power_management->chip_temp_avg > 0) {
|
||||
lv_label_set_text_fmt(chip_temp_label, "Temp: %.1f C", power_management->chip_temp_avg);
|
||||
}
|
||||
|
||||
current_hashrate = module->current_hashrate;
|
||||
current_power = power_management->power;
|
||||
current_difficulty = module->best_session_nonce_diff;
|
||||
curreny_chip_temp = power_management->chip_temp_avg;
|
||||
current_chip_temp = power_management->chip_temp_avg;
|
||||
|
||||
if (CAROUSEL_DELAY_COUNT > current_screen_counter || found_block) {
|
||||
return;
|
||||
@ -353,6 +387,7 @@ esp_err_t screen_start(void * pvParameters)
|
||||
screens[SCR_OVERHEAT] = create_scr_overheat(module);
|
||||
screens[SCR_INVALID_ASIC] = create_scr_invalid_asic(module);
|
||||
screens[SCR_CONFIGURE] = create_scr_configure(module);
|
||||
screens[SCR_FIRMWARE_UPDATE] = create_scr_ota(module);
|
||||
screens[SCR_CONNECTION] = create_scr_connection(module);
|
||||
screens[SCR_LOGO] = create_scr_logo();
|
||||
screens[SCR_URLS] = create_scr_urls(module);
|
||||
|
@ -6,6 +6,7 @@ typedef enum {
|
||||
SCR_OVERHEAT,
|
||||
SCR_INVALID_ASIC,
|
||||
SCR_CONFIGURE,
|
||||
SCR_FIRMWARE_UPDATE,
|
||||
SCR_CONNECTION,
|
||||
SCR_LOGO,
|
||||
SCR_URLS,
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include "TPS546.h"
|
||||
#include "esp_psram.h"
|
||||
|
||||
#include "asic.h"
|
||||
|
||||
#define GPIO_ASIC_ENABLE CONFIG_GPIO_ASIC_ENABLE
|
||||
|
||||
#define TESTS_FAILED 0
|
||||
@ -50,6 +52,8 @@
|
||||
|
||||
static const char * TAG = "self_test";
|
||||
|
||||
SemaphoreHandle_t BootSemaphore;
|
||||
|
||||
//local function prototypes
|
||||
static void tests_done(GlobalState * GLOBAL_STATE, bool test_result);
|
||||
|
||||
@ -64,9 +68,9 @@ bool should_test(GlobalState * GLOBAL_STATE) {
|
||||
}
|
||||
|
||||
static void reset_self_test() {
|
||||
ESP_LOGI(TAG, "Long press detected, resetting self test flag and rebooting...");
|
||||
nvs_config_set_u16(NVS_CONFIG_SELF_TEST, 0);
|
||||
esp_restart();
|
||||
ESP_LOGI(TAG, "Long press detected...");
|
||||
// Give the semaphore back
|
||||
xSemaphoreGive(BootSemaphore);
|
||||
}
|
||||
|
||||
static void display_msg(char * msg, GlobalState * GLOBAL_STATE)
|
||||
@ -314,6 +318,14 @@ void self_test(void * pvParameters)
|
||||
|
||||
GLOBAL_STATE->SELF_TEST_MODULE.active = true;
|
||||
|
||||
// Create a binary semaphore
|
||||
BootSemaphore = xSemaphoreCreateBinary();
|
||||
|
||||
if (BootSemaphore == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to create semaphore");
|
||||
return;
|
||||
}
|
||||
|
||||
//Run PSRAM test
|
||||
if(test_psram(GLOBAL_STATE) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "NO PSRAM on device!");
|
||||
@ -356,11 +368,12 @@ void self_test(void * pvParameters)
|
||||
tests_done(GLOBAL_STATE, TESTS_FAILED);
|
||||
}
|
||||
|
||||
uint8_t chips_detected = (GLOBAL_STATE->ASIC_functions.init_fn)(GLOBAL_STATE->POWER_MANAGEMENT_MODULE.frequency_value, GLOBAL_STATE->asic_count);
|
||||
ESP_LOGI(TAG, "%u chips detected, %u expected", chips_detected, GLOBAL_STATE->asic_count);
|
||||
uint8_t chips_detected = ASIC_init(GLOBAL_STATE);
|
||||
uint8_t chips_expected = ASIC_get_asic_count(GLOBAL_STATE);
|
||||
ESP_LOGI(TAG, "%u chips detected, %u expected", chips_detected, chips_expected);
|
||||
|
||||
if (chips_detected != GLOBAL_STATE->asic_count) {
|
||||
ESP_LOGE(TAG, "SELF TEST FAIL, %d of %d CHIPS DETECTED", chips_detected, GLOBAL_STATE->asic_count);
|
||||
if (chips_detected != chips_expected) {
|
||||
ESP_LOGE(TAG, "SELF TEST FAIL, %d of %d CHIPS DETECTED", chips_detected, chips_expected);
|
||||
char error_buf[20];
|
||||
snprintf(error_buf, 20, "ASIC:FAIL %d CHIPS", chips_detected);
|
||||
display_msg(error_buf, GLOBAL_STATE);
|
||||
@ -368,7 +381,7 @@ void self_test(void * pvParameters)
|
||||
}
|
||||
|
||||
//setup and test hashrate
|
||||
int baud = (*GLOBAL_STATE->ASIC_functions.set_max_baud_fn)();
|
||||
int baud = ASIC_set_max_baud(GLOBAL_STATE);
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
|
||||
if (SERIAL_set_baud(baud) != ESP_OK) {
|
||||
@ -427,11 +440,13 @@ void self_test(void * pvParameters)
|
||||
|
||||
uint8_t difficulty_mask = 8;
|
||||
|
||||
(*GLOBAL_STATE->ASIC_functions.set_difficulty_mask_fn)(difficulty_mask);
|
||||
//(*GLOBAL_STATE->ASIC_functions.set_difficulty_mask_fn)(difficulty_mask);
|
||||
ASIC_set_job_difficulty_mask(GLOBAL_STATE, difficulty_mask);
|
||||
|
||||
ESP_LOGI(TAG, "Sending work");
|
||||
|
||||
(*GLOBAL_STATE->ASIC_functions.send_work_fn)(GLOBAL_STATE, &job);
|
||||
//(*GLOBAL_STATE->ASIC_functions.send_work_fn)(GLOBAL_STATE, &job);
|
||||
ASIC_send_work(GLOBAL_STATE, &job);
|
||||
|
||||
double start = esp_timer_get_time();
|
||||
double sum = 0;
|
||||
@ -439,7 +454,7 @@ void self_test(void * pvParameters)
|
||||
double hash_rate = 0;
|
||||
|
||||
while(duration < 3){
|
||||
task_result * asic_result = (*GLOBAL_STATE->ASIC_functions.receive_result_fn)(GLOBAL_STATE);
|
||||
task_result * asic_result = ASIC_process_work(GLOBAL_STATE);
|
||||
if (asic_result != NULL) {
|
||||
// check the nonce difficulty
|
||||
double nonce_diff = test_nonce_value(&job, asic_result->nonce, asic_result->rolled_version);
|
||||
@ -513,7 +528,7 @@ void self_test(void * pvParameters)
|
||||
}
|
||||
|
||||
tests_done(GLOBAL_STATE, TESTS_PASSED);
|
||||
ESP_LOGI(TAG, "Self Tests Passed!!!");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -530,10 +545,20 @@ static void tests_done(GlobalState * GLOBAL_STATE, bool test_result)
|
||||
default:
|
||||
}
|
||||
|
||||
if (test_result != TESTS_PASSED) {
|
||||
if (test_result == TESTS_FAILED) {
|
||||
ESP_LOGI(TAG, "SELF TESTS FAIL -- Press RESET to continue");
|
||||
//wait here for a long press to reboot
|
||||
vTaskDelay(portMAX_DELAY);
|
||||
while (1) {
|
||||
// Wait here forever until reset_self_test() gives the BootSemaphore
|
||||
if (xSemaphoreTake(BootSemaphore, portMAX_DELAY) == pdTRUE) {
|
||||
nvs_config_set_u16(NVS_CONFIG_SELF_TEST, 0);
|
||||
//wait 100ms for nvs write to finish?
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
esp_restart();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
nvs_config_set_u16(NVS_CONFIG_SELF_TEST, 0);
|
||||
ESP_LOGI(TAG, "Self Tests Passed!!!");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -20,7 +20,6 @@
|
||||
|
||||
#include "system.h"
|
||||
#include "i2c_bitaxe.h"
|
||||
#include "EMC2101.h"
|
||||
#include "INA260.h"
|
||||
#include "adc.h"
|
||||
#include "connect.h"
|
||||
@ -29,6 +28,7 @@
|
||||
#include "input.h"
|
||||
#include "screen.h"
|
||||
#include "vcore.h"
|
||||
#include "thermal.h"
|
||||
|
||||
static const char * TAG = "SystemModule";
|
||||
|
||||
@ -63,10 +63,18 @@ void SYSTEM_init_system(GlobalState * GLOBAL_STATE)
|
||||
module->pool_url = nvs_config_get_string(NVS_CONFIG_STRATUM_URL, CONFIG_STRATUM_URL);
|
||||
module->fallback_pool_url = nvs_config_get_string(NVS_CONFIG_FALLBACK_STRATUM_URL, CONFIG_FALLBACK_STRATUM_URL);
|
||||
|
||||
//set the pool port
|
||||
// set the pool port
|
||||
module->pool_port = nvs_config_get_u16(NVS_CONFIG_STRATUM_PORT, CONFIG_STRATUM_PORT);
|
||||
module->fallback_pool_port = nvs_config_get_u16(NVS_CONFIG_FALLBACK_STRATUM_PORT, CONFIG_FALLBACK_STRATUM_PORT);
|
||||
|
||||
// set the pool user
|
||||
module->pool_user = nvs_config_get_string(NVS_CONFIG_STRATUM_USER, CONFIG_STRATUM_USER);
|
||||
module->fallback_pool_user = nvs_config_get_string(NVS_CONFIG_FALLBACK_STRATUM_USER, CONFIG_FALLBACK_STRATUM_USER);
|
||||
|
||||
// set the pool password
|
||||
module->pool_pass = nvs_config_get_string(NVS_CONFIG_STRATUM_PASS, CONFIG_STRATUM_PW);
|
||||
module->fallback_pool_pass = nvs_config_get_string(NVS_CONFIG_FALLBACK_STRATUM_PASS, CONFIG_FALLBACK_STRATUM_PW);
|
||||
|
||||
// set fallback to false.
|
||||
module->is_using_fallback = false;
|
||||
|
||||
@ -90,33 +98,7 @@ void SYSTEM_init_peripherals(GlobalState * GLOBAL_STATE) {
|
||||
VCORE_init(GLOBAL_STATE);
|
||||
VCORE_set_voltage(nvs_config_get_u16(NVS_CONFIG_ASIC_VOLTAGE, CONFIG_ASIC_VOLTAGE) / 1000.0, GLOBAL_STATE);
|
||||
|
||||
//init the EMC2101, if we have one
|
||||
switch (GLOBAL_STATE->device_model) {
|
||||
case DEVICE_MAX:
|
||||
case DEVICE_ULTRA:
|
||||
case DEVICE_SUPRA:
|
||||
EMC2101_init(nvs_config_get_u16(NVS_CONFIG_INVERT_FAN_POLARITY, 1));
|
||||
break;
|
||||
case DEVICE_GAMMA:
|
||||
EMC2101_init(nvs_config_get_u16(NVS_CONFIG_INVERT_FAN_POLARITY, 1));
|
||||
EMC2101_set_ideality_factor(EMC2101_IDEALITY_1_0319);
|
||||
EMC2101_set_beta_compensation(EMC2101_BETA_11);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
//initialize the INA260, if we have one.
|
||||
switch (GLOBAL_STATE->device_model) {
|
||||
case DEVICE_MAX:
|
||||
case DEVICE_ULTRA:
|
||||
case DEVICE_SUPRA:
|
||||
if (GLOBAL_STATE->board_version < 402) {
|
||||
INA260_init();
|
||||
}
|
||||
break;
|
||||
case DEVICE_GAMMA:
|
||||
default:
|
||||
}
|
||||
Thermal_init(GLOBAL_STATE->device_model, nvs_config_get_u16(NVS_CONFIG_INVERT_FAN_POLARITY, 1));
|
||||
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
|
||||
@ -132,6 +114,7 @@ void SYSTEM_init_peripherals(GlobalState * GLOBAL_STATE) {
|
||||
case DEVICE_ULTRA:
|
||||
case DEVICE_SUPRA:
|
||||
case DEVICE_GAMMA:
|
||||
case DEVICE_GAMMATURBO:
|
||||
// display
|
||||
if (display_init(GLOBAL_STATE) != ESP_OK || !GLOBAL_STATE->SYSTEM_MODULE.is_screen_active) {
|
||||
ESP_LOGW(TAG, "OLED init failed!");
|
||||
@ -160,11 +143,38 @@ void SYSTEM_notify_accepted_share(GlobalState * GLOBAL_STATE)
|
||||
module->shares_accepted++;
|
||||
}
|
||||
|
||||
void SYSTEM_notify_rejected_share(GlobalState * GLOBAL_STATE)
|
||||
static int compare_rejected_reason_stats(const void *a, const void *b) {
|
||||
const RejectedReasonStat *ea = a;
|
||||
const RejectedReasonStat *eb = b;
|
||||
return (eb->count > ea->count) - (ea->count > eb->count);
|
||||
}
|
||||
|
||||
void SYSTEM_notify_rejected_share(GlobalState * GLOBAL_STATE, char * error_msg)
|
||||
{
|
||||
SystemModule * module = &GLOBAL_STATE->SYSTEM_MODULE;
|
||||
|
||||
module->shares_rejected++;
|
||||
|
||||
for (int i = 0; i < module->rejected_reason_stats_count; i++) {
|
||||
if (strncmp(module->rejected_reason_stats[i].message, error_msg, sizeof(module->rejected_reason_stats[i].message) - 1) == 0) {
|
||||
module->rejected_reason_stats[i].count++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (module->rejected_reason_stats_count < sizeof(module->rejected_reason_stats)) {
|
||||
strncpy(module->rejected_reason_stats[module->rejected_reason_stats_count].message,
|
||||
error_msg,
|
||||
sizeof(module->rejected_reason_stats[module->rejected_reason_stats_count].message) - 1);
|
||||
module->rejected_reason_stats[module->rejected_reason_stats_count].message[sizeof(module->rejected_reason_stats[module->rejected_reason_stats_count].message) - 1] = '\0'; // Ensure null termination
|
||||
module->rejected_reason_stats[module->rejected_reason_stats_count].count = 1;
|
||||
module->rejected_reason_stats_count++;
|
||||
}
|
||||
|
||||
if (module->rejected_reason_stats_count > 1) {
|
||||
qsort(module->rejected_reason_stats, module->rejected_reason_stats_count,
|
||||
sizeof(module->rejected_reason_stats[0]), compare_rejected_reason_stats);
|
||||
}
|
||||
}
|
||||
|
||||
void SYSTEM_notify_mining_started(GlobalState * GLOBAL_STATE)
|
||||
|
@ -7,7 +7,7 @@ void SYSTEM_init_system(GlobalState * GLOBAL_STATE);
|
||||
void SYSTEM_init_peripherals(GlobalState * GLOBAL_STATE);
|
||||
|
||||
void SYSTEM_notify_accepted_share(GlobalState * GLOBAL_STATE);
|
||||
void SYSTEM_notify_rejected_share(GlobalState * GLOBAL_STATE);
|
||||
void SYSTEM_notify_rejected_share(GlobalState * GLOBAL_STATE, char * error_msg);
|
||||
void SYSTEM_notify_found_nonce(GlobalState * GLOBAL_STATE, double found_diff, uint8_t job_id);
|
||||
void SYSTEM_notify_mining_started(GlobalState * GLOBAL_STATE);
|
||||
void SYSTEM_notify_new_ntime(GlobalState * GLOBAL_STATE, uint32_t ntime);
|
||||
|
@ -1,3 +1,5 @@
|
||||
#include <lwip/tcpip.h>
|
||||
|
||||
#include "system.h"
|
||||
#include "work_queue.h"
|
||||
#include "serial.h"
|
||||
@ -7,7 +9,7 @@
|
||||
#include "nvs_config.h"
|
||||
#include "utils.h"
|
||||
#include "stratum_task.h"
|
||||
#include <lwip/tcpip.h>
|
||||
#include "asic.h"
|
||||
|
||||
static const char *TAG = "asic_result";
|
||||
|
||||
@ -17,7 +19,8 @@ void ASIC_result_task(void *pvParameters)
|
||||
|
||||
while (1)
|
||||
{
|
||||
task_result *asic_result = (*GLOBAL_STATE->ASIC_functions.receive_result_fn)(GLOBAL_STATE);
|
||||
//task_result *asic_result = (*GLOBAL_STATE->ASIC_functions.receive_result_fn)(GLOBAL_STATE);
|
||||
task_result *asic_result = ASIC_process_work(GLOBAL_STATE);
|
||||
|
||||
if (asic_result == NULL)
|
||||
{
|
||||
@ -28,7 +31,7 @@ void ASIC_result_task(void *pvParameters)
|
||||
|
||||
if (GLOBAL_STATE->valid_jobs[job_id] == 0)
|
||||
{
|
||||
ESP_LOGI(TAG, "Invalid job nonce found, 0x%02X", job_id);
|
||||
ESP_LOGW(TAG, "Invalid job nonce found, 0x%02X", job_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -41,18 +44,18 @@ void ASIC_result_task(void *pvParameters)
|
||||
//log the ASIC response
|
||||
ESP_LOGI(TAG, "Ver: %08" PRIX32 " Nonce %08" PRIX32 " diff %.1f of %ld.", asic_result->rolled_version, asic_result->nonce, nonce_diff, GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->pool_diff);
|
||||
|
||||
if (nonce_diff > GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->pool_diff)
|
||||
if (nonce_diff >= GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->pool_diff)
|
||||
{
|
||||
char * user = GLOBAL_STATE->SYSTEM_MODULE.is_using_fallback ? nvs_config_get_string(NVS_CONFIG_FALLBACK_STRATUM_USER, FALLBACK_STRATUM_USER) : nvs_config_get_string(NVS_CONFIG_STRATUM_USER, STRATUM_USER);
|
||||
char * user = GLOBAL_STATE->SYSTEM_MODULE.is_using_fallback ? GLOBAL_STATE->SYSTEM_MODULE.fallback_pool_user : GLOBAL_STATE->SYSTEM_MODULE.pool_user;
|
||||
int ret = STRATUM_V1_submit_share(
|
||||
GLOBAL_STATE->sock,
|
||||
GLOBAL_STATE->send_uid++,
|
||||
user,
|
||||
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->jobid,
|
||||
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);
|
||||
free(user);
|
||||
|
||||
if (ret < 0) {
|
||||
ESP_LOGI(TAG, "Unable to write share to socket. Closing connection. Ret: %d (errno %d: %s)", ret, errno, strerror(errno));
|
||||
@ -62,4 +65,4 @@ void ASIC_result_task(void *pvParameters)
|
||||
|
||||
SYSTEM_notify_found_nonce(GLOBAL_STATE, nonce_diff, job_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,8 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
#include "asic.h"
|
||||
|
||||
static const char *TAG = "ASIC_task";
|
||||
|
||||
// static bm_job ** active_jobs; is required to keep track of the active jobs since the
|
||||
@ -42,7 +44,8 @@ void ASIC_task(void *pvParameters)
|
||||
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
|
||||
ASIC_send_work(GLOBAL_STATE, next_bm_job);
|
||||
|
||||
// Time to execute the above code is ~0.3ms
|
||||
// Delay for ASIC(s) to finish the job
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user