mirror of
https://github.com/skot/ESP-Miner.git
synced 2025-03-17 13:22:53 +01:00
Compare commits
57 Commits
181b70b2aa
...
6a6b917102
Author | SHA1 | Date | |
---|---|---|---|
|
6a6b917102 | ||
|
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 |
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
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
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.
|
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/skot/esp-miner/security/advisories/new) tab.
|
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.
|
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.
|
||||||
|
|
||||||
|
@ -7,6 +7,8 @@ SRCS
|
|||||||
"serial.c"
|
"serial.c"
|
||||||
"crc.c"
|
"crc.c"
|
||||||
"common.c"
|
"common.c"
|
||||||
|
"asic.c"
|
||||||
|
"frequency_transition_bmXX.c"
|
||||||
|
|
||||||
INCLUDE_DIRS
|
INCLUDE_DIRS
|
||||||
"include"
|
"include"
|
||||||
@ -22,4 +24,4 @@ REQUIRES
|
|||||||
target_include_directories(${COMPONENT_LIB} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../main")
|
target_include_directories(${COMPONENT_LIB} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../main")
|
||||||
|
|
||||||
# Include the header files from "main/tasks" directory
|
# 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 "esp_log.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
|
#include "frequency_transition_bmXX.h"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.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
|
#define GPIO_ASIC_RESET CONFIG_GPIO_ASIC_RESET
|
||||||
|
#else
|
||||||
|
#define GPIO_ASIC_RESET 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#define TYPE_JOB 0x20
|
#define TYPE_JOB 0x20
|
||||||
#define TYPE_CMD 0x40
|
#define TYPE_CMD 0x40
|
||||||
@ -45,23 +54,20 @@
|
|||||||
#define TICKET_MASK 0x14
|
#define TICKET_MASK 0x14
|
||||||
#define MISC_CONTROL 0x18
|
#define MISC_CONTROL 0x18
|
||||||
|
|
||||||
#define BM1366_TIMEOUT_MS 10000
|
|
||||||
#define BM1366_TIMEOUT_THRESHOLD 2
|
|
||||||
typedef struct __attribute__((__packed__))
|
typedef struct __attribute__((__packed__))
|
||||||
{
|
{
|
||||||
uint8_t preamble[2];
|
uint16_t preamble;
|
||||||
uint32_t nonce;
|
uint32_t nonce;
|
||||||
uint8_t midstate_num;
|
uint8_t midstate_num;
|
||||||
uint8_t job_id;
|
uint8_t job_id;
|
||||||
uint16_t version;
|
uint16_t version;
|
||||||
uint8_t crc;
|
uint8_t crc;
|
||||||
} asic_result;
|
} bm1366_asic_result_t;
|
||||||
|
|
||||||
static float current_frequency = 56.25;
|
static float current_frequency = 56.25;
|
||||||
|
|
||||||
static const char * TAG = "bm1366Module";
|
static const char * TAG = "bm1366Module";
|
||||||
|
|
||||||
static uint8_t asic_response_buffer[SERIAL_BUF_SIZE];
|
|
||||||
static task_result result;
|
static task_result result;
|
||||||
|
|
||||||
/// @brief
|
/// @brief
|
||||||
@ -197,38 +203,18 @@ void BM1366_send_hash_frequency(float target_freq)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void do_frequency_ramp_up(float target_frequency) {
|
static void do_frequency_ramp_up(float target_frequency) {
|
||||||
float step = 6.25;
|
ESP_LOGI(TAG, "Ramping up frequency from %.2f MHz to %.2f MHz", current_frequency, target_frequency);
|
||||||
float current = current_frequency;
|
do_frequency_transition(target_frequency, BM1366_send_hash_frequency, 1366);
|
||||||
float target = target_frequency;
|
}
|
||||||
|
|
||||||
float direction = (target > current) ? step : -step;
|
// Add a public function for external use
|
||||||
|
bool BM1366_set_frequency(float target_freq) {
|
||||||
if (fmod(current, step) != 0) {
|
return do_frequency_transition(target_freq, BM1366_send_hash_frequency, 1366);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t _send_init(uint64_t frequency, uint16_t asic_count)
|
static uint8_t _send_init(uint64_t frequency, uint16_t asic_count)
|
||||||
{
|
{
|
||||||
|
|
||||||
// set version mask
|
// set version mask
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
BM1366_set_version_mask(STRATUM_DEFAULT_VERSION_MASK);
|
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};
|
unsigned char init3[7] = {0x55, 0xAA, 0x52, 0x05, 0x00, 0x00, 0x0A};
|
||||||
_send_simple(init3, 7);
|
_send_simple(init3, 7);
|
||||||
|
|
||||||
int chip_counter = 0;
|
int chip_counter = count_asic_chips(asic_count, BM1366_CHIP_ID, BM1366_CHIP_ID_RESPONSE_LENGTH);
|
||||||
while (true) {
|
|
||||||
if(SERIAL_rx(asic_response_buffer, 11, 1000) > 0) {
|
if (chip_counter == 0) {
|
||||||
chip_counter++;
|
return 0;
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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};
|
unsigned char init4[11] = {0x55, 0xAA, 0x51, 0x09, 0x00, 0xA8, 0x00, 0x07, 0x00, 0x00, 0x03};
|
||||||
_send_simple(init4, 11);
|
_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);
|
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, 0x11, 0x5A}; //S19k Pro Default
|
||||||
// unsigned char set_10_hash_counting[6] = {0x00, 0x10, 0x00, 0x00, 0x14, 0x46}; //S19XP-Luxos Default
|
// unsigned char set_10_hash_counting[6] = {0x00, 0x10, 0x00, 0x00, 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");
|
ESP_LOGI(TAG, "Initializing BM1366");
|
||||||
|
|
||||||
memset(asic_response_buffer, 0, SERIAL_BUF_SIZE);
|
|
||||||
|
|
||||||
esp_rom_gpio_pad_select_gpio(GPIO_ASIC_RESET);
|
esp_rom_gpio_pad_select_gpio(GPIO_ASIC_RESET);
|
||||||
gpio_set_direction(GPIO_ASIC_RESET, GPIO_MODE_OUTPUT);
|
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);
|
_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
|
bm1366_asic_result_t asic_result = {0};
|
||||||
int received = SERIAL_rx(asic_response_buffer, 11, BM1366_TIMEOUT_MS);
|
|
||||||
|
|
||||||
bool uart_err = received < 0;
|
if (receive_work((uint8_t *)&asic_result, sizeof(asic_result)) == ESP_FAIL) {
|
||||||
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++;
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (received != 11 || asic_response_buffer[0] != 0xAA || asic_response_buffer[1] != 0x55) {
|
uint8_t job_id = asic_result.job_id & 0xf8;
|
||||||
ESP_LOGI(TAG, "Serial RX invalid %i", received);
|
uint8_t core_id = (uint8_t)((ntohl(asic_result.nonce) >> 25) & 0x7f); // BM1366 has 112 cores, so it should be coded on 7 bits
|
||||||
ESP_LOG_BUFFER_HEX(TAG, asic_response_buffer, received);
|
uint8_t small_core_id = asic_result.job_id & 0x07; // BM1366 has 8 small cores, so it should be coded on 3 bits
|
||||||
SERIAL_clear_buffer();
|
uint32_t version_bits = (ntohs(asic_result.version) << 13); // shift the 16 bit value left 13
|
||||||
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
|
|
||||||
ESP_LOGI(TAG, "Job ID: %02X, Core: %d/%d, Ver: %08" PRIX32, job_id, core_id, small_core_id, version_bits);
|
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;
|
GlobalState * GLOBAL_STATE = (GlobalState *) pvParameters;
|
||||||
|
|
||||||
if (GLOBAL_STATE->valid_jobs[job_id] == 0) {
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t rolled_version = GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->version | version_bits;
|
uint32_t rolled_version = GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->version | version_bits;
|
||||||
|
|
||||||
result.job_id = job_id;
|
result.job_id = job_id;
|
||||||
result.nonce = asic_result->nonce;
|
result.nonce = asic_result.nonce;
|
||||||
result.rolled_version = rolled_version;
|
result.rolled_version = rolled_version;
|
||||||
|
|
||||||
return &result;
|
return &result;
|
||||||
|
@ -8,14 +8,23 @@
|
|||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
|
#include "frequency_transition_bmXX.h"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.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
|
#define GPIO_ASIC_RESET CONFIG_GPIO_ASIC_RESET
|
||||||
|
#else
|
||||||
|
#define GPIO_ASIC_RESET 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#define TYPE_JOB 0x20
|
#define TYPE_JOB 0x20
|
||||||
#define TYPE_CMD 0x40
|
#define TYPE_CMD 0x40
|
||||||
@ -45,21 +54,18 @@
|
|||||||
#define TICKET_MASK 0x14
|
#define TICKET_MASK 0x14
|
||||||
#define MISC_CONTROL 0x18
|
#define MISC_CONTROL 0x18
|
||||||
|
|
||||||
#define BM1368_TIMEOUT_MS 10000
|
|
||||||
#define BM1368_TIMEOUT_THRESHOLD 2
|
|
||||||
typedef struct __attribute__((__packed__))
|
typedef struct __attribute__((__packed__))
|
||||||
{
|
{
|
||||||
uint8_t preamble[2];
|
uint16_t preamble;
|
||||||
uint32_t nonce;
|
uint32_t nonce;
|
||||||
uint8_t midstate_num;
|
uint8_t midstate_num;
|
||||||
uint8_t job_id;
|
uint8_t job_id;
|
||||||
uint16_t version;
|
uint16_t version;
|
||||||
uint8_t crc;
|
uint8_t crc;
|
||||||
} asic_result;
|
} bm1368_asic_result_t;
|
||||||
|
|
||||||
static const char * TAG = "bm1368Module";
|
static const char * TAG = "bm1368Module";
|
||||||
|
|
||||||
static uint8_t asic_response_buffer[CHUNK_SIZE];
|
|
||||||
static task_result result;
|
static task_result result;
|
||||||
|
|
||||||
static float current_frequency = 56.25;
|
static float current_frequency = 56.25;
|
||||||
@ -128,7 +134,7 @@ static void _reset(void)
|
|||||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
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;
|
float max_diff = 0.001;
|
||||||
uint8_t freqbuf[6] = {0x00, 0x08, 0x40, 0xA0, 0x02, 0x41};
|
uint8_t freqbuf[6] = {0x00, 0x08, 0x40, 0xA0, 0x02, 0x41};
|
||||||
uint8_t postdiv_min = 255;
|
uint8_t postdiv_min = 255;
|
||||||
@ -164,7 +170,7 @@ bool BM1368_send_hash_frequency(float target_freq) {
|
|||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
ESP_LOGE(TAG, "Didn't find PLL settings for target frequency %.2f", target_freq);
|
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;
|
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);
|
ESP_LOGI(TAG, "Setting Frequency to %.2fMHz (%.2f)", target_freq, best_freq);
|
||||||
current_frequency = target_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) {
|
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) {
|
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);
|
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)
|
uint8_t BM1368_init(uint64_t frequency, uint16_t asic_count)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "Initializing BM1368");
|
ESP_LOGI(TAG, "Initializing BM1368");
|
||||||
|
|
||||||
memset(asic_response_buffer, 0, CHUNK_SIZE);
|
|
||||||
|
|
||||||
esp_rom_gpio_pad_select_gpio(GPIO_ASIC_RESET);
|
esp_rom_gpio_pad_select_gpio(GPIO_ASIC_RESET);
|
||||||
gpio_set_direction(GPIO_ASIC_RESET, GPIO_MODE_OUTPUT);
|
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);
|
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) {
|
int chip_counter = count_asic_chips(asic_count, BM1368_CHIP_ID, BM1368_CHIP_ID_RESPONSE_LENGTH);
|
||||||
ESP_LOGE(TAG, "Chip count mismatch. Expected: %d, Actual: %d", asic_count, chip_counter);
|
|
||||||
|
if (chip_counter == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_send_chain_inactive();
|
||||||
|
|
||||||
uint8_t init_cmds[][6] = {
|
uint8_t init_cmds[][6] = {
|
||||||
{0x00, 0xA8, 0x00, 0x07, 0x00, 0x00},
|
{0x00, 0xA8, 0x00, 0x07, 0x00, 0x00},
|
||||||
{0x00, 0x18, 0xFF, 0x0F, 0xC1, 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);
|
_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);
|
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;
|
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);
|
_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
|
bm1368_asic_result_t asic_result = {0};
|
||||||
int received = SERIAL_rx(asic_response_buffer, 11, BM1368_TIMEOUT_MS);
|
|
||||||
|
|
||||||
bool uart_err = received < 0;
|
if (receive_work((uint8_t *)&asic_result, sizeof(asic_result)) == ESP_FAIL) {
|
||||||
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++;
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (received != 11 || asic_response_buffer[0] != 0xAA || asic_response_buffer[1] != 0x55) {
|
uint8_t job_id = (asic_result.job_id & 0xf0) >> 1;
|
||||||
ESP_LOGE(TAG, "Serial RX invalid %i", received);
|
uint8_t core_id = (uint8_t)((ntohl(asic_result.nonce) >> 25) & 0x7f);
|
||||||
ESP_LOG_BUFFER_HEX(TAG, asic_response_buffer, received);
|
uint8_t small_core_id = asic_result.job_id & 0x0f;
|
||||||
SERIAL_clear_buffer();
|
uint32_t version_bits = (ntohs(asic_result.version) << 13);
|
||||||
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);
|
|
||||||
ESP_LOGI(TAG, "Job ID: %02X, Core: %d/%d, Ver: %08" PRIX32, job_id, core_id, small_core_id, version_bits);
|
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;
|
GlobalState * GLOBAL_STATE = (GlobalState *) pvParameters;
|
||||||
|
|
||||||
if (GLOBAL_STATE->valid_jobs[job_id] == 0) {
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t rolled_version = GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->version | version_bits;
|
uint32_t rolled_version = GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->version | version_bits;
|
||||||
|
|
||||||
result.job_id = job_id;
|
result.job_id = job_id;
|
||||||
result.nonce = asic_result->nonce;
|
result.nonce = asic_result.nonce;
|
||||||
result.rolled_version = rolled_version;
|
result.rolled_version = rolled_version;
|
||||||
|
|
||||||
return &result;
|
return &result;
|
||||||
}
|
}
|
||||||
|
@ -8,14 +8,23 @@
|
|||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
|
#include "frequency_transition_bmXX.h"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.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
|
#define GPIO_ASIC_RESET CONFIG_GPIO_ASIC_RESET
|
||||||
|
#else
|
||||||
|
#define GPIO_ASIC_RESET 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#define TYPE_JOB 0x20
|
#define TYPE_JOB 0x20
|
||||||
#define TYPE_CMD 0x40
|
#define TYPE_CMD 0x40
|
||||||
@ -45,23 +54,18 @@
|
|||||||
#define TICKET_MASK 0x14
|
#define TICKET_MASK 0x14
|
||||||
#define MISC_CONTROL 0x18
|
#define MISC_CONTROL 0x18
|
||||||
|
|
||||||
#define BM1370_TIMEOUT_MS 10000
|
|
||||||
#define BM1370_TIMEOUT_THRESHOLD 2
|
|
||||||
|
|
||||||
typedef struct __attribute__((__packed__))
|
typedef struct __attribute__((__packed__))
|
||||||
{
|
{
|
||||||
uint8_t preamble[2];
|
uint16_t preamble;
|
||||||
uint32_t nonce;
|
uint32_t nonce;
|
||||||
uint8_t midstate_num;
|
uint8_t midstate_num;
|
||||||
uint8_t job_id;
|
uint8_t job_id;
|
||||||
uint16_t version;
|
uint16_t version;
|
||||||
uint8_t crc;
|
uint8_t crc;
|
||||||
} asic_result;
|
} bm1370_asic_result_t;
|
||||||
|
|
||||||
static const char * TAG = "bm1370Module";
|
static const char * TAG = "bm1370Module";
|
||||||
|
|
||||||
|
|
||||||
static uint8_t asic_response_buffer[SERIAL_BUF_SIZE];
|
|
||||||
static task_result result;
|
static task_result result;
|
||||||
|
|
||||||
/// @brief
|
/// @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);
|
_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) {
|
void BM1370_send_hash_frequency(float target_freq) {
|
||||||
uint8_t freqbuf[6] = {0x00, 0x08, 0x40, 0xA0, 0x02, 0x41};
|
// default 200Mhz if it fails
|
||||||
uint8_t postdiv_min = 255;
|
unsigned char freqbuf[6] = {0x00, 0x08, 0x40, 0xA0, 0x02, 0x41}; // freqbuf - pll0_parameter
|
||||||
uint8_t postdiv2_min = 255;
|
float newf = 200.0;
|
||||||
float best_freq = 0;
|
|
||||||
uint8_t best_refdiv = 0, best_fbdiv = 0, best_postdiv1 = 0, best_postdiv2 = 0;
|
|
||||||
|
|
||||||
for (uint8_t refdiv = 2; refdiv > 0; refdiv--) {
|
uint8_t fb_divider = 0;
|
||||||
for (uint8_t postdiv1 = 7; postdiv1 > 0; postdiv1--) {
|
uint8_t post_divider1 = 0, post_divider2 = 0;
|
||||||
for (uint8_t postdiv2 = 7; postdiv2 > 0; postdiv2--) {
|
uint8_t ref_divider = 0;
|
||||||
uint16_t fb_divider = round(target_freq / 25.0 * (refdiv * postdiv2 * postdiv1));
|
float min_difference = 10;
|
||||||
float newf = 25.0 * fb_divider / (refdiv * postdiv2 * postdiv1);
|
float max_diff = 1.0;
|
||||||
|
|
||||||
if (fb_divider >= 0xa0 && fb_divider <= 0xef &&
|
// refdiver is 2 or 1
|
||||||
fabs(target_freq - newf) < max_diff &&
|
// postdivider 2 is 1 to 7
|
||||||
postdiv1 >= postdiv2 &&
|
// postdivider 1 is 1 to 7 and greater than or equal to postdivider 2
|
||||||
postdiv1 * postdiv2 < postdiv_min &&
|
// fbdiv is 0xa0 to 0xef
|
||||||
postdiv2 <= postdiv2_min) {
|
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--) {
|
||||||
postdiv2_min = postdiv2;
|
for (uint8_t postdiv2_loop = 7; postdiv2_loop > 0 && fb_divider == 0; postdiv2_loop--) {
|
||||||
postdiv_min = postdiv1 * postdiv2;
|
if (postdiv1_loop >= postdiv2_loop) {
|
||||||
best_freq = newf;
|
int temp_fb_divider = round(((float) (postdiv1_loop * postdiv2_loop * target_freq * refdiv_loop) / 25.0));
|
||||||
best_refdiv = refdiv;
|
|
||||||
best_fbdiv = fb_divider;
|
if (temp_fb_divider >= 0xa0 && temp_fb_divider <= 0xef) {
|
||||||
best_postdiv1 = postdiv1;
|
float temp_freq = 25.0 * (float) temp_fb_divider / (float) (refdiv_loop * postdiv2_loop * postdiv1_loop);
|
||||||
best_postdiv2 = postdiv2;
|
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);
|
ESP_LOGE(TAG, "Failed to find PLL settings for target frequency %.2f", target_freq);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
freqbuf[2] = (best_fbdiv * 25 / best_refdiv >= 2400) ? 0x50 : 0x40;
|
freqbuf[3] = fb_divider;
|
||||||
freqbuf[3] = best_fbdiv;
|
freqbuf[4] = ref_divider;
|
||||||
freqbuf[4] = best_refdiv;
|
freqbuf[5] = (((post_divider1 - 1) & 0xf) << 4) + ((post_divider2 - 1) & 0xf);
|
||||||
freqbuf[5] = (((best_postdiv1 - 1) & 0xf) << 4) | ((best_postdiv2 - 1) & 0xf);
|
|
||||||
|
|
||||||
if (id != -1) {
|
if (fb_divider * 25 / (float) ref_divider >= 2400) {
|
||||||
freqbuf[0] = id * 2;
|
freqbuf[2] = 0x50;
|
||||||
_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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
static void do_frequency_ramp_up(float target_frequency) {
|
||||||
float current = 56.25;
|
|
||||||
float step = 6.25;
|
|
||||||
|
|
||||||
if (target_frequency == 0) {
|
if (target_frequency == 0) {
|
||||||
ESP_LOGI(TAG, "Skipping frequency ramp");
|
ESP_LOGI(TAG, "Skipping frequency ramp");
|
||||||
return;
|
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) {
|
ESP_LOGI(TAG, "Ramping up frequency from 56.25 MHz to %.2f MHz", target_frequency);
|
||||||
float next_step = fminf(step, target_frequency - current);
|
do_frequency_transition(target_frequency, BM1370_send_hash_frequency, 1370);
|
||||||
current += next_step;
|
}
|
||||||
BM1370_send_hash_frequency(-1, current, 0.001);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
// 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)
|
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};
|
unsigned char init3[7] = {0x55, 0xAA, 0x52, 0x05, 0x00, 0x00, 0x0A};
|
||||||
_send_simple(init3, 7);
|
_send_simple(init3, 7);
|
||||||
|
|
||||||
int chip_counter = 0;
|
int chip_counter = count_asic_chips(asic_count, BM1370_CHIP_ID, BM1370_CHIP_ID_RESPONSE_LENGTH);
|
||||||
while (true) {
|
|
||||||
if (SERIAL_rx(asic_response_buffer, 11, 1000) > 0) {
|
if (chip_counter == 0) {
|
||||||
chip_counter++;
|
return 0;
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ESP_LOGI(TAG, "%i chip(s) detected on the chain, expected %i", chip_counter, asic_count);
|
|
||||||
|
|
||||||
// set version mask
|
// set version mask
|
||||||
BM1370_set_version_mask(STRATUM_DEFAULT_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
|
//ramp up the hash frequency
|
||||||
do_frequency_ramp_up(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, 0x11, 0x5A}; //S19k Pro Default
|
||||||
// unsigned char set_10_hash_counting[6] = {0x00, 0x10, 0x00, 0x00, 0x14, 0x46}; //S19XP-Luxos Default
|
// unsigned char set_10_hash_counting[6] = {0x00, 0x10, 0x00, 0x00, 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");
|
ESP_LOGI(TAG, "Initializing BM1370");
|
||||||
|
|
||||||
memset(asic_response_buffer, 0, SERIAL_BUF_SIZE);
|
|
||||||
|
|
||||||
esp_rom_gpio_pad_select_gpio(GPIO_ASIC_RESET);
|
esp_rom_gpio_pad_select_gpio(GPIO_ASIC_RESET);
|
||||||
gpio_set_direction(GPIO_ASIC_RESET, GPIO_MODE_OUTPUT);
|
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);
|
_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
|
bm1370_asic_result_t asic_result = {0};
|
||||||
int received = SERIAL_rx(asic_response_buffer, 11, BM1370_TIMEOUT_MS);
|
|
||||||
|
|
||||||
bool uart_err = received < 0;
|
if (receive_work((uint8_t *)&asic_result, sizeof(asic_result)) == ESP_FAIL) {
|
||||||
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++;
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (received != 11 || asic_response_buffer[0] != 0xAA || asic_response_buffer[1] != 0x55) {
|
// uint8_t job_id = asic_result.job_id;
|
||||||
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 rx_job_id = ((int8_t)job_id & 0xf0) >> 1;
|
// uint8_t rx_job_id = ((int8_t)job_id & 0xf0) >> 1;
|
||||||
// ESP_LOGI(TAG, "Job ID: %02X, RX: %02X", job_id, rx_job_id);
|
// ESP_LOGI(TAG, "Job ID: %02X, RX: %02X", job_id, rx_job_id);
|
||||||
|
|
||||||
// uint8_t job_id = asic_result->job_id & 0xf8;
|
// uint8_t job_id = asic_result.job_id & 0xf8;
|
||||||
// ESP_LOGI(TAG, "Job ID: %02X, Core: %01X", job_id, asic_result->job_id & 0x07);
|
// 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 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 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
|
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
|
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);
|
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;
|
GlobalState * GLOBAL_STATE = (GlobalState *) pvParameters;
|
||||||
|
|
||||||
if (GLOBAL_STATE->valid_jobs[job_id] == 0) {
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t rolled_version = GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->version | version_bits;
|
uint32_t rolled_version = GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->version | version_bits;
|
||||||
|
|
||||||
result.job_id = job_id;
|
result.job_id = job_id;
|
||||||
result.nonce = asic_result->nonce;
|
result.nonce = asic_result.nonce;
|
||||||
result.rolled_version = rolled_version;
|
result.rolled_version = rolled_version;
|
||||||
|
|
||||||
return &result;
|
return &result;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
@ -15,7 +16,14 @@
|
|||||||
#include "mining.h"
|
#include "mining.h"
|
||||||
#include "global_state.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
|
#define GPIO_ASIC_RESET CONFIG_GPIO_ASIC_RESET
|
||||||
|
#else
|
||||||
|
#define GPIO_ASIC_RESET 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#define TYPE_JOB 0x20
|
#define TYPE_JOB 0x20
|
||||||
#define TYPE_CMD 0x40
|
#define TYPE_CMD 0x40
|
||||||
@ -45,21 +53,17 @@
|
|||||||
#define TICKET_MASK 0x14
|
#define TICKET_MASK 0x14
|
||||||
#define MISC_CONTROL 0x18
|
#define MISC_CONTROL 0x18
|
||||||
|
|
||||||
#define BM1397_TIMEOUT_MS 10000
|
|
||||||
#define BM1397_TIMEOUT_THRESHOLD 2
|
|
||||||
|
|
||||||
typedef struct __attribute__((__packed__))
|
typedef struct __attribute__((__packed__))
|
||||||
{
|
{
|
||||||
uint8_t preamble[2];
|
uint16_t preamble;
|
||||||
uint32_t nonce;
|
uint32_t nonce;
|
||||||
uint8_t midstate_num;
|
uint8_t midstate_num;
|
||||||
uint8_t job_id;
|
uint8_t job_id;
|
||||||
uint8_t crc;
|
uint8_t crc;
|
||||||
} asic_result;
|
} bm1397_asic_result_t;
|
||||||
|
|
||||||
static const char *TAG = "bm1397Module";
|
static const char *TAG = "bm1397Module";
|
||||||
|
|
||||||
static uint8_t asic_response_buffer[SERIAL_BUF_SIZE];
|
|
||||||
static uint32_t prev_nonce = 0;
|
static uint32_t prev_nonce = 0;
|
||||||
static task_result result;
|
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()
|
// borrowed from cgminer driver-gekko.c calc_gsf_freq()
|
||||||
void BM1397_send_hash_frequency(float frequency)
|
void BM1397_send_hash_frequency(float frequency)
|
||||||
{
|
{
|
||||||
|
|
||||||
unsigned char prefreq1[9] = {0x00, 0x70, 0x0F, 0x0F, 0x0F, 0x00}; // prefreq - pll0_divider
|
unsigned char prefreq1[9] = {0x00, 0x70, 0x0F, 0x0F, 0x0F, 0x00}; // prefreq - pll0_divider
|
||||||
|
|
||||||
// default 200Mhz if it fails
|
// 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 the init command
|
||||||
_send_read_address();
|
_send_read_address();
|
||||||
|
|
||||||
int chip_counter = 0;
|
int chip_counter = count_asic_chips(asic_count, BM1397_CHIP_ID, BM1397_CHIP_ID_RESPONSE_LENGTH);
|
||||||
while (true) {
|
|
||||||
if (SERIAL_rx(asic_response_buffer, 11, 1000) > 0) {
|
if (chip_counter == 0) {
|
||||||
chip_counter++;
|
return 0;
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ESP_LOGI(TAG, "%i chip(s) detected on the chain, expected %i", chip_counter, asic_count);
|
|
||||||
|
|
||||||
// send serial data
|
// send serial data
|
||||||
vTaskDelay(SLEEP_TIME / portTICK_PERIOD_MS);
|
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");
|
ESP_LOGI(TAG, "Initializing BM1397");
|
||||||
|
|
||||||
memset(asic_response_buffer, 0, SERIAL_BUF_SIZE);
|
|
||||||
|
|
||||||
esp_rom_gpio_pad_select_gpio(GPIO_ASIC_RESET);
|
esp_rom_gpio_pad_select_gpio(GPIO_ASIC_RESET);
|
||||||
gpio_set_direction(GPIO_ASIC_RESET, GPIO_MODE_OUTPUT);
|
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)
|
void BM1397_send_work(void *pvParameters, bm_job *next_bm_job)
|
||||||
{
|
{
|
||||||
|
|
||||||
GlobalState *GLOBAL_STATE = (GlobalState *)pvParameters;
|
GlobalState *GLOBAL_STATE = (GlobalState *)pvParameters;
|
||||||
|
|
||||||
job_packet job;
|
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);
|
_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
|
if (receive_work((uint8_t *)&asic_result, sizeof(asic_result)) == ESP_FAIL) {
|
||||||
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");
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t nonce_found = 0;
|
uint8_t nonce_found = 0;
|
||||||
uint32_t first_nonce = 0;
|
uint32_t first_nonce = 0;
|
||||||
|
|
||||||
uint8_t rx_job_id = asic_result->job_id & 0xfc;
|
uint8_t rx_job_id = asic_result.job_id & 0xfc;
|
||||||
uint8_t rx_midstate_index = asic_result->job_id & 0x03;
|
uint8_t rx_midstate_index = asic_result.job_id & 0x03;
|
||||||
|
|
||||||
GlobalState *GLOBAL_STATE = (GlobalState *)pvParameters;
|
GlobalState *GLOBAL_STATE = (GlobalState *)pvParameters;
|
||||||
if (GLOBAL_STATE->valid_jobs[rx_job_id] == 0)
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -469,26 +428,26 @@ task_result *BM1397_proccess_work(void *pvParameters)
|
|||||||
// most of the time it behavies however
|
// most of the time it behavies however
|
||||||
if (nonce_found == 0)
|
if (nonce_found == 0)
|
||||||
{
|
{
|
||||||
first_nonce = asic_result->nonce;
|
first_nonce = asic_result.nonce;
|
||||||
nonce_found = 1;
|
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
|
// stop if we've already seen this nonce
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (asic_result->nonce == prev_nonce)
|
if (asic_result.nonce == prev_nonce)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
prev_nonce = asic_result->nonce;
|
prev_nonce = asic_result.nonce;
|
||||||
}
|
}
|
||||||
|
|
||||||
result.job_id = rx_job_id;
|
result.job_id = rx_job_id;
|
||||||
result.nonce = asic_result->nonce;
|
result.nonce = asic_result.nonce;
|
||||||
result.rolled_version = rolled_version;
|
result.rolled_version = rolled_version;
|
||||||
|
|
||||||
return &result;
|
return &result;
|
||||||
|
@ -1,4 +1,14 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "common.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)
|
unsigned char _reverse_bits(unsigned char num)
|
||||||
{
|
{
|
||||||
@ -24,4 +34,95 @@ int _largest_power_of_two(int num)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return 1 << power;
|
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 <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "bm1397.h"
|
#define CRC5_MASK 0x1F
|
||||||
|
|
||||||
/* compute crc5 over given number of bytes */
|
/* compute crc5 over given number of bytes */
|
||||||
// adapted from https://mightydevices.com/index.php/2018/02/reverse-engineering-antminer-s1/
|
// 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 ASIC_BM1366_JOB_FREQUENCY_MS 2000
|
||||||
|
|
||||||
#define CRC5_MASK 0x1F
|
|
||||||
#define BM1366_ASIC_DIFFICULTY 256
|
#define BM1366_ASIC_DIFFICULTY 256
|
||||||
|
|
||||||
#define BM1366_SERIALTX_DEBUG false
|
#define BM1366_SERIALTX_DEBUG false
|
||||||
@ -36,14 +35,13 @@ typedef struct __attribute__((__packed__))
|
|||||||
} BM1366_job;
|
} BM1366_job;
|
||||||
|
|
||||||
uint8_t BM1366_init(uint64_t frequency, uint16_t asic_count);
|
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_send_work(void * GLOBAL_STATE, bm_job * next_bm_job);
|
||||||
void BM1366_set_job_difficulty_mask(int);
|
void BM1366_set_job_difficulty_mask(int);
|
||||||
void BM1366_set_version_mask(uint32_t version_mask);
|
void BM1366_set_version_mask(uint32_t version_mask);
|
||||||
int BM1366_set_max_baud(void);
|
int BM1366_set_max_baud(void);
|
||||||
int BM1366_set_default_baud(void);
|
int BM1366_set_default_baud(void);
|
||||||
void BM1366_send_hash_frequency(float frequency);
|
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_ */
|
#endif /* BM1366_H_ */
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
#define ASIC_BM1368_JOB_FREQUENCY_MS 500
|
#define ASIC_BM1368_JOB_FREQUENCY_MS 500
|
||||||
|
|
||||||
#define CRC5_MASK 0x1F
|
|
||||||
#define BM1368_ASIC_DIFFICULTY 256
|
#define BM1368_ASIC_DIFFICULTY 256
|
||||||
|
|
||||||
#define BM1368_SERIALTX_DEBUG false
|
#define BM1368_SERIALTX_DEBUG false
|
||||||
@ -36,15 +35,13 @@ typedef struct __attribute__((__packed__))
|
|||||||
} BM1368_job;
|
} BM1368_job;
|
||||||
|
|
||||||
uint8_t BM1368_init(uint64_t frequency, uint16_t asic_count);
|
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_send_work(void * GLOBAL_STATE, bm_job * next_bm_job);
|
||||||
void BM1368_set_job_difficulty_mask(int);
|
void BM1368_set_job_difficulty_mask(int);
|
||||||
void BM1368_set_version_mask(uint32_t version_mask);
|
void BM1368_set_version_mask(uint32_t version_mask);
|
||||||
int BM1368_set_max_baud(void);
|
int BM1368_set_max_baud(void);
|
||||||
int BM1368_set_default_baud(void);
|
int BM1368_set_default_baud(void);
|
||||||
bool BM1368_send_hash_frequency(float frequency);
|
void BM1368_send_hash_frequency(float frequency);
|
||||||
bool do_frequency_transition(float target_frequency);
|
bool BM1368_set_frequency(float target_freq);
|
||||||
task_result * BM1368_proccess_work(void * GLOBAL_STATE);
|
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 ASIC_BM1370_JOB_FREQUENCY_MS 500
|
||||||
|
|
||||||
#define CRC5_MASK 0x1F
|
|
||||||
#define BM1370_ASIC_DIFFICULTY 256
|
#define BM1370_ASIC_DIFFICULTY 256
|
||||||
|
|
||||||
#define BM1370_SERIALTX_DEBUG true
|
#define BM1370_SERIALTX_DEBUG true
|
||||||
@ -36,14 +35,13 @@ typedef struct __attribute__((__packed__))
|
|||||||
} BM1370_job;
|
} BM1370_job;
|
||||||
|
|
||||||
uint8_t BM1370_init(uint64_t frequency, uint16_t asic_count);
|
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_send_work(void * GLOBAL_STATE, bm_job * next_bm_job);
|
||||||
void BM1370_set_job_difficulty_mask(int);
|
void BM1370_set_job_difficulty_mask(int);
|
||||||
void BM1370_set_version_mask(uint32_t version_mask);
|
void BM1370_set_version_mask(uint32_t version_mask);
|
||||||
int BM1370_set_max_baud(void);
|
int BM1370_set_max_baud(void);
|
||||||
int BM1370_set_default_baud(void);
|
int BM1370_set_default_baud(void);
|
||||||
void BM1370_send_hash_frequency(int, float, float);
|
void BM1370_send_hash_frequency(float frequency);
|
||||||
task_result * BM1370_proccess_work(void * GLOBAL_STATE);
|
bool BM1370_set_frequency(float target_freq);
|
||||||
|
task_result * BM1370_process_work(void * GLOBAL_STATE);
|
||||||
|
|
||||||
#endif /* BM1370_H_ */
|
#endif /* BM1370_H_ */
|
||||||
|
@ -7,10 +7,9 @@
|
|||||||
|
|
||||||
#define ASIC_BM1397_JOB_FREQUENCY_MS 20 //not currently used
|
#define ASIC_BM1397_JOB_FREQUENCY_MS 20 //not currently used
|
||||||
|
|
||||||
#define CRC5_MASK 0x1F
|
|
||||||
#define BM1397_ASIC_DIFFICULTY 256
|
#define BM1397_ASIC_DIFFICULTY 256
|
||||||
|
|
||||||
#define BM1937_SERIALTX_DEBUG false
|
#define BM1937_SERIALTX_DEBUG true
|
||||||
#define BM1937_SERIALRX_DEBUG false
|
#define BM1937_SERIALRX_DEBUG false
|
||||||
#define BM1397_DEBUG_WORK false //causes insane amount of debug output
|
#define BM1397_DEBUG_WORK false //causes insane amount of debug output
|
||||||
#define BM1397_DEBUG_JOBS 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;
|
} job_packet;
|
||||||
|
|
||||||
uint8_t BM1397_init(uint64_t frequency, uint16_t asic_count);
|
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_send_work(void * GLOBAL_STATE, bm_job * next_bm_job);
|
||||||
void BM1397_set_job_difficulty_mask(int);
|
void BM1397_set_job_difficulty_mask(int);
|
||||||
void BM1397_set_version_mask(uint32_t version_mask);
|
void BM1397_set_version_mask(uint32_t version_mask);
|
||||||
int BM1397_set_max_baud(void);
|
int BM1397_set_max_baud(void);
|
||||||
int BM1397_set_default_baud(void);
|
int BM1397_set_default_baud(void);
|
||||||
void BM1397_send_hash_frequency(float frequency);
|
void BM1397_send_hash_frequency(float frequency);
|
||||||
task_result * BM1397_proccess_work(void * GLOBAL_STATE);
|
task_result * BM1397_process_work(void * GLOBAL_STATE);
|
||||||
|
|
||||||
#endif /* BM1397_H_ */
|
#endif /* BM1397_H_ */
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define COMMON_H_
|
#define COMMON_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "esp_err.h"
|
||||||
|
|
||||||
typedef struct __attribute__((__packed__))
|
typedef struct __attribute__((__packed__))
|
||||||
{
|
{
|
||||||
@ -13,4 +14,7 @@ typedef struct __attribute__((__packed__))
|
|||||||
unsigned char _reverse_bits(unsigned char num);
|
unsigned char _reverse_bits(unsigned char num);
|
||||||
int _largest_power_of_two(int 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_
|
#ifndef SERIAL_H_
|
||||||
#define SERIAL_H_
|
#define SERIAL_H_
|
||||||
|
|
||||||
#define SERIAL_BUF_SIZE 16
|
#include "esp_err.h"
|
||||||
#define CHUNK_SIZE 1024
|
|
||||||
|
|
||||||
int SERIAL_send(uint8_t *, int, bool);
|
int SERIAL_send(uint8_t *, int, bool);
|
||||||
esp_err_t SERIAL_init(void);
|
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);
|
void SERIAL_clear_buffer(void);
|
||||||
esp_err_t SERIAL_set_baud(int baud);
|
esp_err_t SERIAL_set_baud(int baud);
|
||||||
|
|
||||||
#endif /* SERIAL_H_ */
|
#endif /* SERIAL_H_ */
|
||||||
|
@ -15,6 +15,9 @@
|
|||||||
#include "connect.h"
|
#include "connect.h"
|
||||||
#include "main.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
|
#if CONFIG_ESP_WPA3_SAE_PWE_HUNT_AND_PECK
|
||||||
#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_HUNT_AND_PECK
|
#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_HUNT_AND_PECK
|
||||||
#define EXAMPLE_H2E_IDENTIFIER ""
|
#define EXAMPLE_H2E_IDENTIFIER ""
|
||||||
@ -51,34 +54,114 @@ static EventGroupHandle_t s_wifi_event_group;
|
|||||||
|
|
||||||
static const char * TAG = "wifi_station";
|
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 int s_retry_num = 0;
|
||||||
|
|
||||||
static char * _ip_addr_str;
|
static char * _ip_addr_str;
|
||||||
|
|
||||||
static void event_handler(void * arg, esp_event_base_t event_base, int32_t event_id, void * event_data)
|
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) {
|
if (event_base == WIFI_EVENT)
|
||||||
esp_wifi_connect();
|
{
|
||||||
MINER_set_wifi_status(WIFI_CONNECTING, 0, 0);
|
if (event_id == WIFI_EVENT_SCAN_DONE) {
|
||||||
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
esp_wifi_scan_get_ap_num(&ap_number);
|
||||||
//lookup the exact reason code
|
ESP_LOGI(TAG, "Wi-Fi Scan Done");
|
||||||
wifi_event_sta_disconnected_t* event = (wifi_event_sta_disconnected_t*) event_data;
|
if (esp_wifi_scan_get_ap_records(&ap_number, ap_info) != ESP_OK) {
|
||||||
if (event->reason == WIFI_REASON_ROAMING) {
|
ESP_LOGI(TAG, "Failed esp_wifi_scan_get_ap_records");
|
||||||
ESP_LOGI(TAG, "We are roaming, nothing to do");
|
}
|
||||||
|
is_scanning = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_scanning) {
|
||||||
|
ESP_LOGI(TAG, "Still scanning, ignore wifi event.");
|
||||||
return;
|
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
|
ESP_LOGI(TAG, "Could not connect to '%s' [rssi %d]: reason %d", event->ssid, event->rssi, event->reason);
|
||||||
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);
|
|
||||||
|
|
||||||
} 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;
|
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));
|
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;
|
wifi_auth_mode_t authmode;
|
||||||
|
|
||||||
if (strlen(wifi_pass) == 0) {
|
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;
|
authmode = WIFI_AUTH_OPEN;
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGI(TAG, "WiFi Password provided, using WPA2");
|
ESP_LOGI(TAG, "Wi-Fi Password provided, using WPA2");
|
||||||
authmode = WIFI_AUTH_WPA2_PSK;
|
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(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));
|
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();
|
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
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");
|
ESP_LOGI(TAG, "ESP_WIFI Access Point On");
|
||||||
wifi_init_softap();
|
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 */
|
/* Skip connection if SSID is null */
|
||||||
ESP_ERROR_CHECK(esp_wifi_start());
|
if (strlen(wifi_ssid) == 0) {
|
||||||
|
ESP_LOGI(TAG, "No WiFi SSID provided, skipping connection");
|
||||||
|
|
||||||
/* Disable power savings for best performance */
|
/* Start WiFi */
|
||||||
ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE));
|
ESP_ERROR_CHECK(esp_wifi_start());
|
||||||
|
|
||||||
/* Set Hostname */
|
/* Disable power savings for best performance */
|
||||||
esp_err_t err = esp_netif_set_hostname(esp_netif_sta, hostname);
|
ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE));
|
||||||
if (err != ERR_OK) {
|
|
||||||
ESP_LOGW(TAG, "esp_netif_set_hostname failed: %s", esp_err_to_name(err));
|
return;
|
||||||
} else {
|
} 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)
|
EventBits_t wifi_connect(void)
|
||||||
@ -257,4 +354,4 @@ EventBits_t wifi_connect(void)
|
|||||||
* happened. */
|
* happened. */
|
||||||
|
|
||||||
return bits;
|
return bits;
|
||||||
}
|
}
|
@ -5,6 +5,14 @@
|
|||||||
#include <lwip/netdb.h>
|
#include <lwip/netdb.h>
|
||||||
|
|
||||||
#include "freertos/event_groups.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_SSID CONFIG_ESP_WIFI_SSID
|
||||||
#define WIFI_PASS CONFIG_ESP_WIFI_PASSWORD
|
#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);
|
void wifi_init(const char * wifi_ssid, const char * wifi_pass, const char * hostname, char * ip_addr_str);
|
||||||
EventBits_t wifi_connect(void);
|
EventBits_t wifi_connect(void);
|
||||||
void generate_ssid(char * ssid);
|
void generate_ssid(char * ssid);
|
||||||
|
esp_err_t wifi_scan(wifi_ap_record_simple_t *ap_records, uint16_t *ap_count);
|
@ -62,25 +62,23 @@ typedef struct
|
|||||||
char * error_str;
|
char * error_str;
|
||||||
} StratumApiV1Message;
|
} StratumApiV1Message;
|
||||||
|
|
||||||
void STRATUM_V1_reset_uid();
|
|
||||||
|
|
||||||
void STRATUM_V1_initialize_buffer();
|
void STRATUM_V1_initialize_buffer();
|
||||||
|
|
||||||
char *STRATUM_V1_receive_jsonrpc_line(int sockfd);
|
char *STRATUM_V1_receive_jsonrpc_line(int sockfd);
|
||||||
|
|
||||||
int STRATUM_V1_subscribe(int socket, char * 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_parse(StratumApiV1Message *message, const char *stratum_json);
|
||||||
|
|
||||||
void STRATUM_V1_free_mining_notify(mining_notify *params);
|
void STRATUM_V1_free_mining_notify(mining_notify *params);
|
||||||
|
|
||||||
int STRATUM_V1_authenticate(int socket, const char *username, 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 char *extranonce_2, const uint32_t ntime, const uint32_t nonce,
|
||||||
const uint32_t version);
|
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);
|
char *extranonce_2_str = malloc(length * 2 + 1);
|
||||||
memset(extranonce_2_str, '0', length * 2);
|
memset(extranonce_2_str, '0', length * 2);
|
||||||
extranonce_2_str[length * 2] = '\0';
|
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)
|
if (length > 4)
|
||||||
{
|
{
|
||||||
extranonce_2_str[8] = '0';
|
extranonce_2_str[8] = '0';
|
||||||
|
@ -19,20 +19,9 @@ static const char * TAG = "stratum_api";
|
|||||||
static char * json_rpc_buffer = NULL;
|
static char * json_rpc_buffer = NULL;
|
||||||
static size_t json_rpc_buffer_size = 0;
|
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 *);
|
static void debug_stratum_tx(const char *);
|
||||||
int _parse_stratum_subscribe_result_message(const char * result_json_str, char ** extranonce, int * extranonce2_len);
|
int _parse_stratum_subscribe_result_message(const char * result_json_str, char ** extranonce, int * extranonce2_len);
|
||||||
|
|
||||||
void STRATUM_V1_reset_uid()
|
|
||||||
{
|
|
||||||
ESP_LOGI(TAG, "Resetting stratum uid");
|
|
||||||
|
|
||||||
send_uid = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void STRATUM_V1_initialize_buffer()
|
void STRATUM_V1_initialize_buffer()
|
||||||
{
|
{
|
||||||
json_rpc_buffer = malloc(BUFFER_SIZE);
|
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 * error_json = cJSON_GetObjectItem(json, "error");
|
||||||
cJSON * reject_reason_json = cJSON_GetObjectItem(json, "reject-reason");
|
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) {
|
if (result_json == NULL) {
|
||||||
message->response_success = false;
|
message->response_success = false;
|
||||||
|
message->error_str = strdup("unknown");
|
||||||
//if it's an error, then it's a fail
|
|
||||||
|
// if it's an error, then it's a fail
|
||||||
} else if (!cJSON_IsNull(error_json)) {
|
} else if (!cJSON_IsNull(error_json)) {
|
||||||
|
message->response_success = false;
|
||||||
|
message->error_str = strdup("unknown");
|
||||||
if (parsed_id < 5) {
|
if (parsed_id < 5) {
|
||||||
result = STRATUM_RESULT_SETUP;
|
result = STRATUM_RESULT_SETUP;
|
||||||
} else {
|
} 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)) {
|
} else if (cJSON_IsBool(result_json)) {
|
||||||
if (parsed_id < 5) {
|
if (parsed_id < 5) {
|
||||||
result = STRATUM_RESULT_SETUP;
|
result = STRATUM_RESULT_SETUP;
|
||||||
@ -181,6 +172,7 @@ void STRATUM_V1_parse(StratumApiV1Message * message, const char * stratum_json)
|
|||||||
message->response_success = true;
|
message->response_success = true;
|
||||||
} else {
|
} else {
|
||||||
message->response_success = false;
|
message->response_success = false;
|
||||||
|
message->error_str = strdup("unknown");
|
||||||
if (cJSON_IsString(reject_reason_json)) {
|
if (cJSON_IsString(reject_reason_json)) {
|
||||||
message->error_str = strdup(cJSON_GetStringValue(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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int STRATUM_V1_subscribe(int socket, char * model)
|
int STRATUM_V1_subscribe(int socket, int send_uid, char * model)
|
||||||
{
|
{
|
||||||
// Subscribe
|
// Subscribe
|
||||||
char subscribe_msg[BUFFER_SIZE];
|
char subscribe_msg[BUFFER_SIZE];
|
||||||
const esp_app_desc_t *app_desc = esp_app_get_description();
|
const esp_app_desc_t *app_desc = esp_app_get_description();
|
||||||
const char *version = app_desc->version;
|
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);
|
debug_stratum_tx(subscribe_msg);
|
||||||
|
|
||||||
return write(socket, subscribe_msg, strlen(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];
|
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);
|
debug_stratum_tx(difficulty_msg);
|
||||||
|
|
||||||
return write(socket, difficulty_msg, strlen(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];
|
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);
|
pass);
|
||||||
debug_stratum_tx(authorize_msg);
|
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 ntime The hex-encoded time value use in the block header.
|
||||||
/// @param extranonce_2 The hex-encoded value of extra nonce 2.
|
/// @param extranonce_2 The hex-encoded value of extra nonce 2.
|
||||||
/// @param nonce The hex-encoded nonce value to use in the block header.
|
/// @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,
|
int STRATUM_V1_submit_share(int socket, int send_uid, const char * username, const char * jobid,
|
||||||
const uint32_t nonce, const uint32_t version)
|
const char * extranonce_2, const uint32_t ntime,
|
||||||
|
const uint32_t nonce, const uint32_t version)
|
||||||
{
|
{
|
||||||
char submit_msg[BUFFER_SIZE];
|
char submit_msg[BUFFER_SIZE];
|
||||||
sprintf(submit_msg,
|
sprintf(submit_msg,
|
||||||
"{\"id\": %d, \"method\": \"mining.submit\", \"params\": [\"%s\", \"%s\", \"%s\", \"%08lx\", \"%08lx\", \"%08lx\"]}\n",
|
"{\"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);
|
debug_stratum_tx(submit_msg);
|
||||||
|
|
||||||
return write(socket, submit_msg, strlen(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];
|
char configure_msg[BUFFER_SIZE * 2];
|
||||||
sprintf(configure_msg,
|
sprintf(configure_msg,
|
||||||
"{\"id\": %d, \"method\": \"mining.configure\", \"params\": [[\"version-rolling\"], {\"version-rolling.mask\": "
|
"{\"id\": %d, \"method\": \"mining.configure\", \"params\": [[\"version-rolling\"], {\"version-rolling.mask\": "
|
||||||
"\"ffffffff\"}]}\n",
|
"\"ffffffff\"}]}\n",
|
||||||
send_uid++);
|
send_uid);
|
||||||
debug_stratum_tx(configure_msg);
|
debug_stratum_tx(configure_msg);
|
||||||
|
|
||||||
return write(socket, configure_msg, strlen(configure_msg));
|
return write(socket, configure_msg, strlen(configure_msg));
|
||||||
|
@ -138,7 +138,7 @@ TEST_CASE("Test extranonce 2 generation", "[mining extranonce2]")
|
|||||||
free(fifth);
|
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;
|
mining_notify notify_message;
|
||||||
notify_message.prev_block_hash = "d02b10fc0d4711eae1a805af50a8a83312a2215e00017f2b0000000000000000";
|
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_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;
|
mining_notify notify_message;
|
||||||
notify_message.prev_block_hash = "0c859545a3498373a57452fac22eb7113df2a465000543520000000000000000";
|
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);
|
mbedtls_sha256_update(&midstate, data, 64);
|
||||||
|
|
||||||
// memcpy(dest, midstate.state, 32);
|
// memcpy(dest, midstate.state, 32);
|
||||||
flip32bytes(dest, midstate.state);
|
flip32bytes(dest, midstate.state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void swap_endian_words(const char *hex_words, uint8_t *output)
|
void swap_endian_words(const char *hex_words, uint8_t *output)
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
key,type,encoding,value
|
key,type,encoding,value
|
||||||
main,namespace,,
|
main,namespace,,
|
||||||
hostname,data,string,bitaxe
|
hostname,data,string,bitaxe
|
||||||
wifissid,data,string,myssid
|
wifissid,data,string,
|
||||||
wifipass,data,string,password
|
wifipass,data,string,
|
||||||
stratumurl,data,string,public-pool.io
|
stratumurl,data,string,public-pool.io
|
||||||
stratumport,data,u16,21496
|
stratumport,data,u16,21496
|
||||||
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
key,type,encoding,value
|
key,type,encoding,value
|
||||||
main,namespace,,
|
main,namespace,,
|
||||||
hostname,data,string,bitaxe
|
hostname,data,string,bitaxe
|
||||||
wifissid,data,string,myssid
|
wifissid,data,string,
|
||||||
wifipass,data,string,password
|
wifipass,data,string,
|
||||||
stratumurl,data,string,public-pool.io
|
stratumurl,data,string,public-pool.io
|
||||||
stratumport,data,u16,21496
|
stratumport,data,u16,21496
|
||||||
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
key,type,encoding,value
|
key,type,encoding,value
|
||||||
main,namespace,,
|
main,namespace,,
|
||||||
hostname,data,string,bitaxe
|
hostname,data,string,bitaxe
|
||||||
wifissid,data,string,myssid
|
wifissid,data,string,
|
||||||
wifipass,data,string,password
|
wifipass,data,string,
|
||||||
stratumurl,data,string,public-pool.io
|
stratumurl,data,string,public-pool.io
|
||||||
stratumport,data,u16,21496
|
stratumport,data,u16,21496
|
||||||
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
key,type,encoding,value
|
key,type,encoding,value
|
||||||
main,namespace,,
|
main,namespace,,
|
||||||
hostname,data,string,bitaxe
|
hostname,data,string,bitaxe
|
||||||
wifissid,data,string,myssid
|
wifissid,data,string,
|
||||||
wifipass,data,string,password
|
wifipass,data,string,
|
||||||
stratumurl,data,string,public-pool.io
|
stratumurl,data,string,public-pool.io
|
||||||
stratumport,data,u16,21496
|
stratumport,data,u16,21496
|
||||||
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
key,type,encoding,value
|
key,type,encoding,value
|
||||||
main,namespace,,
|
main,namespace,,
|
||||||
hostname,data,string,bitaxe
|
hostname,data,string,bitaxe
|
||||||
wifissid,data,string,myssid
|
wifissid,data,string,
|
||||||
wifipass,data,string,password
|
wifipass,data,string,
|
||||||
stratumurl,data,string,public-pool.io
|
stratumurl,data,string,public-pool.io
|
||||||
stratumport,data,u16,21496
|
stratumport,data,u16,21496
|
||||||
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
key,type,encoding,value
|
key,type,encoding,value
|
||||||
main,namespace,,
|
main,namespace,,
|
||||||
hostname,data,string,bitaxe
|
hostname,data,string,bitaxe
|
||||||
wifissid,data,string,myssid
|
wifissid,data,string,
|
||||||
wifipass,data,string,password
|
wifipass,data,string,
|
||||||
stratumurl,data,string,public-pool.io
|
stratumurl,data,string,public-pool.io
|
||||||
stratumport,data,u16,21496
|
stratumport,data,u16,21496
|
||||||
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
key,type,encoding,value
|
key,type,encoding,value
|
||||||
main,namespace,,
|
main,namespace,,
|
||||||
hostname,data,string,bitaxe
|
hostname,data,string,bitaxe
|
||||||
wifissid,data,string,myssid
|
wifissid,data,string,
|
||||||
wifipass,data,string,password
|
wifipass,data,string,
|
||||||
stratumurl,data,string,public-pool.io
|
stratumurl,data,string,public-pool.io
|
||||||
stratumport,data,u16,21496
|
stratumport,data,u16,21496
|
||||||
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
key,type,encoding,value
|
key,type,encoding,value
|
||||||
main,namespace,,
|
main,namespace,,
|
||||||
hostname,data,string,bitaxe
|
hostname,data,string,bitaxe
|
||||||
wifissid,data,string,myssid
|
wifissid,data,string,
|
||||||
wifipass,data,string,password
|
wifipass,data,string,
|
||||||
stratumurl,data,string,public-pool.io
|
stratumurl,data,string,public-pool.io
|
||||||
stratumport,data,u16,21496
|
stratumport,data,u16,21496
|
||||||
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
key,type,encoding,value
|
key,type,encoding,value
|
||||||
main,namespace,,
|
main,namespace,,
|
||||||
hostname,data,string,bitaxe
|
hostname,data,string,bitaxe
|
||||||
wifissid,data,string,myssid
|
wifissid,data,string,
|
||||||
wifipass,data,string,password
|
wifipass,data,string,
|
||||||
stratumurl,data,string,public-pool.io
|
stratumurl,data,string,public-pool.io
|
||||||
stratumport,data,u16,21496
|
stratumport,data,u16,21496
|
||||||
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
key,type,encoding,value
|
key,type,encoding,value
|
||||||
main,namespace,,
|
main,namespace,,
|
||||||
hostname,data,string,bitaxe
|
hostname,data,string,bitaxe
|
||||||
wifissid,data,string,myssid
|
wifissid,data,string,
|
||||||
wifipass,data,string,password
|
wifipass,data,string,
|
||||||
stratumurl,data,string,public-pool.io
|
stratumurl,data,string,public-pool.io
|
||||||
stratumport,data,u16,21496
|
stratumport,data,u16,21496
|
||||||
stratumuser,data,string,bc1qnp980s5fpp8l94p5cvttmtdqy8rvrq74qly2yrfmzkdsntqzlc5qkc4rkq.bitaxe
|
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
|
## 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
|
- Power up your bitaxe via the barrel connector
|
||||||
- attach your bitaxe USB to your computer
|
- 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.
|
- on PC it will prolly be one of those COM ports. Good luck.
|
||||||
- Select the proper serial port and then click connect
|
- 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`
|
- 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
|
- Down below click the "Program" button
|
||||||
- Wait paitiently.
|
- Wait paitiently.
|
||||||
- Keep waiting until the console on ESP Tool says "Leaving..."
|
- Keep waiting until the console on ESP Tool says "Leaving..."
|
||||||
|
@ -1,18 +1,13 @@
|
|||||||
idf_component_register(
|
idf_component_register(
|
||||||
SRCS
|
SRCS
|
||||||
"adc.c"
|
"adc.c"
|
||||||
"DS4432U.c"
|
|
||||||
"EMC2101.c"
|
|
||||||
"i2c_bitaxe.c"
|
"i2c_bitaxe.c"
|
||||||
"INA260.c"
|
|
||||||
"main.c"
|
"main.c"
|
||||||
"nvs_config.c"
|
"nvs_config.c"
|
||||||
"display.c"
|
"display.c"
|
||||||
"screen.c"
|
"screen.c"
|
||||||
"input.c"
|
"input.c"
|
||||||
"system.c"
|
"system.c"
|
||||||
"TPS546.c"
|
|
||||||
"vcore.c"
|
|
||||||
"work_queue.c"
|
"work_queue.c"
|
||||||
"nvs_device.c"
|
"nvs_device.c"
|
||||||
"lv_font_portfolio-6x8.c"
|
"lv_font_portfolio-6x8.c"
|
||||||
@ -25,6 +20,15 @@ SRCS
|
|||||||
"./tasks/asic_task.c"
|
"./tasks/asic_task.c"
|
||||||
"./tasks/asic_result_task.c"
|
"./tasks/asic_result_task.c"
|
||||||
"./tasks/power_management_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
|
INCLUDE_DIRS
|
||||||
"."
|
"."
|
||||||
@ -35,6 +39,8 @@ INCLUDE_DIRS
|
|||||||
"../components/connect/include"
|
"../components/connect/include"
|
||||||
"../components/dns_server/include"
|
"../components/dns_server/include"
|
||||||
"../components/stratum/include"
|
"../components/stratum/include"
|
||||||
|
"thermal"
|
||||||
|
"power"
|
||||||
|
|
||||||
PRIV_REQUIRES
|
PRIV_REQUIRES
|
||||||
"app_update"
|
"app_update"
|
||||||
@ -52,6 +58,8 @@ PRIV_REQUIRES
|
|||||||
"spiffs"
|
"spiffs"
|
||||||
"vfs"
|
"vfs"
|
||||||
"esp_driver_i2c"
|
"esp_driver_i2c"
|
||||||
|
|
||||||
|
EMBED_FILES "http_server/recovery_page.html"
|
||||||
)
|
)
|
||||||
|
|
||||||
idf_build_set_property(COMPILE_OPTIONS "-DLV_CONF_INCLUDE_SIMPLE=1" APPEND)
|
idf_build_set_property(COMPILE_OPTIONS "-DLV_CONF_INCLUDE_SIMPLE=1" APPEND)
|
||||||
|
@ -27,6 +27,7 @@ typedef enum
|
|||||||
DEVICE_ULTRA,
|
DEVICE_ULTRA,
|
||||||
DEVICE_SUPRA,
|
DEVICE_SUPRA,
|
||||||
DEVICE_GAMMA,
|
DEVICE_GAMMA,
|
||||||
|
DEVICE_GAMMATURBO,
|
||||||
} DeviceModel;
|
} DeviceModel;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
@ -38,15 +39,20 @@ typedef enum
|
|||||||
ASIC_BM1370,
|
ASIC_BM1370,
|
||||||
} AsicModel;
|
} AsicModel;
|
||||||
|
|
||||||
typedef struct
|
// typedef struct
|
||||||
{
|
// {
|
||||||
uint8_t (*init_fn)(uint64_t, uint16_t);
|
// uint8_t (*init_fn)(uint64_t, uint16_t);
|
||||||
task_result * (*receive_result_fn)(void * GLOBAL_STATE);
|
// task_result * (*receive_result_fn)(void * GLOBAL_STATE);
|
||||||
int (*set_max_baud_fn)(void);
|
// int (*set_max_baud_fn)(void);
|
||||||
void (*set_difficulty_mask_fn)(int);
|
// void (*set_difficulty_mask_fn)(int);
|
||||||
void (*send_work_fn)(void * GLOBAL_STATE, bm_job * next_bm_job);
|
// void (*send_work_fn)(void * GLOBAL_STATE, bm_job * next_bm_job);
|
||||||
void (*set_version_mask)(uint32_t);
|
// void (*set_version_mask)(uint32_t);
|
||||||
} AsicFunctions;
|
// } AsicFunctions;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char message[64];
|
||||||
|
uint32_t count;
|
||||||
|
} RejectedReasonStat;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -59,6 +65,8 @@ typedef struct
|
|||||||
int64_t start_time;
|
int64_t start_time;
|
||||||
uint64_t shares_accepted;
|
uint64_t shares_accepted;
|
||||||
uint64_t shares_rejected;
|
uint64_t shares_rejected;
|
||||||
|
RejectedReasonStat rejected_reason_stats[10];
|
||||||
|
int rejected_reason_stats_count;
|
||||||
int screen_page;
|
int screen_page;
|
||||||
uint64_t best_nonce_diff;
|
uint64_t best_nonce_diff;
|
||||||
char best_diff_string[DIFF_STRING_SIZE];
|
char best_diff_string[DIFF_STRING_SIZE];
|
||||||
@ -74,10 +82,17 @@ typedef struct
|
|||||||
char * fallback_pool_url;
|
char * fallback_pool_url;
|
||||||
uint16_t pool_port;
|
uint16_t pool_port;
|
||||||
uint16_t fallback_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;
|
bool is_using_fallback;
|
||||||
uint16_t overheat_mode;
|
uint16_t overheat_mode;
|
||||||
uint32_t lastClockSync;
|
uint32_t lastClockSync;
|
||||||
bool is_screen_active;
|
bool is_screen_active;
|
||||||
|
bool is_firmware_update;
|
||||||
|
char firmware_update_filename[20];
|
||||||
|
char firmware_update_status[20];
|
||||||
} SystemModule;
|
} SystemModule;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@ -94,10 +109,8 @@ typedef struct
|
|||||||
char * device_model_str;
|
char * device_model_str;
|
||||||
int board_version;
|
int board_version;
|
||||||
AsicModel asic_model;
|
AsicModel asic_model;
|
||||||
|
bool valid_model;
|
||||||
char * asic_model_str;
|
char * asic_model_str;
|
||||||
uint16_t asic_count;
|
|
||||||
uint16_t voltage_domain;
|
|
||||||
AsicFunctions ASIC_functions;
|
|
||||||
double asic_job_frequency_ms;
|
double asic_job_frequency_ms;
|
||||||
uint32_t ASIC_difficulty;
|
uint32_t ASIC_difficulty;
|
||||||
|
|
||||||
@ -122,7 +135,13 @@ typedef struct
|
|||||||
bool new_stratum_version_rolling_msg;
|
bool new_stratum_version_rolling_msg;
|
||||||
|
|
||||||
int sock;
|
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 ASIC_initalized;
|
||||||
|
bool psram_is_available;
|
||||||
} GlobalState;
|
} GlobalState;
|
||||||
|
|
||||||
#endif /* GLOBAL_STATE_H_ */
|
#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",
|
"name": "axe-os",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=22.0.0"
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"ng": "ng",
|
"ng": "ng",
|
||||||
"start": "ng serve",
|
"start": "ng serve",
|
||||||
@ -11,31 +14,32 @@
|
|||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/animations": "17.3.12",
|
"@angular/animations": "18.2.13",
|
||||||
"@angular/common": "17.3.12",
|
"@angular/common": "18.2.13",
|
||||||
"@angular/compiler": "17.3.12",
|
"@angular/compiler": "18.2.13",
|
||||||
"@angular/core": "17.3.12",
|
"@angular/core": "18.2.13",
|
||||||
"@angular/forms": "17.3.12",
|
"@angular/forms": "18.2.13",
|
||||||
"@angular/platform-browser": "17.3.12",
|
"@angular/platform-browser": "18.2.13",
|
||||||
"@angular/platform-browser-dynamic": "17.3.12",
|
"@angular/platform-browser-dynamic": "18.2.13",
|
||||||
"@angular/router": "17.3.12",
|
"@angular/router": "18.2.13",
|
||||||
|
"@xterm/xterm": "^5.5.0",
|
||||||
"chart.js": "^4.4.7",
|
"chart.js": "^4.4.7",
|
||||||
"chartjs-adapter-moment": "^1.0.1",
|
"chartjs-adapter-moment": "^1.0.1",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"ngx-toastr": "^17.0.2",
|
"ngx-toastr": "^19.0.0",
|
||||||
"primeflex": "^3.3.1",
|
"primeflex": "^3.3.1",
|
||||||
"primeicons": "^7.0.0",
|
"primeicons": "^7.0.0",
|
||||||
"primeng": "^17.18.15",
|
"primeng": "^17.18.15",
|
||||||
"rxjs": "~7.8.1",
|
"rxjs": "~7.8.1",
|
||||||
"tslib": "^2.8.1",
|
"tslib": "^2.8.1",
|
||||||
"xterm": "^5.3.0",
|
|
||||||
"zone.js": "~0.14.10"
|
"zone.js": "~0.14.10"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@angular-devkit/build-angular": "^17.3.11",
|
"@angular-devkit/build-angular": "^18.2.14",
|
||||||
"@angular/cli": "17.3.11",
|
"@angular/cli": "18.2.14",
|
||||||
"@angular/compiler-cli": "17.3.12",
|
"@angular/compiler-cli": "18.2.13",
|
||||||
"@types/jasmine": "~5.1.5",
|
"@types/jasmine": "~5.1.5",
|
||||||
|
"chokidar": "^3.6.0",
|
||||||
"gzipper": "^8.2.0",
|
"gzipper": "^8.2.0",
|
||||||
"jasmine-core": "~5.5.0",
|
"jasmine-core": "~5.5.0",
|
||||||
"karma": "~6.4.4",
|
"karma": "~6.4.4",
|
||||||
@ -43,7 +47,7 @@
|
|||||||
"karma-coverage": "~2.2.1",
|
"karma-coverage": "~2.2.1",
|
||||||
"karma-jasmine": "~5.1.0",
|
"karma-jasmine": "~5.1.0",
|
||||||
"karma-jasmine-html-reporter": "~2.1.0",
|
"karma-jasmine-html-reporter": "~2.1.0",
|
||||||
"typescript": "~5.4.5",
|
"typescript": "~5.5.4",
|
||||||
"webpack-bundle-analyzer": "^4.10.2"
|
"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 { SettingsComponent } from './components/settings/settings.component';
|
||||||
import { NetworkComponent } from './components/network/network.component';
|
import { NetworkComponent } from './components/network/network.component';
|
||||||
import { SwarmComponent } from './components/swarm/swarm.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 { AppLayoutComponent } from './layout/app.layout.component';
|
||||||
|
import { ApModeGuard } from './guards/ap-mode.guard';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: 'ap',
|
||||||
|
component: AppLayoutComponent,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: NetworkComponent
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
component: AppLayoutComponent,
|
component: AppLayoutComponent,
|
||||||
|
canActivate: [ApModeGuard],
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
@ -32,6 +46,14 @@ const routes: Routes = [
|
|||||||
{
|
{
|
||||||
path: 'swarm',
|
path: 'swarm',
|
||||||
component: SwarmComponent
|
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 { AppRoutingModule } from './app-routing.module';
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
import { EditComponent } from './components/edit/edit.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 { NetworkEditComponent } from './components/network-edit/network.edit.component';
|
||||||
import { HomeComponent } from './components/home/home.component';
|
import { HomeComponent } from './components/home/home.component';
|
||||||
import { LoadingComponent } from './components/loading/loading.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 { NetworkComponent } from './components/network/network.component';
|
||||||
import { SettingsComponent } from './components/settings/settings.component';
|
import { SettingsComponent } from './components/settings/settings.component';
|
||||||
import { SwarmComponent } from './components/swarm/swarm.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 { AppLayoutModule } from './layout/app.layout.module';
|
||||||
import { ANSIPipe } from './pipes/ansi.pipe';
|
import { ANSIPipe } from './pipes/ansi.pipe';
|
||||||
import { DateAgoPipe } from './pipes/date-ago.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 { PrimeNGModule } from './prime-ng.module';
|
||||||
import { MessageModule } from 'primeng/message';
|
import { MessageModule } from 'primeng/message';
|
||||||
import { TooltipModule } from 'primeng/tooltip';
|
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 = [
|
const components = [
|
||||||
AppComponent,
|
AppComponent,
|
||||||
@ -35,7 +40,8 @@ const components = [
|
|||||||
LoadingComponent,
|
LoadingComponent,
|
||||||
NetworkComponent,
|
NetworkComponent,
|
||||||
SettingsComponent,
|
SettingsComponent,
|
||||||
LogsComponent
|
LogsComponent,
|
||||||
|
PoolComponent
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@ -47,7 +53,10 @@ const components = [
|
|||||||
SwarmComponent,
|
SwarmComponent,
|
||||||
SettingsComponent,
|
SettingsComponent,
|
||||||
HashSuffixPipe,
|
HashSuffixPipe,
|
||||||
ThemeConfigComponent
|
ThemeConfigComponent,
|
||||||
|
DesignComponent,
|
||||||
|
PoolComponent,
|
||||||
|
DialogListComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
@ -63,10 +72,14 @@ const components = [
|
|||||||
PrimeNGModule,
|
PrimeNGModule,
|
||||||
AppLayoutModule,
|
AppLayoutModule,
|
||||||
MessageModule,
|
MessageModule,
|
||||||
TooltipModule
|
TooltipModule,
|
||||||
|
DialogModule,
|
||||||
|
DynamicDialogModule
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: LocationStrategy, useClass: HashLocationStrategy },
|
{ provide: LocationStrategy, useClass: HashLocationStrategy },
|
||||||
|
DialogService,
|
||||||
|
PrimeDialogService
|
||||||
],
|
],
|
||||||
bootstrap: [AppComponent]
|
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">
|
<div class="col-12">
|
||||||
<h6>Theme Colors</h6>
|
<h6>Theme Colors</h6>
|
||||||
<div class="grid">
|
<div class="grid gap-2">
|
||||||
<div *ngFor="let theme of themes" class="col-3">
|
<div *ngFor="let theme of themes" class="col-2">
|
||||||
<button pButton [class]="'p-button-rounded p-button-text color-dot'"
|
<button pButton [class]="'p-button-rounded p-button-text color-dot'"
|
||||||
[style.backgroundColor]="theme.primaryColor"
|
[style.backgroundColor]="theme.primaryColor"
|
||||||
style="width: 2rem; height: 2rem; border: none;"
|
style="width: 2rem; height: 2rem; border: none;"
|
||||||
@ -52,6 +52,38 @@ interface ThemeOption {
|
|||||||
export class ThemeConfigComponent implements OnInit {
|
export class ThemeConfigComponent implements OnInit {
|
||||||
selectedScheme: string;
|
selectedScheme: string;
|
||||||
themes: ThemeOption[] = [
|
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',
|
name: 'Red',
|
||||||
primaryColor: '#F80421',
|
primaryColor: '#F80421',
|
@ -1,73 +1,11 @@
|
|||||||
<ng-container *ngIf="form != null">
|
<ng-container *ngIf="form != null">
|
||||||
<form [formGroup]="form">
|
<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">
|
<div class="field grid p-fluid">
|
||||||
<label class="col-12 mb-2 md:col-2 md:mb-0" htmlFor="frequency">Frequency</label>
|
<label class="col-12 mb-2 md:col-2 md:mb-0" htmlFor="frequency">Frequency</label>
|
||||||
<div class="col-12 md:col-10">
|
<div class="col-12 md:col-10">
|
||||||
@ -83,7 +21,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container *ngIf="devToolsOpen === true">
|
<ng-container *ngIf="settingsUnlocked === true">
|
||||||
|
|
||||||
<div class="field grid p-fluid">
|
<div class="field grid p-fluid">
|
||||||
<label htmlFor="frequency" class="col-12 mb-2 md:col-2 md:mb-0">Frequency</label>
|
<label htmlFor="frequency" class="col-12 mb-2 md:col-2 md:mb-0">Frequency</label>
|
||||||
@ -115,7 +53,7 @@
|
|||||||
<div class="field-checkbox">
|
<div class="field-checkbox">
|
||||||
<p-checkbox name="flipscreen" formControlName="flipscreen" inputId="flipscreen"
|
<p-checkbox name="flipscreen" formControlName="flipscreen" inputId="flipscreen"
|
||||||
[binary]="true"></p-checkbox>
|
[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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -123,7 +61,7 @@
|
|||||||
<div class="field-checkbox">
|
<div class="field-checkbox">
|
||||||
<p-checkbox name="invertfanpolarity" formControlName="invertfanpolarity" inputId="invertfanpolarity"
|
<p-checkbox name="invertfanpolarity" formControlName="invertfanpolarity" inputId="invertfanpolarity"
|
||||||
[binary]="true"></p-checkbox>
|
[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>
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
@ -153,6 +91,11 @@
|
|||||||
|
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
<button pButton [disabled]="!savedChanges" (click)="restart()">Restart</button>
|
<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>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import { startWith, Subject, takeUntil } from 'rxjs';
|
|||||||
import { LoadingService } from 'src/app/services/loading.service';
|
import { LoadingService } from 'src/app/services/loading.service';
|
||||||
import { SystemService } from 'src/app/services/system.service';
|
import { SystemService } from 'src/app/services/system.service';
|
||||||
import { eASICModel } from 'src/models/enum/eASICModel';
|
import { eASICModel } from 'src/models/enum/eASICModel';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-edit',
|
selector: 'app-edit',
|
||||||
@ -20,9 +21,11 @@ export class EditComponent implements OnInit, OnDestroy {
|
|||||||
public websiteUpdateProgress: number | null = null;
|
public websiteUpdateProgress: number | null = null;
|
||||||
|
|
||||||
public savedChanges: boolean = false;
|
public savedChanges: boolean = false;
|
||||||
public devToolsOpen: boolean = false;
|
public settingsUnlocked: boolean = false;
|
||||||
public eASICModel = eASICModel;
|
public eASICModel = eASICModel;
|
||||||
public ASICModel!: eASICModel;
|
public ASICModel!: eASICModel;
|
||||||
|
public restrictedModels: eASICModel[] = Object.values(eASICModel)
|
||||||
|
.filter((v): v is eASICModel => typeof v === 'string');
|
||||||
|
|
||||||
@Input() uri = '';
|
@Input() uri = '';
|
||||||
|
|
||||||
@ -122,10 +125,44 @@ export class EditComponent implements OnInit, OnDestroy {
|
|||||||
private fb: FormBuilder,
|
private fb: FormBuilder,
|
||||||
private systemService: SystemService,
|
private systemService: SystemService,
|
||||||
private toastr: ToastrService,
|
private toastr: ToastrService,
|
||||||
private loadingService: LoadingService
|
private loadingService: LoadingService,
|
||||||
|
private route: ActivatedRoute,
|
||||||
) {
|
) {
|
||||||
window.addEventListener('resize', this.checkDevTools.bind(this));
|
// Check URL parameter for settings unlock
|
||||||
this.checkDevTools();
|
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 {
|
ngOnInit(): void {
|
||||||
@ -136,33 +173,19 @@ export class EditComponent implements OnInit, OnDestroy {
|
|||||||
)
|
)
|
||||||
.subscribe(info => {
|
.subscribe(info => {
|
||||||
this.ASICModel = info.ASICModel;
|
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({
|
this.form = this.fb.group({
|
||||||
flipscreen: [info.flipscreen == 1],
|
flipscreen: [info.flipscreen == 1],
|
||||||
invertscreen: [info.invertscreen == 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]],
|
coreVoltage: [info.coreVoltage, [Validators.required]],
|
||||||
frequency: [info.frequency, [Validators.required]],
|
frequency: [info.frequency, [Validators.required]],
|
||||||
autofanspeed: [info.autofanspeed == 1, [Validators.required]],
|
autofanspeed: [info.autofanspeed == 1, [Validators.required]],
|
||||||
@ -185,22 +208,10 @@ export class EditComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
window.removeEventListener('resize', this.checkDevTools.bind(this));
|
|
||||||
this.destroy$.next();
|
this.destroy$.next();
|
||||||
this.destroy$.complete();
|
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() {
|
public updateSystem() {
|
||||||
|
|
||||||
const form = this.form.getRawValue();
|
const form = this.form.getRawValue();
|
||||||
@ -213,21 +224,18 @@ export class EditComponent implements OnInit, OnDestroy {
|
|||||||
.pipe(this.loadingService.lockUIUntilComplete())
|
.pipe(this.loadingService.lockUIUntilComplete())
|
||||||
.subscribe({
|
.subscribe({
|
||||||
next: () => {
|
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;
|
this.savedChanges = true;
|
||||||
},
|
},
|
||||||
error: (err: HttpErrorResponse) => {
|
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;
|
this.savedChanges = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
showStratumPassword: boolean = false;
|
|
||||||
toggleStratumPasswordVisibility() {
|
|
||||||
this.showStratumPassword = !this.showStratumPassword;
|
|
||||||
}
|
|
||||||
|
|
||||||
showWifiPassword: boolean = false;
|
showWifiPassword: boolean = false;
|
||||||
toggleWifiPasswordVisibility() {
|
toggleWifiPasswordVisibility() {
|
||||||
this.showWifiPassword = !this.showWifiPassword;
|
this.showWifiPassword = !this.showWifiPassword;
|
||||||
@ -238,9 +246,18 @@ export class EditComponent implements OnInit, OnDestroy {
|
|||||||
this.updateSystem();
|
this.updateSystem();
|
||||||
}
|
}
|
||||||
|
|
||||||
showFallbackStratumPassword: boolean = false;
|
toggleOverclockMode(enable: boolean) {
|
||||||
toggleFallbackStratumPasswordVisibility() {
|
this.settingsUnlocked = enable;
|
||||||
this.showFallbackStratumPassword = !this.showFallbackStratumPassword;
|
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() {
|
public restart() {
|
||||||
@ -248,10 +265,12 @@ export class EditComponent implements OnInit, OnDestroy {
|
|||||||
.pipe(this.loadingService.lockUIUntilComplete())
|
.pipe(this.loadingService.lockUIUntilComplete())
|
||||||
.subscribe({
|
.subscribe({
|
||||||
next: () => {
|
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) => {
|
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 class="flex justify-content-between mb-3">
|
||||||
<div>
|
<div>
|
||||||
<span class="block text-500 font-medium mb-3">Hash Rate</span>
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ng-container *ngIf="expectedHashRate$ | async as expectedHashRate">
|
|
||||||
<span class="text-green-500 font-medium">{{expectedHashRate * 1000000000 |
|
<ng-container>
|
||||||
hashSuffix}}</span>
|
Average:
|
||||||
<span class="text-500"> expected</span>
|
<span class="text-green-500 font-medium">
|
||||||
|
{{calculateAverage(hashrateData) | hashSuffix}}
|
||||||
|
</span>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
<div class="text-500 text-xs" *ngIf="expectedHashRate$ | async as expectedHashRate">
|
||||||
|
Expected: {{expectedHashRate * 1000000000 | hashSuffix}}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 md:col-6 xl:col-3">
|
<div class="col-12 md:col-6 xl:col-3">
|
||||||
@ -35,20 +44,24 @@
|
|||||||
<div class="flex justify-content-between mb-3">
|
<div class="flex justify-content-between mb-3">
|
||||||
<div>
|
<div>
|
||||||
<span class="block text-500 font-medium mb-3">Efficiency</span>
|
<span class="block text-500 font-medium mb-3">Efficiency</span>
|
||||||
<div class="text-900 font-medium text-xl">
|
<div class="text-900 font-medium text-2xl flex align-items-center gap-2">
|
||||||
<td>{{info.power / (info.hashRate/1000) | number: '1.2-2'}} <small>J/TH</small>
|
<span>
|
||||||
</td>
|
{{info.power / (info.hashRate/1000) | number: '1.2-2'}} <small>J/TH</small>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ng-container *ngIf="expectedHashRate$ | async as expectedHashRate">
|
|
||||||
<span class="text-green-500 font-medium">{{info.power / (expectedHashRate/1000) | number:
|
<ng-container>
|
||||||
'1.2-2'}} <small>J/TH</small>
|
Average:
|
||||||
|
<span class="text-green-500 font-medium">
|
||||||
|
{{calculateEfficiencyAverage(hashrateData, powerData) | number: '1.2-2'}} <small>J/TH</small>
|
||||||
</span>
|
</span>
|
||||||
<span class="text-500"> expected</span>
|
|
||||||
</ng-container>
|
</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>
|
</div>
|
||||||
<div class="col-12 md:col-6 xl:col-3">
|
<div class="col-12 md:col-6 xl:col-3">
|
||||||
@ -56,12 +69,21 @@
|
|||||||
<div class="flex justify-content-between mb-3">
|
<div class="flex justify-content-between mb-3">
|
||||||
<div>
|
<div>
|
||||||
<span class="block text-500 font-medium mb-3">Shares</span>
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span class="text-red-500 font-medium">{{info.sharesRejected | number: '1.0-0'}} </span>
|
<div *ngIf="info.sharesRejected === 0">
|
||||||
<span class="text-500">rejected</span> <span class="font-medium"> ({{(info.sharesRejected / (info.sharesAccepted + info.sharesRejected) * 100) | number: '1.2-2'}}%)</span>
|
<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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -70,8 +92,8 @@
|
|||||||
<div class="flex justify-content-between mb-3">
|
<div class="flex justify-content-between mb-3">
|
||||||
<div>
|
<div>
|
||||||
<span class="block text-500 font-medium mb-3">Best Difficulty</span>
|
<span class="block text-500 font-medium mb-3">Best Difficulty</span>
|
||||||
<div class="text-900 font-medium text-xl">{{info.bestDiff}}
|
<div class="text-900 font-medium text-2xl">{{info.bestDiff}}
|
||||||
<span class="text-500">all-time best</span>
|
<span class="text-500 text-lg">all-time best</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -146,7 +168,14 @@
|
|||||||
<div class="grid">
|
<div class="grid">
|
||||||
<div class="col-12">
|
<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' }" >
|
<p-progressBar [value]="(info.temp / maxTemp) * 100" [style]="{ height: '6px' }" >
|
||||||
<ng-template pTemplate="content" let-value></ng-template>
|
<ng-template pTemplate="content" let-value></ng-template>
|
||||||
</p-progressBar>
|
</p-progressBar>
|
||||||
|
@ -23,7 +23,7 @@ export class HomeComponent {
|
|||||||
public dataLabel: number[] = [];
|
public dataLabel: number[] = [];
|
||||||
public hashrateData: number[] = [];
|
public hashrateData: number[] = [];
|
||||||
public temperatureData: number[] = [];
|
public temperatureData: number[] = [];
|
||||||
public dataDataAverage: number[] = [];
|
public powerData: number[] = [];
|
||||||
public chartData?: any;
|
public chartData?: any;
|
||||||
|
|
||||||
public maxPower: number = 50;
|
public maxPower: number = 50;
|
||||||
@ -97,19 +97,6 @@ export class HomeComponent {
|
|||||||
yAxisID: 'y',
|
yAxisID: 'y',
|
||||||
fill: true,
|
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',
|
type: 'line',
|
||||||
label: 'ASIC Temp',
|
label: 'ASIC Temp',
|
||||||
@ -203,21 +190,20 @@ export class HomeComponent {
|
|||||||
tap(info => {
|
tap(info => {
|
||||||
this.hashrateData.push(info.hashRate * 1000000000);
|
this.hashrateData.push(info.hashRate * 1000000000);
|
||||||
this.temperatureData.push(info.temp);
|
this.temperatureData.push(info.temp);
|
||||||
|
this.powerData.push(info.power);
|
||||||
|
|
||||||
this.dataLabel.push(new Date().getTime());
|
this.dataLabel.push(new Date().getTime());
|
||||||
|
|
||||||
if (this.hashrateData.length >= 720) {
|
if (this.hashrateData.length >= 720) {
|
||||||
this.hashrateData.shift();
|
this.hashrateData.shift();
|
||||||
|
this.temperatureData.shift();
|
||||||
|
this.powerData.shift();
|
||||||
this.dataLabel.shift();
|
this.dataLabel.shift();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.chartData.labels = this.dataLabel;
|
this.chartData.labels = this.dataLabel;
|
||||||
this.chartData.datasets[0].data = this.hashrateData;
|
this.chartData.datasets[0].data = this.hashrateData;
|
||||||
this.chartData.datasets[2].data = this.temperatureData;
|
this.chartData.datasets[1].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 = {
|
this.chartData = {
|
||||||
...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;
|
if (data.length === 0) return 0;
|
||||||
const sum = data.reduce((sum, value) => sum + value, 0);
|
const sum = data.reduce((sum, value) => sum + value, 0);
|
||||||
return sum / data.length;
|
return sum / data.length;
|
||||||
@ -283,4 +269,16 @@ export class HomeComponent {
|
|||||||
}
|
}
|
||||||
return stratumURL.startsWith('http') ? stratumURL : `http://${stratumURL}`;
|
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>
|
<td>{{info.uptimeSeconds | dateAgo}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>WiFi Status:</td>
|
<td>Wi-Fi Status:</td>
|
||||||
<td>{{info.wifiStatus}}</td>
|
<td>{{info.wifiStatus}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -8,20 +8,21 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field grid p-fluid">
|
<div class="field grid p-fluid">
|
||||||
<label htmlFor="ssid" class="col-12 mb-2 md:col-2 md:mb-0">WiFi SSID:</label>
|
<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">
|
<div class="col-12 md:col-10 p-inputgroup">
|
||||||
<input pInputText id="ssid" type="text" formControlName="ssid" />
|
<input pInputText id="ssid" type="text" formControlName="ssid" />
|
||||||
|
<button pButton type="button" icon="pi pi-search" (click)="scanWifi()" [loading]="scanning"></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field grid p-fluid">
|
<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">
|
<div class="col-12 md:col-10 p-input-icon-right">
|
||||||
<i *ngIf="form.get('wifiPass')?.dirty" class="pi"
|
<i *ngIf="form.get('wifiPass')?.dirty" class="pi"
|
||||||
[ngClass]="{'pi-eye': !showWifiPassword, 'pi-eye-slash': showWifiPassword}"
|
[ngClass]="{'pi-eye': !showWifiPassword, 'pi-eye-slash': showWifiPassword}"
|
||||||
(click)="toggleWifiPasswordVisibility()" style="cursor: pointer;"></i>
|
(click)="toggleWifiPasswordVisibility()" style="cursor: pointer;"></i>
|
||||||
<input pInputText id="wifiPass" formControlName="wifiPass"
|
<input pInputText id="wifiPass" formControlName="wifiPass"
|
||||||
[type]="showWifiPassword ? 'text' : 'password'"
|
[type]="showWifiPassword ? 'text' : 'password'"
|
||||||
placeholder="Enter WiFi password" />
|
placeholder="Enter Wi-Fi password" />
|
||||||
</div>
|
</div>
|
||||||
</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 { Component, Input, OnInit } from '@angular/core';
|
||||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||||
import { ToastrService } from 'ngx-toastr';
|
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 { LoadingService } from 'src/app/services/loading.service';
|
||||||
import { SystemService } from 'src/app/services/system.service';
|
import { SystemService } from 'src/app/services/system.service';
|
||||||
|
|
||||||
|
interface WifiNetwork {
|
||||||
|
ssid: string;
|
||||||
|
rssi: number;
|
||||||
|
authmode: number;
|
||||||
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-network-edit',
|
selector: 'app-network-edit',
|
||||||
templateUrl: './network.edit.component.html',
|
templateUrl: './network.edit.component.html',
|
||||||
@ -15,6 +22,7 @@ export class NetworkEditComponent implements OnInit {
|
|||||||
|
|
||||||
public form!: FormGroup;
|
public form!: FormGroup;
|
||||||
public savedChanges: boolean = false;
|
public savedChanges: boolean = false;
|
||||||
|
public scanning: boolean = false;
|
||||||
|
|
||||||
@Input() uri = '';
|
@Input() uri = '';
|
||||||
|
|
||||||
@ -23,7 +31,9 @@ export class NetworkEditComponent implements OnInit {
|
|||||||
private systemService: SystemService,
|
private systemService: SystemService,
|
||||||
private toastr: ToastrService,
|
private toastr: ToastrService,
|
||||||
private toastrService: 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;
|
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)
|
this.systemService.updateSystem(this.uri, form)
|
||||||
.pipe(this.loadingService.lockUIUntilComplete())
|
.pipe(this.loadingService.lockUIUntilComplete())
|
||||||
.subscribe({
|
.subscribe({
|
||||||
@ -71,6 +86,52 @@ export class NetworkEditComponent implements OnInit {
|
|||||||
this.showWifiPassword = !this.showWifiPassword;
|
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() {
|
public restart() {
|
||||||
this.systemService.restart()
|
this.systemService.restart()
|
||||||
.pipe(this.loadingService.lockUIUntilComplete())
|
.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>
|
<app-edit></app-edit>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid">
|
|
||||||
<div class="col-12">
|
|
||||||
<app-theme-config></app-theme-config>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<div class="col-12 lg:col-6 xl:col-4">
|
<div class="col-12 lg:col-6 xl:col-4">
|
||||||
<div class="card" *ngIf="checkLatestRelease == false">
|
<div class="card" *ngIf="checkLatestRelease == false">
|
||||||
@ -34,6 +28,16 @@
|
|||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
</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="col-12 lg:col-6 xl:col-4">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h2>Update Firmware <span *ngIf="firmwareUpdateProgress != null">{{firmwareUpdateProgress}}%</span></h2>
|
<h2>Update Firmware <span *ngIf="firmwareUpdateProgress != null">{{firmwareUpdateProgress}}%</span></h2>
|
||||||
@ -45,14 +49,4 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
</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>
|
</div>
|
||||||
|
@ -22,7 +22,6 @@ export class SettingsComponent {
|
|||||||
public websiteUpdateProgress: number | null = null;
|
public websiteUpdateProgress: number | null = null;
|
||||||
|
|
||||||
|
|
||||||
public devToolsOpen: boolean = false;
|
|
||||||
public eASICModel = eASICModel;
|
public eASICModel = eASICModel;
|
||||||
public ASICModel!: 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 => {
|
this.latestRelease$ = this.githubUpdateService.getReleases().pipe(map(releases => {
|
||||||
return releases[0];
|
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() {
|
public updateSystem() {
|
||||||
|
|
||||||
const form = this.form.getRawValue();
|
const form = this.form.getRawValue();
|
||||||
@ -136,7 +121,7 @@ export class SettingsComponent {
|
|||||||
otaUpdate(event: FileUploadHandlerEvent) {
|
otaUpdate(event: FileUploadHandlerEvent) {
|
||||||
const file = event.files[0];
|
const file = event.files[0];
|
||||||
this.firmwareUpload.clear(); // clear the file upload component
|
this.firmwareUpload.clear(); // clear the file upload component
|
||||||
|
|
||||||
if (file.name != 'esp-miner.bin') {
|
if (file.name != 'esp-miner.bin') {
|
||||||
this.toastrService.error('Incorrect file, looking for esp-miner.bin.', 'Error');
|
this.toastrService.error('Incorrect file, looking for esp-miner.bin.', 'Error');
|
||||||
return;
|
return;
|
||||||
|
@ -24,8 +24,8 @@
|
|||||||
<div class="flex align-items-center gap-2">
|
<div class="flex align-items-center gap-2">
|
||||||
<label for="refresh-interval" class="text-sm md:text-base">Refresh Interval:</label>
|
<label for="refresh-interval" class="text-sm md:text-base">Refresh Interval:</label>
|
||||||
<p-slider id="refresh-interval" class="pl-2 pr-2"
|
<p-slider id="refresh-interval" class="pl-2 pr-2"
|
||||||
[min]="5"
|
[min]="5"
|
||||||
[max]="30"
|
[max]="30"
|
||||||
[style]="{'width': '150px'}"
|
[style]="{'width': '150px'}"
|
||||||
[formControl]="refreshIntervalControl">
|
[formControl]="refreshIntervalControl">
|
||||||
</p-slider>
|
</p-slider>
|
||||||
@ -48,7 +48,26 @@
|
|||||||
<div class="table-container">
|
<div class="table-container">
|
||||||
<table cellspacing="0" cellpadding="0" class="text-sm md:text-base">
|
<table cellspacing="0" cellpadding="0" class="text-sm md:text-base">
|
||||||
<tr>
|
<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>Hash Rate</th>
|
||||||
<th>Uptime</th>
|
<th>Uptime</th>
|
||||||
<th>Shares</th>
|
<th>Shares</th>
|
||||||
@ -63,18 +82,30 @@
|
|||||||
<ng-container *ngFor="let axe of swarm">
|
<ng-container *ngFor="let axe of swarm">
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a class="text-primary" [href]="'http://'+axe.IP" target="_blank">{{axe.IP}}</a>
|
<a
|
||||||
<div class="text-sm">{{axe.hostname}}</div>
|
[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>
|
||||||
|
<td>{{axe.hostname}}</td>
|
||||||
<td>{{axe.hashRate * 1000000000 | hashSuffix}}</td>
|
<td>{{axe.hashRate * 1000000000 | hashSuffix}}</td>
|
||||||
<td>{{axe.uptimeSeconds | dateAgo: {intervals: 2} }}</td>
|
<td>{{axe.uptimeSeconds | dateAgo: {intervals: 2} }}</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="w-min cursor-pointer"
|
<div class="w-min cursor-pointer"
|
||||||
pTooltip="Shares Accepted"
|
pTooltip="Shares Accepted"
|
||||||
tooltipPosition="top">
|
tooltipPosition="top">
|
||||||
{{axe.sharesAccepted | number: '1.0-0'}}
|
{{axe.sharesAccepted | number: '1.0-0'}}
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm w-min cursor-pointer"
|
<div class="text-sm w-min cursor-pointer"
|
||||||
pTooltip="Shares Rejected"
|
pTooltip="Shares Rejected"
|
||||||
tooltipPosition="top">
|
tooltipPosition="top">
|
||||||
{{axe.sharesRejected | number: '1.0-0'}}
|
{{axe.sharesRejected | number: '1.0-0'}}
|
||||||
@ -85,8 +116,8 @@
|
|||||||
<div [ngClass]="{'text-orange-500': axe.temp > 68}">
|
<div [ngClass]="{'text-orange-500': axe.temp > 68}">
|
||||||
{{axe.temp | number: '1.0-1'}}°<small>C</small>
|
{{axe.temp | number: '1.0-1'}}°<small>C</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm w-min cursor-pointer"
|
<div class="text-sm w-min cursor-pointer"
|
||||||
[ngClass]="{'text-orange-500': axe.vrTemp > 90}"
|
[ngClass]="{'text-orange-500': axe.vrTemp > 90}"
|
||||||
*ngIf="axe.vrTemp"
|
*ngIf="axe.vrTemp"
|
||||||
pTooltip="Voltage Regulator Temperature"
|
pTooltip="Voltage Regulator Temperature"
|
||||||
tooltipPosition="top">
|
tooltipPosition="top">
|
||||||
@ -95,19 +126,43 @@
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>{{axe.bestDiff}}</div>
|
<div>{{axe.bestDiff}}</div>
|
||||||
<div class="text-sm w-min cursor-pointer"
|
<div class="text-sm w-min cursor-pointer"
|
||||||
pTooltip="Best Session Diff"
|
pTooltip="Best Session Diff"
|
||||||
tooltipPosition="top">
|
tooltipPosition="top">
|
||||||
{{axe.bestSessionDiff}}
|
{{axe.bestSessionDiff}}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>{{axe.version}}</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-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>
|
<td><p-button icon="pi pi-trash" pp-button severity="secondary" (click)="remove(axe)"></p-button></td>
|
||||||
</tr>
|
</tr>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</table>
|
</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>
|
||||||
|
|
||||||
<div class="modal-backdrop" *ngIf="showEdit" (click)="showEdit = false"></div>
|
<div class="modal-backdrop" *ngIf="showEdit" (click)="showEdit = false"></div>
|
||||||
@ -115,4 +170,4 @@
|
|||||||
<div class="close" (click)="showEdit = false">✖</div>
|
<div class="close" (click)="showEdit = false">✖</div>
|
||||||
<h1>{{selectedAxeOs.IP}}</h1>
|
<h1>{{selectedAxeOs.IP}}</h1>
|
||||||
<app-edit [uri]="'http://' + selectedAxeOs.IP"></app-edit>
|
<app-edit [uri]="'http://' + selectedAxeOs.IP"></app-edit>
|
||||||
</div>
|
</div>
|
||||||
|
@ -6,15 +6,40 @@ table {
|
|||||||
th {
|
th {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
background-color: #1f2d40;
|
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,
|
th,
|
||||||
td {
|
td {
|
||||||
padding: 1rem 1rem;
|
|
||||||
border-bottom: 1px solid #304562;
|
border-bottom: 1px solid #304562;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
th > div {
|
||||||
|
min-width: 100px;
|
||||||
|
padding-right: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,9 @@ export class SwarmComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
public refreshIntervalControl: FormControl;
|
public refreshIntervalControl: FormControl;
|
||||||
|
|
||||||
|
public sortField: string = '';
|
||||||
|
public sortDirection: 'asc' | 'desc' = 'asc';
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private fb: FormBuilder,
|
private fb: FormBuilder,
|
||||||
private systemService: SystemService,
|
private systemService: SystemService,
|
||||||
@ -169,12 +172,12 @@ export class SwarmComponent implements OnInit, OnDestroy {
|
|||||||
public restart(axe: any) {
|
public restart(axe: any) {
|
||||||
this.systemService.restart(`http://${axe.IP}`).pipe(
|
this.systemService.restart(`http://${axe.IP}`).pipe(
|
||||||
catchError(error => {
|
catchError(error => {
|
||||||
this.toastr.error('Failed to restart device', 'Error');
|
this.toastr.error(`Failed to restart device at ${axe.IP}`, 'Error');
|
||||||
return of(null);
|
return of(null);
|
||||||
})
|
})
|
||||||
).subscribe(res => {
|
).subscribe(res => {
|
||||||
if (res !== null) {
|
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);
|
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 {
|
private convertBestDiffToNumber(bestDiff: string): number {
|
||||||
if (!bestDiff) return 0;
|
if (!bestDiff) return 0;
|
||||||
const value = parseFloat(bestDiff);
|
const value = parseFloat(bestDiff);
|
||||||
@ -270,4 +302,12 @@ export class SwarmComponent implements OnInit, OnDestroy {
|
|||||||
this.totals.bestDiff = this.formatBestDiff(maxDiff);
|
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">
|
<div class="layout-wrapper" [ngClass]="containerClass">
|
||||||
<app-topbar></app-topbar>
|
<app-topbar [isAPMode]="isAPMode"></app-topbar>
|
||||||
<div class="layout-sidebar">
|
<div class="layout-sidebar" *ngIf="!isAPMode">
|
||||||
<app-sidebar></app-sidebar>
|
<app-sidebar></app-sidebar>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-main-container">
|
<div class="layout-main-container">
|
||||||
|
@ -109,6 +109,10 @@ export class AppLayoutComponent implements OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get isAPMode(): boolean {
|
||||||
|
return this.router.url.startsWith('/ap');
|
||||||
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
if (this.overlayMenuOpenSubscription) {
|
if (this.overlayMenuOpenSubscription) {
|
||||||
this.overlayMenuOpenSubscription.unsubscribe();
|
this.overlayMenuOpenSubscription.unsubscribe();
|
||||||
|
@ -25,6 +25,8 @@ export class AppMenuComponent implements OnInit {
|
|||||||
{ label: 'Dashboard', icon: 'pi pi-fw pi-home', routerLink: ['/'] },
|
{ label: 'Dashboard', icon: 'pi pi-fw pi-home', routerLink: ['/'] },
|
||||||
{ label: 'Swarm', icon: 'pi pi-fw pi-share-alt', routerLink: ['swarm'] },
|
{ label: 'Swarm', icon: 'pi pi-fw pi-share-alt', routerLink: ['swarm'] },
|
||||||
{ label: 'Network', icon: 'pi pi-fw pi-wifi', routerLink: ['network'] },
|
{ 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: 'Settings', icon: 'pi pi-fw pi-cog', routerLink: ['settings'] },
|
||||||
{ label: 'Logs', icon: 'pi pi-fw pi-list', routerLink: ['logs'] },
|
{ 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>
|
<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>
|
</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>
|
<i class="pi pi-bars"></i>
|
||||||
</button>
|
</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 { MenuItem } from 'primeng/api';
|
||||||
|
|
||||||
import { LayoutService } from './service/app.layout.service';
|
import { LayoutService } from './service/app.layout.service';
|
||||||
@ -11,6 +11,8 @@ export class AppTopBarComponent {
|
|||||||
|
|
||||||
items!: MenuItem[];
|
items!: MenuItem[];
|
||||||
|
|
||||||
|
@Input() isAPMode: boolean = false;
|
||||||
|
|
||||||
@ViewChild('menubutton') menuButton!: ElementRef;
|
@ViewChild('menubutton') menuButton!: ElementRef;
|
||||||
|
|
||||||
@ViewChild('topbarmenubutton') topbarMenuButton!: 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[]> {
|
public getReleases(): Observable<GithubRelease[]> {
|
||||||
return this.httpClient.get<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(
|
).pipe(
|
||||||
map((releases: GithubRelease[]) => releases.filter((release: GithubRelease) => !release.prerelease))
|
map((releases: GithubRelease[]) => releases.filter((release: GithubRelease) => !release.prerelease))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -37,8 +37,10 @@ export class SystemService {
|
|||||||
ssid: "default",
|
ssid: "default",
|
||||||
wifiPass: "password",
|
wifiPass: "password",
|
||||||
wifiStatus: "Connected!",
|
wifiStatus: "Connected!",
|
||||||
|
apEnabled: 0,
|
||||||
sharesAccepted: 1,
|
sharesAccepted: 1,
|
||||||
sharesRejected: 0,
|
sharesRejected: 0,
|
||||||
|
sharesRejectedReasons: [],
|
||||||
uptimeSeconds: 38,
|
uptimeSeconds: 38,
|
||||||
asicCount: 1,
|
asicCount: 1,
|
||||||
smallCoreCount: 672,
|
smallCoreCount: 672,
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
|
import { environment } from '../../environments/environment';
|
||||||
|
import { of } from 'rxjs';
|
||||||
|
import { catchError, shareReplay } from 'rxjs/operators';
|
||||||
|
|
||||||
export interface ThemeSettings {
|
export interface ThemeSettings {
|
||||||
colorScheme: string;
|
colorScheme: string;
|
||||||
@ -14,15 +17,64 @@ export interface ThemeSettings {
|
|||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class ThemeService {
|
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) {}
|
constructor(private http: HttpClient) {}
|
||||||
|
|
||||||
// Get theme settings from NVS storage
|
// Get theme settings from NVS storage
|
||||||
getThemeSettings(): Observable<ThemeSettings> {
|
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
|
// Save theme settings to NVS storage
|
||||||
saveThemeSettings(settings: ThemeSettings): Observable<void> {
|
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';
|
import { eASICModel } from './enum/eASICModel';
|
||||||
|
|
||||||
|
interface ISharesRejectedStat {
|
||||||
|
message: string;
|
||||||
|
count: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ISystemInfo {
|
export interface ISystemInfo {
|
||||||
|
|
||||||
flipscreen: number;
|
flipscreen: number;
|
||||||
@ -18,8 +23,10 @@ export interface ISystemInfo {
|
|||||||
macAddr: string,
|
macAddr: string,
|
||||||
ssid: string,
|
ssid: string,
|
||||||
wifiStatus: string,
|
wifiStatus: string,
|
||||||
|
apEnabled: number,
|
||||||
sharesAccepted: number,
|
sharesAccepted: number,
|
||||||
sharesRejected: number,
|
sharesRejected: number,
|
||||||
|
sharesRejectedReasons: ISharesRejectedStat[];
|
||||||
uptimeSeconds: number,
|
uptimeSeconds: number,
|
||||||
asicCount: number,
|
asicCount: number,
|
||||||
smallCoreCount: number,
|
smallCoreCount: number,
|
||||||
@ -43,5 +50,6 @@ export interface ISystemInfo {
|
|||||||
|
|
||||||
boardtemp1?: number,
|
boardtemp1?: number,
|
||||||
boardtemp2?: number,
|
boardtemp2?: number,
|
||||||
overheat_mode: number
|
overheat_mode: number,
|
||||||
|
overclockEnabled?: number
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include "http_server.h"
|
#include "http_server.h"
|
||||||
#include "recovery_page.h"
|
|
||||||
#include "theme_api.h" // Add theme API include
|
#include "theme_api.h" // Add theme API include
|
||||||
#include "cJSON.h"
|
#include "cJSON.h"
|
||||||
#include "esp_chip_info.h"
|
#include "esp_chip_info.h"
|
||||||
@ -16,6 +15,8 @@
|
|||||||
#include "global_state.h"
|
#include "global_state.h"
|
||||||
#include "nvs_config.h"
|
#include "nvs_config.h"
|
||||||
#include "vcore.h"
|
#include "vcore.h"
|
||||||
|
#include "power.h"
|
||||||
|
#include "connect.h"
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
@ -32,10 +33,51 @@
|
|||||||
#include "lwip/sockets.h"
|
#include "lwip/sockets.h"
|
||||||
#include "lwip/sys.h"
|
#include "lwip/sys.h"
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include "connect.h"
|
||||||
|
|
||||||
|
#include "asic.h"
|
||||||
|
|
||||||
static const char * TAG = "http_server";
|
static const char * TAG = "http_server";
|
||||||
static const char * CORS_TAG = "CORS";
|
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 GlobalState * GLOBAL_STATE;
|
||||||
static httpd_handle_t server = NULL;
|
static httpd_handle_t server = NULL;
|
||||||
QueueHandle_t log_queue = NULL;
|
QueueHandle_t log_queue = NULL;
|
||||||
@ -83,19 +125,11 @@ static esp_err_t ip_in_private_range(uint32_t address) {
|
|||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t extract_origin_ip_addr(httpd_req_t *req)
|
static uint32_t extract_origin_ip_addr(char *origin)
|
||||||
{
|
{
|
||||||
char origin[128];
|
|
||||||
char ip_str[16];
|
char ip_str[16];
|
||||||
uint32_t origin_ip_addr = 0;
|
uint32_t origin_ip_addr = 0;
|
||||||
|
|
||||||
// Attempt to get the Origin header.
|
|
||||||
if (httpd_req_get_hdr_value_str(req, "Origin", origin, sizeof(origin)) != ESP_OK) {
|
|
||||||
ESP_LOGD(CORS_TAG, "No origin header found.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
ESP_LOGD(CORS_TAG, "Origin header: %s", origin);
|
|
||||||
|
|
||||||
// Find the start of the IP address in the Origin header
|
// Find the start of the IP address in the Origin header
|
||||||
const char *prefix = "http://";
|
const char *prefix = "http://";
|
||||||
char *ip_start = strstr(origin, prefix);
|
char *ip_start = strstr(origin, prefix);
|
||||||
@ -149,8 +183,14 @@ static esp_err_t is_network_allowed(httpd_req_t * req)
|
|||||||
// Convert to IPv4 string
|
// Convert to IPv4 string
|
||||||
inet_ntop(AF_INET, &request_ip_addr, ipstr, sizeof(ipstr));
|
inet_ntop(AF_INET, &request_ip_addr, ipstr, sizeof(ipstr));
|
||||||
|
|
||||||
uint32_t origin_ip_addr = extract_origin_ip_addr(req);
|
// Attempt to get the Origin header.
|
||||||
if (origin_ip_addr == 0) {
|
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;
|
origin_ip_addr = request_ip_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,7 +287,11 @@ static esp_err_t rest_recovery_handler(httpd_req_t * req)
|
|||||||
return httpd_resp_send_err(req, HTTPD_401_UNAUTHORIZED, "Unauthorized");
|
return httpd_resp_send_err(req, HTTPD_401_UNAUTHORIZED, "Unauthorized");
|
||||||
}
|
}
|
||||||
|
|
||||||
httpd_resp_send(req, recovery_page, HTTPD_RESP_USE_STRLEN);
|
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;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,22 +415,22 @@ static esp_err_t PATCH_update_settings(httpd_req_t * req)
|
|||||||
return ESP_OK;
|
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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
nvs_config_set_string(NVS_CONFIG_FALLBACK_STRATUM_PASS, item->valuestring);
|
||||||
}
|
}
|
||||||
if ((item = cJSON_GetObjectItem(root, "stratumPort")) != NULL) {
|
if ((item = cJSON_GetObjectItem(root, "stratumPort")) != NULL) {
|
||||||
@ -395,13 +439,13 @@ static esp_err_t PATCH_update_settings(httpd_req_t * req)
|
|||||||
if ((item = cJSON_GetObjectItem(root, "fallbackStratumPort")) != NULL) {
|
if ((item = cJSON_GetObjectItem(root, "fallbackStratumPort")) != NULL) {
|
||||||
nvs_config_set_u16(NVS_CONFIG_FALLBACK_STRATUM_PORT, item->valueint);
|
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);
|
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);
|
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);
|
nvs_config_set_string(NVS_CONFIG_HOSTNAME, item->valuestring);
|
||||||
}
|
}
|
||||||
if ((item = cJSON_GetObjectItem(root, "coreVoltage")) != NULL && item->valueint > 0) {
|
if ((item = cJSON_GetObjectItem(root, "coreVoltage")) != NULL && item->valueint > 0) {
|
||||||
@ -428,6 +472,9 @@ static esp_err_t PATCH_update_settings(httpd_req_t * req)
|
|||||||
if ((item = cJSON_GetObjectItem(root, "fanspeed")) != NULL) {
|
if ((item = cJSON_GetObjectItem(root, "fanspeed")) != NULL) {
|
||||||
nvs_config_set_u16(NVS_CONFIG_FAN_SPEED, item->valueint);
|
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);
|
cJSON_Delete(root);
|
||||||
httpd_resp_send_chunk(req, NULL, 0);
|
httpd_resp_send_chunk(req, NULL, 0);
|
||||||
@ -487,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 * 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 * 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");
|
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);
|
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]);
|
snprintf(formattedMac, 18, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||||
@ -494,48 +543,44 @@ static esp_err_t GET_system_info(httpd_req_t * req)
|
|||||||
cJSON * root = cJSON_CreateObject();
|
cJSON * root = cJSON_CreateObject();
|
||||||
cJSON_AddNumberToObject(root, "power", GLOBAL_STATE->POWER_MANAGEMENT_MODULE.power);
|
cJSON_AddNumberToObject(root, "power", GLOBAL_STATE->POWER_MANAGEMENT_MODULE.power);
|
||||||
cJSON_AddNumberToObject(root, "voltage", GLOBAL_STATE->POWER_MANAGEMENT_MODULE.voltage);
|
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, "temp", GLOBAL_STATE->POWER_MANAGEMENT_MODULE.chip_temp_avg);
|
||||||
cJSON_AddNumberToObject(root, "vrTemp", GLOBAL_STATE->POWER_MANAGEMENT_MODULE.vr_temp);
|
cJSON_AddNumberToObject(root, "vrTemp", GLOBAL_STATE->POWER_MANAGEMENT_MODULE.vr_temp);
|
||||||
cJSON_AddNumberToObject(root, "hashRate", GLOBAL_STATE->SYSTEM_MODULE.current_hashrate);
|
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, "bestDiff", GLOBAL_STATE->SYSTEM_MODULE.best_diff_string);
|
||||||
cJSON_AddStringToObject(root, "bestSessionDiff", GLOBAL_STATE->SYSTEM_MODULE.best_session_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, "stratumDiff", GLOBAL_STATE->stratum_difficulty);
|
||||||
|
|
||||||
cJSON_AddNumberToObject(root, "isUsingFallbackStratum", GLOBAL_STATE->SYSTEM_MODULE.is_using_fallback);
|
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, "freeHeap", esp_get_free_heap_size());
|
||||||
cJSON_AddNumberToObject(root, "coreVoltage", nvs_config_get_u16(NVS_CONFIG_ASIC_VOLTAGE, CONFIG_ASIC_VOLTAGE));
|
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, "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, "ssid", ssid);
|
||||||
cJSON_AddStringToObject(root, "macAddr", formattedMac);
|
cJSON_AddStringToObject(root, "macAddr", formattedMac);
|
||||||
cJSON_AddStringToObject(root, "hostname", hostname);
|
cJSON_AddStringToObject(root, "hostname", hostname);
|
||||||
cJSON_AddStringToObject(root, "wifiStatus", GLOBAL_STATE->SYSTEM_MODULE.wifi_status);
|
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, "sharesAccepted", GLOBAL_STATE->SYSTEM_MODULE.shares_accepted);
|
||||||
cJSON_AddNumberToObject(root, "sharesRejected", GLOBAL_STATE->SYSTEM_MODULE.shares_rejected);
|
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);
|
cJSON *error_array = cJSON_CreateArray();
|
||||||
uint16_t small_core_count = 0;
|
cJSON_AddItemToObject(root, "sharesRejectedReasons", error_array);
|
||||||
switch (GLOBAL_STATE->asic_model){
|
|
||||||
case ASIC_BM1397:
|
for (int i = 0; i < GLOBAL_STATE->SYSTEM_MODULE.rejected_reason_stats_count; i++) {
|
||||||
small_core_count = BM1397_SMALL_CORE_COUNT;
|
cJSON *error_obj = cJSON_CreateObject();
|
||||||
break;
|
cJSON_AddStringToObject(error_obj, "message", GLOBAL_STATE->SYSTEM_MODULE.rejected_reason_stats[i].message);
|
||||||
case ASIC_BM1366:
|
cJSON_AddNumberToObject(error_obj, "count", GLOBAL_STATE->SYSTEM_MODULE.rejected_reason_stats[i].count);
|
||||||
small_core_count = BM1366_SMALL_CORE_COUNT;
|
cJSON_AddItemToArray(error_array, error_obj);
|
||||||
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_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, "ASICModel", GLOBAL_STATE->asic_model_str);
|
||||||
cJSON_AddStringToObject(root, "stratumURL", stratumURL);
|
cJSON_AddStringToObject(root, "stratumURL", stratumURL);
|
||||||
cJSON_AddStringToObject(root, "fallbackStratumURL", fallbackStratumURL);
|
cJSON_AddStringToObject(root, "fallbackStratumURL", fallbackStratumURL);
|
||||||
@ -551,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, "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, "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, "invertscreen", nvs_config_get_u16(NVS_CONFIG_INVERT_SCREEN, 0));
|
||||||
|
|
||||||
cJSON_AddNumberToObject(root, "invertfanpolarity", nvs_config_get_u16(NVS_CONFIG_INVERT_FAN_POLARITY, 1));
|
cJSON_AddNumberToObject(root, "invertfanpolarity", nvs_config_get_u16(NVS_CONFIG_INVERT_FAN_POLARITY, 1));
|
||||||
@ -588,6 +634,10 @@ esp_err_t POST_WWW_update(httpd_req_t * req)
|
|||||||
return ESP_OK;
|
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];
|
char buf[1000];
|
||||||
int remaining = req->content_len;
|
int remaining = req->content_len;
|
||||||
|
|
||||||
@ -613,19 +663,30 @@ esp_err_t POST_WWW_update(httpd_req_t * req)
|
|||||||
if (recv_len == HTTPD_SOCK_ERR_TIMEOUT) {
|
if (recv_len == HTTPD_SOCK_ERR_TIMEOUT) {
|
||||||
continue;
|
continue;
|
||||||
} else if (recv_len <= 0) {
|
} 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");
|
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Protocol Error");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (esp_partition_write(www_partition, www_partition->size - remaining, (const void *) buf, recv_len) != ESP_OK) {
|
if (esp_partition_write(www_partition, www_partition->size - remaining, (const void *) buf, recv_len) != ESP_OK) {
|
||||||
|
snprintf(GLOBAL_STATE->SYSTEM_MODULE.firmware_update_status, 20, "Write Error");
|
||||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Write Error");
|
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Write Error");
|
||||||
return ESP_OK;
|
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;
|
remaining -= recv_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
httpd_resp_sendstr(req, "WWW update complete\n");
|
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;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -646,6 +707,10 @@ esp_err_t POST_OTA_update(httpd_req_t * req)
|
|||||||
return ESP_OK;
|
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];
|
char buf[1000];
|
||||||
esp_ota_handle_t ota_handle;
|
esp_ota_handle_t ota_handle;
|
||||||
int remaining = req->content_len;
|
int remaining = req->content_len;
|
||||||
@ -662,6 +727,7 @@ esp_err_t POST_OTA_update(httpd_req_t * req)
|
|||||||
|
|
||||||
// Serious Error: Abort OTA
|
// Serious Error: Abort OTA
|
||||||
} else if (recv_len <= 0) {
|
} 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");
|
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Protocol Error");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
@ -669,19 +735,27 @@ esp_err_t POST_OTA_update(httpd_req_t * req)
|
|||||||
// Successful Upload: Flash firmware chunk
|
// Successful Upload: Flash firmware chunk
|
||||||
if (esp_ota_write(ota_handle, (const void *) buf, recv_len) != ESP_OK) {
|
if (esp_ota_write(ota_handle, (const void *) buf, recv_len) != ESP_OK) {
|
||||||
esp_ota_abort(ota_handle);
|
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;
|
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;
|
remaining -= recv_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate and switch to new OTA image and reboot
|
// Validate and switch to new OTA image and reboot
|
||||||
if (esp_ota_end(ota_handle) != ESP_OK || esp_ota_set_boot_partition(ota_partition) != ESP_OK) {
|
if (esp_ota_end(ota_handle) != ESP_OK || esp_ota_set_boot_partition(ota_partition) != ESP_OK) {
|
||||||
|
snprintf(GLOBAL_STATE->SYSTEM_MODULE.firmware_update_status, 20, "Validation Error");
|
||||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Validation / Activation Error");
|
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Validation / Activation Error");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
snprintf(GLOBAL_STATE->SYSTEM_MODULE.firmware_update_status, 20, "Rebooting...");
|
||||||
|
|
||||||
httpd_resp_sendstr(req, "Firmware update complete, rebooting now!\n");
|
httpd_resp_sendstr(req, "Firmware update complete, rebooting now!\n");
|
||||||
ESP_LOGI(TAG, "Restarting System because of Firmware update complete");
|
ESP_LOGI(TAG, "Restarting System because of Firmware update complete");
|
||||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||||
@ -828,6 +902,7 @@ esp_err_t start_rest_server(void * pvParameters)
|
|||||||
|
|
||||||
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
||||||
config.uri_match_fn = httpd_uri_match_wildcard;
|
config.uri_match_fn = httpd_uri_match_wildcard;
|
||||||
|
config.stack_size = 8192;
|
||||||
config.max_open_sockets = 10;
|
config.max_open_sockets = 10;
|
||||||
config.max_uri_handlers = 20;
|
config.max_uri_handlers = 20;
|
||||||
|
|
||||||
@ -854,6 +929,15 @@ esp_err_t start_rest_server(void * pvParameters)
|
|||||||
};
|
};
|
||||||
httpd_register_uri_handler(server, &system_info_get_uri);
|
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 = {
|
httpd_uri_t swarm_options_uri = {
|
||||||
.uri = "/api/swarm",
|
.uri = "/api/swarm",
|
||||||
.method = HTTP_OPTIONS,
|
.method = HTTP_OPTIONS,
|
||||||
|
@ -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);
|
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
|
* @brief Write a byte to a I2C register
|
||||||
* @param dev_handle The I2C device handle
|
* @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_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_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_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_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);
|
esp_err_t i2c_bitaxe_register_write_word(i2c_master_dev_handle_t dev_handle, uint8_t reg_addr, uint16_t data);
|
||||||
|
21
main/main.c
21
main/main.c
@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
#include "esp_event.h"
|
#include "esp_event.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
|
#include "esp_psram.h"
|
||||||
#include "nvs_flash.h"
|
#include "nvs_flash.h"
|
||||||
|
|
||||||
// #include "protocol_examples_common.h"
|
// #include "protocol_examples_common.h"
|
||||||
@ -19,6 +20,7 @@
|
|||||||
#include "adc.h"
|
#include "adc.h"
|
||||||
#include "nvs_device.h"
|
#include "nvs_device.h"
|
||||||
#include "self_test.h"
|
#include "self_test.h"
|
||||||
|
#include "asic.h"
|
||||||
|
|
||||||
static GlobalState GLOBAL_STATE = {
|
static GlobalState GLOBAL_STATE = {
|
||||||
.extranonce_str = NULL,
|
.extranonce_str = NULL,
|
||||||
@ -32,7 +34,14 @@ static const char * TAG = "bitaxe";
|
|||||||
|
|
||||||
void app_main(void)
|
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
|
// Init I2C
|
||||||
ESP_ERROR_CHECK(i2c_bitaxe_init());
|
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));
|
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;
|
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);
|
wifi_init(wifi_ssid, wifi_pass, hostname, GLOBAL_STATE.SYSTEM_MODULE.ip_addr_str);
|
||||||
|
|
||||||
generate_ssid(GLOBAL_STATE.SYSTEM_MODULE.ap_ssid);
|
generate_ssid(GLOBAL_STATE.SYSTEM_MODULE.ap_ssid);
|
||||||
@ -116,15 +125,15 @@ void app_main(void)
|
|||||||
|
|
||||||
GLOBAL_STATE.new_stratum_version_rolling_msg = false;
|
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.stratum_queue);
|
||||||
queue_init(&GLOBAL_STATE.ASIC_jobs_queue);
|
queue_init(&GLOBAL_STATE.ASIC_jobs_queue);
|
||||||
|
|
||||||
SERIAL_init();
|
SERIAL_init();
|
||||||
(*GLOBAL_STATE.ASIC_functions.init_fn)(GLOBAL_STATE.POWER_MANAGEMENT_MODULE.frequency_value, GLOBAL_STATE.asic_count);
|
ASIC_init(&GLOBAL_STATE);
|
||||||
SERIAL_set_baud((*GLOBAL_STATE.ASIC_functions.set_max_baud_fn)());
|
SERIAL_set_baud(ASIC_set_max_baud(&GLOBAL_STATE));
|
||||||
SERIAL_clear_buffer();
|
SERIAL_clear_buffer();
|
||||||
|
|
||||||
GLOBAL_STATE.ASIC_initalized = true;
|
GLOBAL_STATE.ASIC_initalized = true;
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#define NVS_CONFIG_BEST_DIFF "bestdiff"
|
#define NVS_CONFIG_BEST_DIFF "bestdiff"
|
||||||
#define NVS_CONFIG_SELF_TEST "selftest"
|
#define NVS_CONFIG_SELF_TEST "selftest"
|
||||||
#define NVS_CONFIG_OVERHEAT_MODE "overheat_mode"
|
#define NVS_CONFIG_OVERHEAT_MODE "overheat_mode"
|
||||||
|
#define NVS_CONFIG_OVERCLOCK_ENABLED "oc_enabled"
|
||||||
#define NVS_CONFIG_SWARM "swarmconfig"
|
#define NVS_CONFIG_SWARM "swarmconfig"
|
||||||
|
|
||||||
// Theme configuration
|
// Theme configuration
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "esp_event.h"
|
#include "esp_event.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "esp_check.h"
|
||||||
#include "nvs_flash.h"
|
#include "nvs_flash.h"
|
||||||
#include "nvs_config.h"
|
#include "nvs_config.h"
|
||||||
#include "nvs_device.h"
|
#include "nvs_device.h"
|
||||||
|
|
||||||
#include "connect.h"
|
#include "connect.h"
|
||||||
#include "global_state.h"
|
#include "global_state.h"
|
||||||
|
#include "asic.h"
|
||||||
|
|
||||||
static const char * TAG = "nvs_device";
|
static const char * TAG = "nvs_device";
|
||||||
static const double NONCE_SPACE = 4294967296.0; // 2^32
|
|
||||||
|
|
||||||
|
|
||||||
esp_err_t NVSDevice_init(void) {
|
esp_err_t NVSDevice_init(void) {
|
||||||
esp_err_t err = nvs_flash_init();
|
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);
|
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);
|
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, "");
|
GLOBAL_STATE->asic_model_str = nvs_config_get_string(NVS_CONFIG_ASIC_MODEL, "");
|
||||||
if (strcmp(GLOBAL_STATE->device_model_str, "max") == 0) {
|
GLOBAL_STATE->device_model_str = nvs_config_get_string(NVS_CONFIG_DEVICE_MODEL, "invalid");
|
||||||
ESP_LOGI(TAG, "DEVICE: Max");
|
char * board_version = nvs_config_get_string(NVS_CONFIG_BOARD_VERSION, "000");
|
||||||
GLOBAL_STATE->device_model = DEVICE_MAX;
|
GLOBAL_STATE->board_version = atoi(board_version);
|
||||||
GLOBAL_STATE->asic_count = 1;
|
free(board_version);
|
||||||
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"));
|
|
||||||
ESP_LOGI(TAG, "Found Device Model: %s", GLOBAL_STATE->device_model_str);
|
ESP_LOGI(TAG, "Found Device Model: %s", GLOBAL_STATE->device_model_str);
|
||||||
ESP_LOGI(TAG, "Found Board Version: %d", GLOBAL_STATE->board_version);
|
ESP_LOGI(TAG, "Found Board Version: %d", GLOBAL_STATE->board_version);
|
||||||
|
|
||||||
GLOBAL_STATE->asic_model_str = nvs_config_get_string(NVS_CONFIG_ASIC_MODEL, "");
|
ESP_RETURN_ON_ERROR(ASIC_set_device_model(GLOBAL_STATE), TAG, "Failed to get device 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
@ -10,6 +10,18 @@
|
|||||||
#define DS4432U_OUT0_REG 0xF8 // register for current output 0
|
#define DS4432U_OUT0_REG 0xF8 // register for current output 0
|
||||||
#define DS4432U_OUT1_REG 0xF9 // register for current output 1
|
#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 const char *TAG = "DS4432U";
|
||||||
|
|
||||||
static i2c_master_dev_handle_t ds4432u_dev_handle;
|
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);
|
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.
|
* @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_init(void);
|
||||||
esp_err_t DS4432U_set_current_code(uint8_t output, uint8_t code);
|
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_get_current_code(uint8_t output, uint8_t *code);
|
||||||
|
esp_err_t DS4432U_set_voltage(float vout);
|
||||||
|
|
||||||
#endif /* DS4432U_H_ */
|
#endif /* DS4432U_H_ */
|
@ -3,6 +3,7 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
|
#include "esp_err.h"
|
||||||
#include "pmbus_commands.h"
|
#include "pmbus_commands.h"
|
||||||
|
|
||||||
#include "i2c_bitaxe.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 i2c_master_dev_handle_t tps546_dev_handle;
|
||||||
|
|
||||||
|
static TPS546_CONFIG tps546_config;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief SMBus read byte
|
* @brief SMBus read byte
|
||||||
* @param command The command to read
|
* @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);
|
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
|
* @brief SMBus read word
|
||||||
* @param command The command to read
|
* @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
|
* @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 data[7];
|
||||||
uint8_t u8_value;
|
uint8_t u8_value;
|
||||||
@ -328,11 +340,13 @@ int TPS546_init(void)
|
|||||||
uint8_t comp_config[5];
|
uint8_t comp_config[5];
|
||||||
uint8_t voutmode;
|
uint8_t voutmode;
|
||||||
|
|
||||||
|
tps546_config = config;
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Initializing the core voltage regulator");
|
ESP_LOGI(TAG, "Initializing the core voltage regulator");
|
||||||
|
|
||||||
if (i2c_bitaxe_add_device(TPS546_I2CADDR, &tps546_dev_handle, TAG) != ESP_OK) {
|
if (i2c_bitaxe_add_device(TPS546_I2CADDR, &tps546_dev_handle, TAG) != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "Failed to add I2C device");
|
ESP_LOGE(TAG, "Failed to add I2C device");
|
||||||
return -1;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Establish communication with regulator */
|
/* 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))
|
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");
|
ESP_LOGE(TAG, "Cannot find TPS546 regulator - Device ID mismatch");
|
||||||
return -1;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure power is turned off until commanded */
|
/* Make sure power is turned off until commanded */
|
||||||
@ -375,46 +389,77 @@ int TPS546_init(void)
|
|||||||
/* Show voltage settings */
|
/* Show voltage settings */
|
||||||
TPS546_show_voltage_settings();
|
TPS546_show_voltage_settings();
|
||||||
|
|
||||||
//TPS546_print_status();
|
uint16_t status;
|
||||||
|
TPS546_check_status(&status);
|
||||||
|
|
||||||
// ESP_LOGI(TAG, "-----------VOLTAGE/CURRENT---------------------");
|
if (status != 0) {
|
||||||
// /* Get voltage input (SLINEAR11) */
|
ESP_LOGE(TAG, "Status error: %04x", status);
|
||||||
// ESP_LOGI(TAG, "READ_VIN: %.2fV", TPS546_get_vin());
|
TPS546_parse_status(status);
|
||||||
// /* Get output current (SLINEAR11) */
|
}
|
||||||
// ESP_LOGI(TAG, "READ_IOUT: %.2fA", TPS546_get_iout());
|
|
||||||
// /* Get voltage output (ULINEAR16) */
|
ESP_LOGI(TAG, "-----------VOLTAGE/CURRENT---------------------");
|
||||||
// ESP_LOGI(TAG, "READ_VOUT: %.2fV", TPS546_get_vout());
|
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---------------------");
|
ESP_LOGI(TAG, "-----------TIMING---------------------");
|
||||||
smb_read_word(PMBUS_TON_DELAY, &u16_value);
|
smb_read_word(PMBUS_TON_DELAY, &u16_value);
|
||||||
temp = slinear11_2_int(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);
|
smb_read_word(PMBUS_TON_RISE, &u16_value);
|
||||||
temp = slinear11_2_int(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);
|
smb_read_word(PMBUS_TON_MAX_FAULT_LIMIT, &u16_value);
|
||||||
temp = slinear11_2_int(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);
|
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);
|
smb_read_word(PMBUS_TOFF_DELAY, &u16_value);
|
||||||
temp = slinear11_2_int(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);
|
smb_read_word(PMBUS_TOFF_FALL, &u16_value);
|
||||||
temp = slinear11_2_int(u16_value);
|
temp = slinear11_2_int(u16_value);
|
||||||
ESP_LOGI(TAG, "TOFF_FALL: %d", temp);
|
ESP_LOGI(TAG, "read TOFF_FALL: %dms", temp);
|
||||||
ESP_LOGI(TAG, "--------------------------------------");
|
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
|
// Read the compensation config registers
|
||||||
if (smb_read_block(PMBUS_COMPENSATION_CONFIG, comp_config, 5) != ESP_OK) {
|
if (smb_read_block(PMBUS_COMPENSATION_CONFIG, comp_config, 5) != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "Failed to read COMPENSATION CONFIG");
|
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],
|
ESP_LOGI(TAG, "%02x %02x %02x %02x %02x", comp_config[0], comp_config[1],
|
||||||
comp_config[2], comp_config[3], comp_config[4]);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ESP_LOGI(TAG, "MFR_ID: %s", read_mfr_id);
|
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: %s", read_mfr_model);
|
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: %d%d%d ", read_mfr_revision[0],
|
ESP_LOGI(TAG, "MFR_REVISION: %02X %02X %02X", read_mfr_revision[0], read_mfr_revision[1], read_mfr_revision[2]);
|
||||||
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)
|
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);
|
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);
|
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);
|
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---");
|
ESP_LOGI(TAG, "---Writing new config values to TPS546---");
|
||||||
/* set up the ON_OFF_CONFIG */
|
/* 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) {
|
if (smb_write_byte(PMBUS_ON_OFF_CONFIG, TPS546_INIT_ON_OFF_CONFIG) != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "Failed to write ON_OFF_CONFIG");
|
ESP_LOGE(TAG, "Failed to write ON_OFF_CONFIG");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Phase */
|
||||||
|
ESP_LOGI(TAG, "Setting PHASE: %02X", TPS546_INIT_PHASE);
|
||||||
|
smb_write_byte(PMBUS_PHASE, TPS546_INIT_PHASE);
|
||||||
|
|
||||||
/* Switch frequency */
|
/* 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));
|
smb_write_word(PMBUS_FREQUENCY_SWITCH, int_2_slinear11(TPS546_INIT_FREQUENCY));
|
||||||
|
|
||||||
/* vin voltage */
|
/* 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));
|
//deal with the UV_WARN_LIMIT bug
|
||||||
ESP_LOGI(TAG, "Setting VIN_OFF: %.2f", TPS546_INIT_VIN_OFF);
|
if (tps546_config.TPS546_INIT_VIN_UV_WARN_LIMIT > 0) {
|
||||||
smb_write_word(PMBUS_VIN_OFF, float_2_slinear11(TPS546_INIT_VIN_OFF));
|
ESP_LOGI(TAG, "Setting VIN_UV_WARN_LIMIT: %.2f", tps546_config.TPS546_INIT_VIN_UV_WARN_LIMIT);
|
||||||
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_config.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));
|
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);
|
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);
|
smb_write_byte(PMBUS_VIN_OV_FAULT_RESPONSE, TPS546_INIT_VIN_OV_FAULT_RESPONSE);
|
||||||
|
|
||||||
/* vout voltage */
|
/* vout voltage */
|
||||||
ESP_LOGI(TAG, "Setting VOUT SCALE: %.2f", TPS546_INIT_SCALE_LOOP);
|
ESP_LOGI(TAG, "Setting VOUT SCALE: %.2f", tps546_config.TPS546_INIT_SCALE_LOOP);
|
||||||
smb_write_word(PMBUS_VOUT_SCALE_LOOP, float_2_slinear11(TPS546_INIT_SCALE_LOOP));
|
smb_write_word(PMBUS_VOUT_SCALE_LOOP, float_2_slinear11(tps546_config.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, "Setting VOUT_COMMAND: %.2fV", tps546_config.TPS546_INIT_VOUT_COMMAND);
|
||||||
ESP_LOGI(TAG, "VOUT_MAX: %d", TPS546_INIT_VOUT_MAX);
|
smb_write_word(PMBUS_VOUT_COMMAND, float_2_ulinear16(tps546_config.TPS546_INIT_VOUT_COMMAND));
|
||||||
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_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));
|
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));
|
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));
|
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));
|
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));
|
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));
|
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 */
|
/* iout current */
|
||||||
ESP_LOGI(TAG, "Setting IOUT");
|
ESP_LOGI(TAG, "----- IOUT");
|
||||||
smb_write_word(PMBUS_IOUT_OC_WARN_LIMIT, float_2_slinear11(TPS546_INIT_IOUT_OC_WARN_LIMIT));
|
ESP_LOGI(TAG, "Setting IOUT_OC_WARN_LIMIT: %.2fA", tps546_config.TPS546_INIT_IOUT_OC_WARN_LIMIT);
|
||||||
smb_write_word(PMBUS_IOUT_OC_FAULT_LIMIT, float_2_slinear11(TPS546_INIT_IOUT_OC_FAULT_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);
|
smb_write_byte(PMBUS_IOUT_OC_FAULT_RESPONSE, TPS546_INIT_IOUT_OC_FAULT_RESPONSE);
|
||||||
|
|
||||||
/* temperature */
|
/* temperature */
|
||||||
ESP_LOGI(TAG, "Setting TEMPERATURE");
|
ESP_LOGI(TAG, "----- TEMPERATURE");
|
||||||
ESP_LOGI(TAG, "OT_WARN_LIMIT: %d", TPS546_INIT_OT_WARN_LIMIT);
|
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));
|
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));
|
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);
|
smb_write_byte(PMBUS_OT_FAULT_RESPONSE, TPS546_INIT_OT_FAULT_RESPONSE);
|
||||||
|
|
||||||
/* timing */
|
/* timing */
|
||||||
ESP_LOGI(TAG, "Setting TIMING");
|
ESP_LOGI(TAG, "----- TIMING");
|
||||||
ESP_LOGI(TAG, "TON_DELAY: %d", TPS546_INIT_TON_DELAY);
|
ESP_LOGI(TAG, "Setting TON_DELAY: %dms", TPS546_INIT_TON_DELAY);
|
||||||
smb_write_word(PMBUS_TON_DELAY, int_2_slinear11(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));
|
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));
|
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);
|
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));
|
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));
|
smb_write_word(PMBUS_TOFF_FALL, int_2_slinear11(TPS546_INIT_TOFF_FALL));
|
||||||
|
|
||||||
/* Compensation config */
|
/* Compensation config */
|
||||||
@ -549,11 +622,11 @@ void TPS546_write_entire_config(void)
|
|||||||
smb_write_word(PMBUS_PIN_DETECT_OVERRIDE, INIT_PIN_DETECT_OVERRIDE);
|
smb_write_word(PMBUS_PIN_DETECT_OVERRIDE, INIT_PIN_DETECT_OVERRIDE);
|
||||||
|
|
||||||
/* TODO write new MFR_REVISION number to reflect these parameters */
|
/* 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);
|
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);
|
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);
|
smb_write_block(PMBUS_MFR_ID, MFR_REVISION, 3);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -659,27 +732,123 @@ float TPS546_get_vout(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TPS546_print_status(void) {
|
esp_err_t TPS546_check_status(uint16_t *status) {
|
||||||
uint16_t u16_value;
|
|
||||||
|
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;
|
uint8_t u8_value;
|
||||||
|
|
||||||
if (smb_read_word(PMBUS_STATUS_WORD, &u16_value) != ESP_OK) {
|
if (status & TPS546_STATUS_BUSY) {
|
||||||
ESP_LOGE(TAG, "Could not read STATUS_WORD");
|
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 {
|
} else {
|
||||||
ESP_LOGI(TAG, "TPS546 Status: %04X", u16_value);
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (smb_read_byte(PMBUS_STATUS_VOUT, &u8_value) != ESP_OK) {
|
//STATUS_WORD bits
|
||||||
ESP_LOGE(TAG, "Could not read STATUS_VOUT");
|
|
||||||
} else {
|
if (status & TPS546_STATUS_VOUT) {
|
||||||
ESP_LOGI(TAG, "TPS546 VOUT Status: %02X", u8_value);
|
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) {
|
if (status & TPS546_STATUS_IOUT) {
|
||||||
ESP_LOGE(TAG, "Could not read STATUS_INPUT");
|
ESP_LOGI(TAG, "TPS546 IOUT Status Error");
|
||||||
} else {
|
//the host should check STATUS_IOUT for more information.
|
||||||
ESP_LOGI(TAG, "TPS546 INPUT Status: %02X", u8_value);
|
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
|
* send a 0 to turn off the output
|
||||||
* @param volts The desired output voltage
|
* @param volts The desired output voltage
|
||||||
**/
|
**/
|
||||||
void TPS546_set_vout(float volts)
|
esp_err_t TPS546_set_vout(float volts) {
|
||||||
{
|
|
||||||
uint16_t value;
|
uint16_t value;
|
||||||
|
|
||||||
if (volts == 0) {
|
if (volts == 0) {
|
||||||
/* turn off output */
|
/* turn off output */
|
||||||
if (smb_write_byte(PMBUS_OPERATION, OPERATION_OFF) != ESP_OK) {
|
if (smb_write_byte(PMBUS_OPERATION, OPERATION_OFF) != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "Could not turn off Vout");
|
ESP_LOGE(TAG, "Could not turn off Vout");
|
||||||
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* make sure we're in range */
|
/* 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);
|
ESP_LOGE(TAG, "Voltage requested (%f V) is out of range", volts);
|
||||||
|
return ESP_FAIL;
|
||||||
} else {
|
} else {
|
||||||
/* set the output voltage */
|
/* set the output voltage */
|
||||||
value = float_2_ulinear16(volts);
|
value = float_2_ulinear16(volts);
|
||||||
if (smb_write_word(PMBUS_VOUT_COMMAND, value) != ESP_OK) {
|
if (smb_write_word(PMBUS_VOUT_COMMAND, value) != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "Could not set Vout to %1.2f V", volts);
|
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);
|
ESP_LOGI(TAG, "Vout changed to %1.2f V", volts);
|
||||||
@ -715,70 +886,88 @@ void TPS546_set_vout(float volts)
|
|||||||
/* turn on output */
|
/* turn on output */
|
||||||
if (smb_write_byte(PMBUS_OPERATION, OPERATION_ON) != ESP_OK) {
|
if (smb_write_byte(PMBUS_OPERATION, OPERATION_ON) != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "Could not turn on Vout");
|
ESP_LOGE(TAG, "Could not turn on Vout");
|
||||||
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TPS546_show_voltage_settings(void)
|
void TPS546_show_voltage_settings(void)
|
||||||
{
|
{
|
||||||
uint16_t u16_value;
|
uint16_t u16_value;
|
||||||
|
uint8_t u8_value;
|
||||||
float f_value;
|
float f_value;
|
||||||
|
|
||||||
ESP_LOGI(TAG, "-----------VOLTAGE---------------------");
|
ESP_LOGI(TAG, "-----------VOLTAGE---------------------");
|
||||||
/* VIN_ON SLINEAR11 */
|
/* VIN_ON SLINEAR11 */
|
||||||
smb_read_word(PMBUS_VIN_ON, &u16_value);
|
smb_read_word(PMBUS_VIN_ON, &u16_value);
|
||||||
f_value = slinear11_2_float(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 */
|
/* VIN_OFF SLINEAR11 */
|
||||||
smb_read_word(PMBUS_VIN_OFF, &u16_value);
|
smb_read_word(PMBUS_VIN_OFF, &u16_value);
|
||||||
f_value = slinear11_2_float(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 */
|
/* VOUT_MAX */
|
||||||
smb_read_word(PMBUS_VOUT_MAX, &u16_value);
|
smb_read_word(PMBUS_VOUT_MAX, &u16_value);
|
||||||
f_value = ulinear16_2_float(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 */
|
/* VOUT_OV_FAULT_LIMIT */
|
||||||
smb_read_word(PMBUS_VOUT_OV_FAULT_LIMIT, &u16_value);
|
smb_read_word(PMBUS_VOUT_OV_FAULT_LIMIT, &u16_value);
|
||||||
f_value = ulinear16_2_float(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 */
|
/* VOUT_OV_WARN_LIMIT */
|
||||||
smb_read_word(PMBUS_VOUT_OV_WARN_LIMIT, &u16_value);
|
smb_read_word(PMBUS_VOUT_OV_WARN_LIMIT, &u16_value);
|
||||||
f_value = ulinear16_2_float(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 */
|
/* VOUT_MARGIN_HIGH */
|
||||||
smb_read_word(PMBUS_VOUT_MARGIN_HIGH, &u16_value);
|
smb_read_word(PMBUS_VOUT_MARGIN_HIGH, &u16_value);
|
||||||
f_value = ulinear16_2_float(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 --- */
|
/* --- VOUT_COMMAND --- */
|
||||||
smb_read_word(PMBUS_VOUT_COMMAND, &u16_value);
|
smb_read_word(PMBUS_VOUT_COMMAND, &u16_value);
|
||||||
f_value = ulinear16_2_float(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 */
|
/* VOUT_MARGIN_LOW */
|
||||||
smb_read_word(PMBUS_VOUT_MARGIN_LOW, &u16_value);
|
smb_read_word(PMBUS_VOUT_MARGIN_LOW, &u16_value);
|
||||||
f_value = ulinear16_2_float(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 */
|
/* VOUT_UV_WARN_LIMIT */
|
||||||
smb_read_word(PMBUS_VOUT_UV_WARN_LIMIT, &u16_value);
|
smb_read_word(PMBUS_VOUT_UV_WARN_LIMIT, &u16_value);
|
||||||
f_value = ulinear16_2_float(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 */
|
/* VOUT_UV_FAULT_LIMIT */
|
||||||
smb_read_word(PMBUS_VOUT_UV_FAULT_LIMIT, &u16_value);
|
smb_read_word(PMBUS_VOUT_UV_FAULT_LIMIT, &u16_value);
|
||||||
f_value = ulinear16_2_float(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 */
|
/* VOUT_MIN */
|
||||||
smb_read_word(PMBUS_VOUT_MIN, &u16_value);
|
smb_read_word(PMBUS_VOUT_MIN, &u16_value);
|
||||||
f_value = ulinear16_2_float(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_
|
#ifndef TPS546_H_
|
||||||
#define TPS546_H_
|
#define TPS546_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <esp_err.h>
|
||||||
|
|
||||||
#define TPS546_I2CADDR 0x24 //< TPS546 i2c address
|
#define TPS546_I2CADDR 0x24 //< TPS546 i2c address
|
||||||
#define TPS546_MANUFACTURER_ID 0xFE //< Manufacturer ID
|
#define TPS546_MANUFACTURER_ID 0xFE //< Manufacturer ID
|
||||||
#define TPS546_REVISION 0xFF //< Chip revision
|
#define TPS546_REVISION 0xFF //< Chip revision
|
||||||
@ -14,30 +17,49 @@
|
|||||||
#define OPERATION_OFF 0x00
|
#define OPERATION_OFF 0x00
|
||||||
#define OPERATION_ON 0x80
|
#define OPERATION_ON 0x80
|
||||||
|
|
||||||
|
#define TPS546_INIT_PHASE 0x00 /* phase */
|
||||||
|
|
||||||
#define TPS546_INIT_FREQUENCY 650 /* KHz */
|
#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 */
|
/* vin voltage */
|
||||||
#define TPS546_INIT_VIN_ON 4.8 /* V */
|
// #define TPS546_INIT_VIN_ON 11.0 /* V */
|
||||||
#define TPS546_INIT_VIN_OFF 4.5 /* V */
|
// #define TPS546_INIT_VIN_OFF 10.5 /* V */
|
||||||
#define TPS546_INIT_VIN_UV_WARN_LIMIT 5.8 /* V */
|
// #define TPS546_INIT_VIN_UV_WARN_LIMIT 14.0 /* V */
|
||||||
#define TPS546_INIT_VIN_OV_FAULT_LIMIT 6.0 /* V */
|
// #define TPS546_INIT_VIN_OV_FAULT_LIMIT 15.0 /* V */
|
||||||
#define TPS546_INIT_VIN_OV_FAULT_RESPONSE 0xB7 /* retry 6 times */
|
#define TPS546_INIT_VIN_OV_FAULT_RESPONSE 0xB7 /* retry 6 times */
|
||||||
|
|
||||||
/* vout voltage */
|
/* vout voltage */
|
||||||
#define TPS546_INIT_SCALE_LOOP 0.25 /* Voltage Scale factor */
|
//#define TPS546_INIT_SCALE_LOOP 0.25 /* Voltage Scale factor */
|
||||||
#define TPS546_INIT_VOUT_MAX 3 /* V */
|
//#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_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_OV_WARN_LIMIT 1.1 /* %/100 above VOUT_COMMAND */
|
||||||
#define TPS546_INIT_VOUT_MARGIN_HIGH 1.1 /* %/100 above VOUT */
|
#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_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_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_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 */
|
/* iout current */
|
||||||
#define TPS546_INIT_IOUT_OC_WARN_LIMIT 25.00 /* A */
|
// #define TPS546_INIT_IOUT_OC_WARN_LIMIT 50.00 /* A */
|
||||||
#define TPS546_INIT_IOUT_OC_FAULT_LIMIT 30.00 /* A */
|
// #define TPS546_INIT_IOUT_OC_FAULT_LIMIT 55.00 /* A */
|
||||||
#define TPS546_INIT_IOUT_OC_FAULT_RESPONSE 0xC0 /* shut down, no retries */
|
#define TPS546_INIT_IOUT_OC_FAULT_RESPONSE 0xC0 /* shut down, no retries */
|
||||||
|
|
||||||
/* temperature */
|
/* temperature */
|
||||||
@ -54,9 +76,9 @@
|
|||||||
#define TPS546_INIT_TOFF_DELAY 0
|
#define TPS546_INIT_TOFF_DELAY 0
|
||||||
#define TPS546_INIT_TOFF_FALL 0
|
#define TPS546_INIT_TOFF_FALL 0
|
||||||
|
|
||||||
#define INIT_STACK_CONFIG 0x0000
|
#define INIT_STACK_CONFIG 0x0001 //One-Slave, 2-phase
|
||||||
#define INIT_SYNC_CONFIG 0x0010
|
#define INIT_SYNC_CONFIG 0x00D0 //Enable Auto Detect SYNC
|
||||||
#define INIT_PIN_DETECT_OVERRIDE 0x0000
|
#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_POLARITY 0x00 // turn off POLARITY bit
|
||||||
#define ON_OFF_CONFIG_DELAY 0x00 // turn off DELAY 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 */
|
/* public functions */
|
||||||
int TPS546_init(void);
|
esp_err_t TPS546_init(TPS546_CONFIG config);
|
||||||
void TPS546_read_mfr_info(uint8_t *);
|
void TPS546_read_mfr_info(uint8_t *);
|
||||||
void TPS546_set_mfr_info(void);
|
void TPS546_set_mfr_info(void);
|
||||||
void TPS546_write_entire_config(void);
|
void TPS546_write_entire_config(void);
|
||||||
@ -79,8 +118,12 @@ int TPS546_get_temperature(void);
|
|||||||
float TPS546_get_vin(void);
|
float TPS546_get_vin(void);
|
||||||
float TPS546_get_iout(void);
|
float TPS546_get_iout(void);
|
||||||
float TPS546_get_vout(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_show_voltage_settings(void);
|
||||||
void TPS546_print_status(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_ */
|
#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_init(GlobalState * global_state);
|
||||||
esp_err_t VCORE_set_voltage(float core_voltage, 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_ */
|
#endif /* VCORE_H_ */
|
@ -23,6 +23,8 @@ static lv_obj_t *efficiency_label;
|
|||||||
static lv_obj_t *difficulty_label;
|
static lv_obj_t *difficulty_label;
|
||||||
static lv_obj_t *chip_temp_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_overheat_label;
|
||||||
static lv_obj_t *ip_addr_scr_urls_label;
|
static lv_obj_t *ip_addr_scr_urls_label;
|
||||||
static lv_obj_t *mining_url_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 double current_hashrate;
|
||||||
static float current_power;
|
static float current_power;
|
||||||
static uint64_t current_difficulty;
|
static uint64_t current_difficulty;
|
||||||
static float curreny_chip_temp;
|
static float current_chip_temp;
|
||||||
static bool found_block;
|
static bool found_block;
|
||||||
|
|
||||||
#define SCREEN_UPDATE_MS 500
|
#define SCREEN_UPDATE_MS 500
|
||||||
@ -97,7 +99,7 @@ static lv_obj_t * create_scr_invalid_asic(SystemModule * module) {
|
|||||||
lv_label_set_text(label1, "ASIC MODEL INVALID");
|
lv_label_set_text(label1, "ASIC MODEL INVALID");
|
||||||
|
|
||||||
lv_obj_t *label2 = 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_obj_t *label3 = lv_label_create(scr);
|
||||||
lv_label_set_text(label3, module->ap_ssid);
|
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_t *label1 = lv_label_create(scr);
|
||||||
lv_obj_set_width(label1, LV_HOR_RES);
|
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_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_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_obj_t *label3 = lv_label_create(scr);
|
||||||
lv_label_set_text(label3, module->ap_ssid);
|
lv_label_set_text(label3, module->ap_ssid);
|
||||||
@ -125,6 +131,23 @@ static lv_obj_t * create_scr_configure(SystemModule * module) {
|
|||||||
return scr;
|
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) {
|
static lv_obj_t * create_scr_connection(SystemModule * module) {
|
||||||
lv_obj_t * scr = lv_obj_create(NULL);
|
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_t *label1 = lv_label_create(scr);
|
||||||
lv_obj_set_width(label1, LV_HOR_RES);
|
lv_obj_set_width(label1, LV_HOR_RES);
|
||||||
lv_label_set_long_mode(label1, LV_LABEL_LONG_SCROLL_CIRCULAR);
|
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);
|
wifi_status_label = lv_label_create(scr);
|
||||||
lv_label_set_text(wifi_status_label, module->wifi_status);
|
lv_label_set_text(wifi_status_label, module->wifi_status);
|
||||||
|
|
||||||
lv_obj_t *label3 = lv_label_create(scr);
|
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_obj_t *label4 = lv_label_create(scr);
|
||||||
lv_label_set_text(label4, module->ap_ssid);
|
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);
|
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);
|
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);
|
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);
|
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);
|
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;
|
return scr;
|
||||||
}
|
}
|
||||||
@ -236,7 +259,18 @@ static void screen_update_cb(lv_timer_t * timer)
|
|||||||
return;
|
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);
|
screen_show(SCR_INVALID_ASIC);
|
||||||
return;
|
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);
|
lv_label_set_text_fmt(chip_temp_label, "Temp: %.1f C", power_management->chip_temp_avg);
|
||||||
}
|
}
|
||||||
|
|
||||||
current_hashrate = module->current_hashrate;
|
current_hashrate = module->current_hashrate;
|
||||||
current_power = power_management->power;
|
current_power = power_management->power;
|
||||||
current_difficulty = module->best_session_nonce_diff;
|
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) {
|
if (CAROUSEL_DELAY_COUNT > current_screen_counter || found_block) {
|
||||||
return;
|
return;
|
||||||
@ -353,6 +387,7 @@ esp_err_t screen_start(void * pvParameters)
|
|||||||
screens[SCR_OVERHEAT] = create_scr_overheat(module);
|
screens[SCR_OVERHEAT] = create_scr_overheat(module);
|
||||||
screens[SCR_INVALID_ASIC] = create_scr_invalid_asic(module);
|
screens[SCR_INVALID_ASIC] = create_scr_invalid_asic(module);
|
||||||
screens[SCR_CONFIGURE] = create_scr_configure(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_CONNECTION] = create_scr_connection(module);
|
||||||
screens[SCR_LOGO] = create_scr_logo();
|
screens[SCR_LOGO] = create_scr_logo();
|
||||||
screens[SCR_URLS] = create_scr_urls(module);
|
screens[SCR_URLS] = create_scr_urls(module);
|
||||||
|
@ -6,6 +6,7 @@ typedef enum {
|
|||||||
SCR_OVERHEAT,
|
SCR_OVERHEAT,
|
||||||
SCR_INVALID_ASIC,
|
SCR_INVALID_ASIC,
|
||||||
SCR_CONFIGURE,
|
SCR_CONFIGURE,
|
||||||
|
SCR_FIRMWARE_UPDATE,
|
||||||
SCR_CONNECTION,
|
SCR_CONNECTION,
|
||||||
SCR_LOGO,
|
SCR_LOGO,
|
||||||
SCR_URLS,
|
SCR_URLS,
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
#include "TPS546.h"
|
#include "TPS546.h"
|
||||||
#include "esp_psram.h"
|
#include "esp_psram.h"
|
||||||
|
|
||||||
|
#include "asic.h"
|
||||||
|
|
||||||
#define GPIO_ASIC_ENABLE CONFIG_GPIO_ASIC_ENABLE
|
#define GPIO_ASIC_ENABLE CONFIG_GPIO_ASIC_ENABLE
|
||||||
|
|
||||||
#define TESTS_FAILED 0
|
#define TESTS_FAILED 0
|
||||||
@ -366,11 +368,12 @@ void self_test(void * pvParameters)
|
|||||||
tests_done(GLOBAL_STATE, TESTS_FAILED);
|
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);
|
uint8_t chips_detected = ASIC_init(GLOBAL_STATE);
|
||||||
ESP_LOGI(TAG, "%u chips detected, %u expected", chips_detected, GLOBAL_STATE->asic_count);
|
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) {
|
if (chips_detected != chips_expected) {
|
||||||
ESP_LOGE(TAG, "SELF TEST FAIL, %d of %d CHIPS DETECTED", chips_detected, GLOBAL_STATE->asic_count);
|
ESP_LOGE(TAG, "SELF TEST FAIL, %d of %d CHIPS DETECTED", chips_detected, chips_expected);
|
||||||
char error_buf[20];
|
char error_buf[20];
|
||||||
snprintf(error_buf, 20, "ASIC:FAIL %d CHIPS", chips_detected);
|
snprintf(error_buf, 20, "ASIC:FAIL %d CHIPS", chips_detected);
|
||||||
display_msg(error_buf, GLOBAL_STATE);
|
display_msg(error_buf, GLOBAL_STATE);
|
||||||
@ -378,7 +381,7 @@ void self_test(void * pvParameters)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//setup and test hashrate
|
//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);
|
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||||
|
|
||||||
if (SERIAL_set_baud(baud) != ESP_OK) {
|
if (SERIAL_set_baud(baud) != ESP_OK) {
|
||||||
@ -437,11 +440,13 @@ void self_test(void * pvParameters)
|
|||||||
|
|
||||||
uint8_t difficulty_mask = 8;
|
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");
|
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 start = esp_timer_get_time();
|
||||||
double sum = 0;
|
double sum = 0;
|
||||||
@ -449,7 +454,7 @@ void self_test(void * pvParameters)
|
|||||||
double hash_rate = 0;
|
double hash_rate = 0;
|
||||||
|
|
||||||
while(duration < 3){
|
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) {
|
if (asic_result != NULL) {
|
||||||
// check the nonce difficulty
|
// check the nonce difficulty
|
||||||
double nonce_diff = test_nonce_value(&job, asic_result->nonce, asic_result->rolled_version);
|
double nonce_diff = test_nonce_value(&job, asic_result->nonce, asic_result->rolled_version);
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
|
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "i2c_bitaxe.h"
|
#include "i2c_bitaxe.h"
|
||||||
#include "EMC2101.h"
|
|
||||||
#include "INA260.h"
|
#include "INA260.h"
|
||||||
#include "adc.h"
|
#include "adc.h"
|
||||||
#include "connect.h"
|
#include "connect.h"
|
||||||
@ -29,6 +28,7 @@
|
|||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
#include "vcore.h"
|
#include "vcore.h"
|
||||||
|
#include "thermal.h"
|
||||||
|
|
||||||
static const char * TAG = "SystemModule";
|
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->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);
|
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->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);
|
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.
|
// set fallback to false.
|
||||||
module->is_using_fallback = false;
|
module->is_using_fallback = false;
|
||||||
|
|
||||||
@ -90,33 +98,7 @@ void SYSTEM_init_peripherals(GlobalState * GLOBAL_STATE) {
|
|||||||
VCORE_init(GLOBAL_STATE);
|
VCORE_init(GLOBAL_STATE);
|
||||||
VCORE_set_voltage(nvs_config_get_u16(NVS_CONFIG_ASIC_VOLTAGE, CONFIG_ASIC_VOLTAGE) / 1000.0, 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
|
Thermal_init(GLOBAL_STATE->device_model, nvs_config_get_u16(NVS_CONFIG_INVERT_FAN_POLARITY, 1));
|
||||||
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:
|
|
||||||
}
|
|
||||||
|
|
||||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||||
|
|
||||||
@ -132,6 +114,7 @@ void SYSTEM_init_peripherals(GlobalState * GLOBAL_STATE) {
|
|||||||
case DEVICE_ULTRA:
|
case DEVICE_ULTRA:
|
||||||
case DEVICE_SUPRA:
|
case DEVICE_SUPRA:
|
||||||
case DEVICE_GAMMA:
|
case DEVICE_GAMMA:
|
||||||
|
case DEVICE_GAMMATURBO:
|
||||||
// display
|
// display
|
||||||
if (display_init(GLOBAL_STATE) != ESP_OK || !GLOBAL_STATE->SYSTEM_MODULE.is_screen_active) {
|
if (display_init(GLOBAL_STATE) != ESP_OK || !GLOBAL_STATE->SYSTEM_MODULE.is_screen_active) {
|
||||||
ESP_LOGW(TAG, "OLED init failed!");
|
ESP_LOGW(TAG, "OLED init failed!");
|
||||||
@ -160,11 +143,38 @@ void SYSTEM_notify_accepted_share(GlobalState * GLOBAL_STATE)
|
|||||||
module->shares_accepted++;
|
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;
|
SystemModule * module = &GLOBAL_STATE->SYSTEM_MODULE;
|
||||||
|
|
||||||
module->shares_rejected++;
|
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)
|
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_init_peripherals(GlobalState * GLOBAL_STATE);
|
||||||
|
|
||||||
void SYSTEM_notify_accepted_share(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_found_nonce(GlobalState * GLOBAL_STATE, double found_diff, uint8_t job_id);
|
||||||
void SYSTEM_notify_mining_started(GlobalState * GLOBAL_STATE);
|
void SYSTEM_notify_mining_started(GlobalState * GLOBAL_STATE);
|
||||||
void SYSTEM_notify_new_ntime(GlobalState * GLOBAL_STATE, uint32_t ntime);
|
void SYSTEM_notify_new_ntime(GlobalState * GLOBAL_STATE, uint32_t ntime);
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#include <lwip/tcpip.h>
|
||||||
|
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "work_queue.h"
|
#include "work_queue.h"
|
||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
@ -7,7 +9,7 @@
|
|||||||
#include "nvs_config.h"
|
#include "nvs_config.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "stratum_task.h"
|
#include "stratum_task.h"
|
||||||
#include <lwip/tcpip.h>
|
#include "asic.h"
|
||||||
|
|
||||||
static const char *TAG = "asic_result";
|
static const char *TAG = "asic_result";
|
||||||
|
|
||||||
@ -17,7 +19,8 @@ void ASIC_result_task(void *pvParameters)
|
|||||||
|
|
||||||
while (1)
|
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)
|
if (asic_result == NULL)
|
||||||
{
|
{
|
||||||
@ -28,7 +31,7 @@ void ASIC_result_task(void *pvParameters)
|
|||||||
|
|
||||||
if (GLOBAL_STATE->valid_jobs[job_id] == 0)
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,18 +44,18 @@ void ASIC_result_task(void *pvParameters)
|
|||||||
//log the ASIC response
|
//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);
|
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(
|
int ret = STRATUM_V1_submit_share(
|
||||||
GLOBAL_STATE->sock,
|
GLOBAL_STATE->sock,
|
||||||
|
GLOBAL_STATE->send_uid++,
|
||||||
user,
|
user,
|
||||||
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->jobid,
|
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]->extranonce2,
|
||||||
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->ntime,
|
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->ntime,
|
||||||
asic_result->nonce,
|
asic_result->nonce,
|
||||||
asic_result->rolled_version ^ GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->version);
|
asic_result->rolled_version ^ GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->version);
|
||||||
free(user);
|
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
ESP_LOGI(TAG, "Unable to write share to socket. Closing connection. Ret: %d (errno %d: %s)", ret, errno, strerror(errno));
|
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);
|
SYSTEM_notify_found_nonce(GLOBAL_STATE, nonce_diff, job_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
|
|
||||||
|
#include "asic.h"
|
||||||
|
|
||||||
static const char *TAG = "ASIC_task";
|
static const char *TAG = "ASIC_task";
|
||||||
|
|
||||||
// static bm_job ** active_jobs; is required to keep track of the active jobs since the
|
// 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->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
|
// Time to execute the above code is ~0.3ms
|
||||||
// Delay for ASIC(s) to finish the job
|
// Delay for ASIC(s) to finish the job
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
|
#include <sys/time.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#include "work_queue.h"
|
#include "work_queue.h"
|
||||||
#include "global_state.h"
|
#include "global_state.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
#include "mining.h"
|
#include "mining.h"
|
||||||
#include <limits.h>
|
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
|
||||||
#include <sys/time.h>
|
#include "asic.h"
|
||||||
|
|
||||||
static const char *TAG = "create_jobs_task";
|
static const char *TAG = "create_jobs_task";
|
||||||
|
|
||||||
@ -32,7 +34,8 @@ void create_jobs_task(void *pvParameters)
|
|||||||
|
|
||||||
if (GLOBAL_STATE->new_stratum_version_rolling_msg) {
|
if (GLOBAL_STATE->new_stratum_version_rolling_msg) {
|
||||||
ESP_LOGI(TAG, "Set chip version rolls %i", (int)(GLOBAL_STATE->version_mask >> 13));
|
ESP_LOGI(TAG, "Set chip version rolls %i", (int)(GLOBAL_STATE->version_mask >> 13));
|
||||||
(GLOBAL_STATE->ASIC_functions.set_version_mask)(GLOBAL_STATE->version_mask);
|
//(GLOBAL_STATE->ASIC_functions.set_version_mask)(GLOBAL_STATE->version_mask);
|
||||||
|
ASIC_set_version_mask(GLOBAL_STATE, GLOBAL_STATE->version_mask);
|
||||||
GLOBAL_STATE->new_stratum_version_rolling_msg = false;
|
GLOBAL_STATE->new_stratum_version_rolling_msg = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "EMC2101.h"
|
|
||||||
#include "INA260.h"
|
#include "INA260.h"
|
||||||
#include "bm1397.h"
|
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
@ -12,10 +10,9 @@
|
|||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
#include "TPS546.h"
|
#include "TPS546.h"
|
||||||
#include "vcore.h"
|
#include "vcore.h"
|
||||||
|
#include "thermal.h"
|
||||||
#define GPIO_ASIC_ENABLE CONFIG_GPIO_ASIC_ENABLE
|
#include "power.h"
|
||||||
#define GPIO_ASIC_RESET CONFIG_GPIO_ASIC_RESET
|
#include "asic.h"
|
||||||
#define GPIO_PLUG_SENSE CONFIG_GPIO_PLUG_SENSE
|
|
||||||
|
|
||||||
#define POLL_RATE 2000
|
#define POLL_RATE 2000
|
||||||
#define MAX_TEMP 90.0
|
#define MAX_TEMP 90.0
|
||||||
@ -29,9 +26,6 @@
|
|||||||
#define TPS546_THROTTLE_TEMP 105.0
|
#define TPS546_THROTTLE_TEMP 105.0
|
||||||
#define TPS546_MAX_TEMP 145.0
|
#define TPS546_MAX_TEMP 145.0
|
||||||
|
|
||||||
#define SUPRA_POWER_OFFSET 5
|
|
||||||
#define GAMMA_POWER_OFFSET 5
|
|
||||||
|
|
||||||
static const char * TAG = "power_management";
|
static const char * TAG = "power_management";
|
||||||
|
|
||||||
// static float _fbound(float value, float lower_bound, float upper_bound)
|
// static float _fbound(float value, float lower_bound, float upper_bound)
|
||||||
@ -61,18 +55,10 @@ static double automatic_fan_speed(float chip_temp, GlobalState * GLOBAL_STATE)
|
|||||||
double fan_range = 100 - min_fan_speed;
|
double fan_range = 100 - min_fan_speed;
|
||||||
result = ((chip_temp - min_temp) / temp_range) * fan_range + min_fan_speed;
|
result = ((chip_temp - min_temp) / temp_range) * fan_range + min_fan_speed;
|
||||||
}
|
}
|
||||||
|
PowerManagementModule * power_management = &GLOBAL_STATE->POWER_MANAGEMENT_MODULE;
|
||||||
|
power_management->fan_perc = result;
|
||||||
|
Thermal_set_fan_percent(GLOBAL_STATE->device_model, result/100.0);
|
||||||
|
|
||||||
switch (GLOBAL_STATE->device_model) {
|
|
||||||
case DEVICE_MAX:
|
|
||||||
case DEVICE_ULTRA:
|
|
||||||
case DEVICE_SUPRA:
|
|
||||||
case DEVICE_GAMMA:
|
|
||||||
float perc = (float) result / 100;
|
|
||||||
GLOBAL_STATE->POWER_MANAGEMENT_MODULE.fan_perc = perc;
|
|
||||||
EMC2101_set_fan_speed( perc );
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,195 +72,64 @@ void POWER_MANAGEMENT_task(void * pvParameters)
|
|||||||
|
|
||||||
power_management->frequency_multiplier = 1;
|
power_management->frequency_multiplier = 1;
|
||||||
|
|
||||||
power_management->HAS_POWER_EN = GLOBAL_STATE->board_version == 202 || GLOBAL_STATE->board_version == 203 || GLOBAL_STATE->board_version == 204;
|
|
||||||
power_management->HAS_PLUG_SENSE = GLOBAL_STATE->board_version == 204;
|
|
||||||
|
|
||||||
//int last_frequency_increase = 0;
|
//int last_frequency_increase = 0;
|
||||||
//uint16_t frequency_target = nvs_config_get_u16(NVS_CONFIG_ASIC_FREQ, CONFIG_ASIC_FREQUENCY);
|
//uint16_t frequency_target = nvs_config_get_u16(NVS_CONFIG_ASIC_FREQ, CONFIG_ASIC_FREQUENCY);
|
||||||
|
|
||||||
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 || !power_management->HAS_PLUG_SENSE) {
|
|
||||||
// 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:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
|
|
||||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||||
uint16_t last_core_voltage = 0.0;
|
uint16_t last_core_voltage = 0.0;
|
||||||
uint16_t last_asic_frequency = power_management->frequency_value;
|
uint16_t last_asic_frequency = power_management->frequency_value;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
switch (GLOBAL_STATE->device_model) {
|
power_management->voltage = Power_get_input_voltage(GLOBAL_STATE);
|
||||||
case DEVICE_MAX:
|
power_management->power = Power_get_power(GLOBAL_STATE);
|
||||||
case DEVICE_ULTRA:
|
|
||||||
case DEVICE_SUPRA:
|
power_management->fan_rpm = Thermal_get_fan_speed(GLOBAL_STATE->device_model);
|
||||||
if (GLOBAL_STATE->board_version >= 402 && GLOBAL_STATE->board_version <= 499) {
|
power_management->chip_temp_avg = Thermal_get_chip_temp(GLOBAL_STATE);
|
||||||
power_management->voltage = TPS546_get_vin() * 1000;
|
|
||||||
power_management->current = TPS546_get_iout() * 1000;
|
power_management->vr_temp = Power_get_vreg_temp(GLOBAL_STATE);
|
||||||
// calculate regulator power (in milliwatts)
|
|
||||||
power_management->power = (TPS546_get_vout() * power_management->current) / 1000;
|
|
||||||
// The power reading from the TPS546 is only it's output power. So the rest of the Bitaxe power is not accounted for.
|
// ASIC Thermal Diode will give bad readings if the ASIC is turned off
|
||||||
power_management->power += SUPRA_POWER_OFFSET; // Add offset for the rest of the Bitaxe power. TODO: this better.
|
// if(power_management->voltage < tps546_config.TPS546_INIT_VOUT_MIN){
|
||||||
} else {
|
// goto looper;
|
||||||
if (INA260_installed() == true) {
|
// }
|
||||||
power_management->voltage = INA260_read_voltage();
|
|
||||||
power_management->current = INA260_read_current();
|
//overheat mode if the voltage regulator or ASIC is too hot
|
||||||
power_management->power = INA260_read_power() / 1000;
|
if ((power_management->vr_temp > TPS546_THROTTLE_TEMP || power_management->chip_temp_avg > THROTTLE_TEMP) && (power_management->frequency_value > 50 || power_management->voltage > 1000)) {
|
||||||
}
|
ESP_LOGE(TAG, "OVERHEAT! VR: %fC ASIC %fC", power_management->vr_temp, power_management->chip_temp_avg );
|
||||||
}
|
power_management->fan_perc = 100;
|
||||||
|
Thermal_set_fan_percent(GLOBAL_STATE->device_model, 1);
|
||||||
break;
|
|
||||||
case DEVICE_GAMMA:
|
// Turn off core voltage
|
||||||
power_management->voltage = TPS546_get_vin() * 1000;
|
Power_disable(GLOBAL_STATE);
|
||||||
power_management->current = TPS546_get_iout() * 1000;
|
|
||||||
// calculate regulator power (in milliwatts)
|
nvs_config_set_u16(NVS_CONFIG_ASIC_VOLTAGE, 1000);
|
||||||
power_management->power = (TPS546_get_vout() * power_management->current) / 1000;
|
nvs_config_set_u16(NVS_CONFIG_ASIC_FREQ, 50);
|
||||||
// The power reading from the TPS546 is only it's output power. So the rest of the Bitaxe power is not accounted for.
|
nvs_config_set_u16(NVS_CONFIG_FAN_SPEED, 100);
|
||||||
power_management->power += GAMMA_POWER_OFFSET; // Add offset for the rest of the Bitaxe power. TODO: this better.
|
nvs_config_set_u16(NVS_CONFIG_AUTO_FAN_SPEED, 0);
|
||||||
break;
|
nvs_config_set_u16(NVS_CONFIG_OVERHEAT_MODE, 1);
|
||||||
default:
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
power_management->fan_rpm = EMC2101_get_fan_speed();
|
|
||||||
|
|
||||||
switch (GLOBAL_STATE->device_model) {
|
|
||||||
case DEVICE_MAX:
|
|
||||||
power_management->chip_temp_avg = GLOBAL_STATE->ASIC_initalized ? EMC2101_get_external_temp() : -1;
|
|
||||||
|
|
||||||
if ((power_management->chip_temp_avg > THROTTLE_TEMP) &&
|
|
||||||
(power_management->frequency_value > 50 || power_management->voltage > 1000)) {
|
|
||||||
ESP_LOGE(TAG, "OVERHEAT ASIC %fC", power_management->chip_temp_avg );
|
|
||||||
|
|
||||||
EMC2101_set_fan_speed(1);
|
|
||||||
if (power_management->HAS_POWER_EN) {
|
|
||||||
gpio_set_level(GPIO_ASIC_ENABLE, 1);
|
|
||||||
}
|
|
||||||
nvs_config_set_u16(NVS_CONFIG_ASIC_VOLTAGE, 1000);
|
|
||||||
nvs_config_set_u16(NVS_CONFIG_ASIC_FREQ, 50);
|
|
||||||
nvs_config_set_u16(NVS_CONFIG_FAN_SPEED, 100);
|
|
||||||
nvs_config_set_u16(NVS_CONFIG_AUTO_FAN_SPEED, 0);
|
|
||||||
nvs_config_set_u16(NVS_CONFIG_OVERHEAT_MODE, 1);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DEVICE_ULTRA:
|
|
||||||
case DEVICE_SUPRA:
|
|
||||||
|
|
||||||
if (GLOBAL_STATE->board_version >= 402 && GLOBAL_STATE->board_version <= 499) {
|
|
||||||
power_management->chip_temp_avg = GLOBAL_STATE->ASIC_initalized ? EMC2101_get_external_temp() : -1;
|
|
||||||
power_management->vr_temp = (float)TPS546_get_temperature();
|
|
||||||
} else {
|
|
||||||
power_management->chip_temp_avg = EMC2101_get_internal_temp() + 5;
|
|
||||||
power_management->vr_temp = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// EMC2101 will give bad readings if the ASIC is turned off
|
|
||||||
if(power_management->voltage < TPS546_INIT_VOUT_MIN){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
//overheat mode if the voltage regulator or ASIC is too hot
|
|
||||||
if ((power_management->vr_temp > TPS546_THROTTLE_TEMP || power_management->chip_temp_avg > THROTTLE_TEMP) &&
|
|
||||||
(power_management->frequency_value > 50 || power_management->voltage > 1000)) {
|
|
||||||
ESP_LOGE(TAG, "OVERHEAT! VR: %fC ASIC %fC", power_management->vr_temp, power_management->chip_temp_avg );
|
|
||||||
|
|
||||||
EMC2101_set_fan_speed(1);
|
|
||||||
if (GLOBAL_STATE->board_version >= 402 && GLOBAL_STATE->board_version <= 499) {
|
|
||||||
// Turn off core voltage
|
|
||||||
VCORE_set_voltage(0.0, GLOBAL_STATE);
|
|
||||||
} else if (power_management->HAS_POWER_EN) {
|
|
||||||
gpio_set_level(GPIO_ASIC_ENABLE, 1);
|
|
||||||
}
|
|
||||||
nvs_config_set_u16(NVS_CONFIG_ASIC_VOLTAGE, 1000);
|
|
||||||
nvs_config_set_u16(NVS_CONFIG_ASIC_FREQ, 50);
|
|
||||||
nvs_config_set_u16(NVS_CONFIG_FAN_SPEED, 100);
|
|
||||||
nvs_config_set_u16(NVS_CONFIG_AUTO_FAN_SPEED, 0);
|
|
||||||
nvs_config_set_u16(NVS_CONFIG_OVERHEAT_MODE, 1);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case DEVICE_GAMMA:
|
|
||||||
power_management->chip_temp_avg = GLOBAL_STATE->ASIC_initalized ? EMC2101_get_external_temp() : -1;
|
|
||||||
power_management->vr_temp = (float)TPS546_get_temperature();
|
|
||||||
|
|
||||||
// EMC2101 will give bad readings if the ASIC is turned off
|
|
||||||
if(power_management->voltage < TPS546_INIT_VOUT_MIN){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
//overheat mode if the voltage regulator or ASIC is too hot
|
|
||||||
if ((power_management->vr_temp > TPS546_THROTTLE_TEMP || power_management->chip_temp_avg > THROTTLE_TEMP) &&
|
|
||||||
(power_management->frequency_value > 50 || power_management->voltage > 1000)) {
|
|
||||||
ESP_LOGE(TAG, "OVERHEAT! VR: %fC ASIC %fC", power_management->vr_temp, power_management->chip_temp_avg );
|
|
||||||
|
|
||||||
EMC2101_set_fan_speed(1);
|
|
||||||
|
|
||||||
// Turn off core voltage
|
|
||||||
VCORE_set_voltage(0.0, GLOBAL_STATE);
|
|
||||||
|
|
||||||
nvs_config_set_u16(NVS_CONFIG_ASIC_VOLTAGE, 1000);
|
|
||||||
nvs_config_set_u16(NVS_CONFIG_ASIC_FREQ, 50);
|
|
||||||
nvs_config_set_u16(NVS_CONFIG_FAN_SPEED, 100);
|
|
||||||
nvs_config_set_u16(NVS_CONFIG_AUTO_FAN_SPEED, 0);
|
|
||||||
nvs_config_set_u16(NVS_CONFIG_OVERHEAT_MODE, 1);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (nvs_config_get_u16(NVS_CONFIG_AUTO_FAN_SPEED, 1) == 1) {
|
if (nvs_config_get_u16(NVS_CONFIG_AUTO_FAN_SPEED, 1) == 1) {
|
||||||
|
|
||||||
power_management->fan_perc = (float)automatic_fan_speed(power_management->chip_temp_avg, GLOBAL_STATE);
|
power_management->fan_perc = (float)automatic_fan_speed(power_management->chip_temp_avg, GLOBAL_STATE);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
switch (GLOBAL_STATE->device_model) {
|
float fs = (float) nvs_config_get_u16(NVS_CONFIG_FAN_SPEED, 100);
|
||||||
case DEVICE_MAX:
|
power_management->fan_perc = fs;
|
||||||
case DEVICE_ULTRA:
|
Thermal_set_fan_percent(GLOBAL_STATE->device_model, (float) fs / 100.0);
|
||||||
case DEVICE_SUPRA:
|
|
||||||
case DEVICE_GAMMA:
|
|
||||||
|
|
||||||
float fs = (float) nvs_config_get_u16(NVS_CONFIG_FAN_SPEED, 100);
|
|
||||||
power_management->fan_perc = fs;
|
|
||||||
EMC2101_set_fan_speed((float) fs / 100);
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the state of plug sense pin
|
// Read the state of plug sense pin
|
||||||
if (power_management->HAS_PLUG_SENSE) {
|
// if (power_management->HAS_PLUG_SENSE) {
|
||||||
int gpio_plug_sense_state = gpio_get_level(GPIO_PLUG_SENSE);
|
// int gpio_plug_sense_state = gpio_get_level(GPIO_PLUG_SENSE);
|
||||||
if (gpio_plug_sense_state == 0) {
|
// if (gpio_plug_sense_state == 0) {
|
||||||
// turn ASIC off
|
// // turn ASIC off
|
||||||
gpio_set_level(GPIO_ASIC_ENABLE, 1);
|
// gpio_set_level(GPIO_ASIC_ENABLE, 1);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// New voltage and frequency adjustment code
|
// New voltage and frequency adjustment code
|
||||||
uint16_t core_voltage = nvs_config_get_u16(NVS_CONFIG_ASIC_VOLTAGE, CONFIG_ASIC_VOLTAGE);
|
uint16_t core_voltage = nvs_config_get_u16(NVS_CONFIG_ASIC_VOLTAGE, CONFIG_ASIC_VOLTAGE);
|
||||||
@ -288,12 +143,13 @@ void POWER_MANAGEMENT_task(void * pvParameters)
|
|||||||
|
|
||||||
if (asic_frequency != last_asic_frequency) {
|
if (asic_frequency != last_asic_frequency) {
|
||||||
ESP_LOGI(TAG, "New ASIC frequency requested: %uMHz (current: %uMHz)", asic_frequency, last_asic_frequency);
|
ESP_LOGI(TAG, "New ASIC frequency requested: %uMHz (current: %uMHz)", asic_frequency, last_asic_frequency);
|
||||||
if (do_frequency_transition((float)asic_frequency)) {
|
|
||||||
|
bool success = ASIC_set_frequency(GLOBAL_STATE, (float)asic_frequency);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
power_management->frequency_value = (float)asic_frequency;
|
power_management->frequency_value = (float)asic_frequency;
|
||||||
ESP_LOGI(TAG, "Successfully transitioned to new ASIC frequency: %uMHz", asic_frequency);
|
|
||||||
} else {
|
|
||||||
ESP_LOGE(TAG, "Failed to transition to new ASIC frequency: %uMHz", asic_frequency);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
last_asic_frequency = asic_frequency;
|
last_asic_frequency = asic_frequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,6 +162,7 @@ void POWER_MANAGEMENT_task(void * pvParameters)
|
|||||||
ESP_LOGI(TAG, "Overheat mode updated to: %d", module->overheat_mode);
|
ESP_LOGI(TAG, "Overheat mode updated to: %d", module->overheat_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// looper:
|
||||||
vTaskDelay(POLL_RATE / portTICK_PERIOD_MS);
|
vTaskDelay(POLL_RATE / portTICK_PERIOD_MS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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