mirror of
https://github.com/OpenEPaperLink/OpenEPaperLink.git
synced 2026-03-21 05:06:39 +01:00
Merge branch 'jjwbruijn:master' into master
This commit is contained in:
BIN
ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/88MZ100_7.4_BETA-0.3.bin
Normal file
BIN
ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/88MZ100_7.4_BETA-0.3.bin
Normal file
Binary file not shown.
@@ -1,26 +1,48 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "led.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/timers.h"
|
||||
#include "proto.h"
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void init_led()
|
||||
{
|
||||
gpio_config_t led1 = {};
|
||||
led1.intr_type = GPIO_INTR_DISABLE;
|
||||
led1.mode = GPIO_MODE_OUTPUT;
|
||||
led1.pin_bit_mask = ((1ULL<<LED1) | (1ULL<<LED2));
|
||||
led1.pull_down_en = 0;
|
||||
led1.pull_up_en = 0;
|
||||
gpio_config(&led1);
|
||||
#define NUM_LEDS 2
|
||||
|
||||
const gpio_num_t led_pins[NUM_LEDS] = {LED1, LED2};
|
||||
TimerHandle_t led_timers[NUM_LEDS] = {0};
|
||||
|
||||
void led_timer_callback(TimerHandle_t xTimer) {
|
||||
int led_index = (int)pvTimerGetTimerID(xTimer);
|
||||
if (led_index >= 0 && led_index < NUM_LEDS) {
|
||||
gpio_set_level(led_pins[led_index], 0);
|
||||
}
|
||||
}
|
||||
|
||||
void led_set(int nr, bool state)
|
||||
{
|
||||
gpio_set_level(nr, state);
|
||||
void init_led() {
|
||||
gpio_config_t led1 = {};
|
||||
led1.intr_type = GPIO_INTR_DISABLE;
|
||||
led1.mode = GPIO_MODE_OUTPUT;
|
||||
led1.pin_bit_mask = ((1ULL << LED1) | (1ULL << LED2));
|
||||
led1.pull_down_en = 0;
|
||||
led1.pull_up_en = 0;
|
||||
gpio_config(&led1);
|
||||
|
||||
for (int i = 0; i < NUM_LEDS; i++) {
|
||||
led_timers[i] = xTimerCreate("led_timer", pdMS_TO_TICKS(50), pdFALSE, (void *)i, led_timer_callback);
|
||||
}
|
||||
}
|
||||
|
||||
void led_flash(int nr) {
|
||||
gpio_set_level(led_pins[nr], 1);
|
||||
if (nr >= 0 && nr < NUM_LEDS) {
|
||||
xTimerStart(led_timers[nr], 0);
|
||||
}
|
||||
}
|
||||
|
||||
void led_set(int nr, bool state) {
|
||||
gpio_set_level(nr, state);
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
#pragma once
|
||||
#include <stdbool.h>
|
||||
|
||||
void init_led();
|
||||
void led_set(int nr, bool state);
|
||||
void led_set(int nr, bool state);
|
||||
void led_flash(int nr);
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
// Ported to ESP32-C6 By ATC1441(ATCnetz.de) for OpenEPaperLink at ~08.2023
|
||||
|
||||
#include "main.h"
|
||||
#include <esp_mac.h>
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/uart.h"
|
||||
#include "esp_err.h"
|
||||
@@ -16,21 +12,27 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/task.h"
|
||||
#include "led.h"
|
||||
#include "proto.h"
|
||||
#include "radio.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "second_uart.h"
|
||||
#include "soc/uart_struct.h"
|
||||
#include "soc/lp_uart_reg.h"
|
||||
#include "soc/uart_struct.h"
|
||||
#include "utils.h"
|
||||
#include "led.h"
|
||||
#include <esp_mac.h>
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
static const char *TAG = "MAIN";
|
||||
|
||||
const uint8_t channelList[6] = {11, 15, 20, 25, 26, 27};
|
||||
|
||||
#define DATATYPE_NOUPDATE 0
|
||||
#define HW_TYPE 0xFF
|
||||
#define HW_TYPE 0xC6
|
||||
|
||||
#define MAX_PENDING_MACS 250
|
||||
#define HOUSEKEEPING_INTERVAL 60UL
|
||||
@@ -38,7 +40,7 @@ const uint8_t channelList[6] = {11, 15, 20, 25, 26, 27};
|
||||
struct pendingData pendingDataArr[MAX_PENDING_MACS];
|
||||
|
||||
// VERSION GOES HERE!
|
||||
uint16_t version = 0x0017;
|
||||
uint16_t version = 0x0018;
|
||||
|
||||
#define RAW_PKT_PADDING 2
|
||||
|
||||
@@ -69,6 +71,8 @@ uint8_t curPower = 10;
|
||||
uint8_t curPendingData = 0;
|
||||
uint8_t curNoUpdate = 0;
|
||||
|
||||
bool highspeedSerial = false;
|
||||
|
||||
void sendXferCompleteAck(uint8_t *dst);
|
||||
void sendCancelXfer(uint8_t *dst);
|
||||
void espNotifyAPInfo();
|
||||
@@ -191,7 +195,7 @@ void processSerial(uint8_t lastchar) {
|
||||
static uint8_t *serialbufferp;
|
||||
static uint8_t bytesRemain = 0;
|
||||
static uint32_t lastSerial = 0;
|
||||
static uint32_t blockStartTime = 0;
|
||||
static uint32_t blockStartTime = 0;
|
||||
if ((RXState != ZBS_RX_WAIT_HEADER) && ((getMillis() - lastSerial) > 1000)) {
|
||||
RXState = ZBS_RX_WAIT_HEADER;
|
||||
ESP_LOGI(TAG, "UART Timeout");
|
||||
@@ -206,9 +210,9 @@ void processSerial(uint8_t lastchar) {
|
||||
cmdbuffer[3] = lastchar;
|
||||
|
||||
if (isSame(cmdbuffer + 1, ">D>", 3)) {
|
||||
pr("ACK>\n");
|
||||
pr("ACK>");
|
||||
blockStartTime = getMillis();
|
||||
ESP_LOGI(TAG, "Starting BlkData");
|
||||
ESP_LOGI(TAG, "Starting BlkData, %lu ms after request", blockStartTime - nextBlockAttempt );
|
||||
blockPosition = 0;
|
||||
RXState = ZBS_RX_WAIT_BLOCKDATA;
|
||||
}
|
||||
@@ -252,11 +256,21 @@ void processSerial(uint8_t lastchar) {
|
||||
// TODO RESET US HERE
|
||||
RXState = ZBS_RX_WAIT_HEADER;
|
||||
}
|
||||
if (isSame(cmdbuffer, "HSPD", 4)) {
|
||||
pr("ACK>");
|
||||
ESP_LOGI(TAG, "HSPD In, switching to 2000000");
|
||||
delay(100);
|
||||
uart_switch_speed(2000000);
|
||||
delay(100);
|
||||
highspeedSerial = true;
|
||||
pr("ACK>");
|
||||
RXState = ZBS_RX_WAIT_HEADER;
|
||||
}
|
||||
break;
|
||||
case ZBS_RX_WAIT_BLOCKDATA:
|
||||
blockbuffer[blockPosition++] = 0xAA ^ lastchar;
|
||||
if (blockPosition >= 4100) {
|
||||
ESP_LOGI(TAG, "Blockdata fully received %lu", getMillis() - blockStartTime);
|
||||
ESP_LOGI(TAG, "Blockdata fully received in %lu ms, %lu ms after the request", getMillis() - blockStartTime, getMillis() - nextBlockAttempt);
|
||||
RXState = ZBS_RX_WAIT_HEADER;
|
||||
}
|
||||
break;
|
||||
@@ -272,12 +286,12 @@ void processSerial(uint8_t lastchar) {
|
||||
if (slot == -1) slot = findFreeSlot();
|
||||
if (slot != -1) {
|
||||
memcpy(&(pendingDataArr[slot]), serialbuffer, sizeof(struct pendingData));
|
||||
pr("ACK>\n");
|
||||
pr("ACK>");
|
||||
} else {
|
||||
pr("NOQ>\n");
|
||||
pr("NOQ>");
|
||||
}
|
||||
} else {
|
||||
pr("NOK>\n");
|
||||
pr("NOK>");
|
||||
}
|
||||
|
||||
RXState = ZBS_RX_WAIT_HEADER;
|
||||
@@ -290,11 +304,10 @@ void processSerial(uint8_t lastchar) {
|
||||
if (bytesRemain == 0) {
|
||||
if (checkCRC(serialbuffer, sizeof(struct pendingData))) {
|
||||
struct pendingData *pd = (struct pendingData *) serialbuffer;
|
||||
// deleteAllPendingDataForVer((uint8_t *)&pd->availdatainfo.dataVer);
|
||||
deleteAllPendingDataForMac((uint8_t *) &pd->targetMac);
|
||||
pr("ACK>\n");
|
||||
pr("ACK>");
|
||||
} else {
|
||||
pr("NOK>\n");
|
||||
pr("NOK>");
|
||||
}
|
||||
|
||||
RXState = ZBS_RX_WAIT_HEADER;
|
||||
@@ -316,10 +329,11 @@ void processSerial(uint8_t lastchar) {
|
||||
curPower = scp->power;
|
||||
radioSetChannel(scp->channel);
|
||||
radioSetTxPower(scp->power);
|
||||
pr("ACK>\n");
|
||||
ESP_LOGI(TAG, "Set channel: %d power: %d", curChannel, curPower);
|
||||
pr("ACK>");
|
||||
} else {
|
||||
SCPfailed:
|
||||
pr("NOK>\n");
|
||||
pr("NOK>");
|
||||
}
|
||||
RXState = ZBS_RX_WAIT_HEADER;
|
||||
}
|
||||
@@ -381,17 +395,17 @@ void espNotifyTimeOut(const uint8_t *src) {
|
||||
}
|
||||
}
|
||||
void espNotifyAPInfo() {
|
||||
pr("TYP>%02X\n", HW_TYPE);
|
||||
pr("VER>%04X\n", version);
|
||||
pr("TYP>%02X", HW_TYPE);
|
||||
pr("VER>%04X", version);
|
||||
pr("MAC>%02X%02X", mSelfMac[0], mSelfMac[1]);
|
||||
pr("%02X%02X", mSelfMac[2], mSelfMac[3]);
|
||||
pr("%02X%02X", mSelfMac[4], mSelfMac[5]);
|
||||
pr("%02X%02X\n", mSelfMac[6], mSelfMac[7]);
|
||||
pr("ZCH>%02X\n", curChannel);
|
||||
pr("ZPW>%02X\n", curPower);
|
||||
pr("%02X%02X", mSelfMac[6], mSelfMac[7]);
|
||||
pr("ZCH>%02X", curChannel);
|
||||
pr("ZPW>%02X", curPower);
|
||||
countSlots();
|
||||
pr("PEN>%02X\n", curPendingData);
|
||||
pr("NOP>%02X\n", curNoUpdate);
|
||||
pr("PEN>%02X", curPendingData);
|
||||
pr("NOP>%02X", curNoUpdate);
|
||||
}
|
||||
|
||||
// process data from tag
|
||||
@@ -450,18 +464,17 @@ void processBlockRequest(const uint8_t *buffer, uint8_t forceBlockDownload) {
|
||||
|
||||
if (blockStartTimer == 0) {
|
||||
if (requestDataDownload) {
|
||||
// check if we need to download the first block; we need to give the ESP32 some additional time to cache the file
|
||||
if (blockReq->blockId == 0) {
|
||||
blockRequestAck->pleaseWaitMs = 450;
|
||||
if (highspeedSerial == true) {
|
||||
blockRequestAck->pleaseWaitMs = 220;
|
||||
} else {
|
||||
blockRequestAck->pleaseWaitMs = 450;
|
||||
blockRequestAck->pleaseWaitMs = 550;
|
||||
}
|
||||
} else {
|
||||
// block is already in buffer
|
||||
blockRequestAck->pleaseWaitMs = 50;
|
||||
blockRequestAck->pleaseWaitMs = 30;
|
||||
}
|
||||
} else {
|
||||
blockRequestAck->pleaseWaitMs = 50;
|
||||
blockRequestAck->pleaseWaitMs = 30;
|
||||
}
|
||||
blockStartTimer = getMillis() + blockRequestAck->pleaseWaitMs;
|
||||
|
||||
@@ -624,8 +637,8 @@ void sendPong(void *buf) {
|
||||
}
|
||||
|
||||
void app_main(void) {
|
||||
init_nvs();
|
||||
init_led();
|
||||
init_nvs();
|
||||
init_led();
|
||||
init_second_uart();
|
||||
|
||||
esp_event_loop_create_default();
|
||||
@@ -639,23 +652,23 @@ void app_main(void) {
|
||||
radioSetChannel(curChannel);
|
||||
radioSetTxPower(10);
|
||||
|
||||
pr("RES>\n");
|
||||
pr("RDY>\n");
|
||||
pr("RES>");
|
||||
pr("RDY>");
|
||||
|
||||
housekeepingTimer = getMillis();
|
||||
while (1) {
|
||||
while ((getMillis() - housekeepingTimer) < ((1000 * HOUSEKEEPING_INTERVAL) - 100)) {
|
||||
int8_t ret = commsRxUnencrypted(radiorxbuffer);
|
||||
if (ret > 1) {
|
||||
led_set(LED1, 1);
|
||||
led_flash(0);
|
||||
// received a packet, lets see what it is
|
||||
switch (getPacketType(radiorxbuffer)) {
|
||||
case PKT_AVAIL_DATA_REQ:
|
||||
if (ret == 28) {
|
||||
// old version of the AvailDataReq struct, set all the new fields to zero, so it will pass the CRC
|
||||
processAvailDataReq(radiorxbuffer);
|
||||
memset(radiorxbuffer + 1 + sizeof(struct MacFrameBcast) + sizeof(struct oldAvailDataReq), 0,
|
||||
sizeof(struct AvailDataReq) - sizeof(struct oldAvailDataReq) + 2);
|
||||
processAvailDataReq(radiorxbuffer);
|
||||
} else if (ret == 40) {
|
||||
// new version of the AvailDataReq struct
|
||||
processAvailDataReq(radiorxbuffer);
|
||||
@@ -683,22 +696,24 @@ void app_main(void) {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pr("t=%02X\n", getPacketType(radiorxbuffer));
|
||||
ESP_LOGI(TAG, "t=%02X" , getPacketType(radiorxbuffer));
|
||||
break;
|
||||
}
|
||||
led_set(LED1, 0);
|
||||
} else if (blockStartTimer == 0) {
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
uint8_t curr_char;
|
||||
while (getRxCharSecond(&curr_char)) processSerial(curr_char);
|
||||
|
||||
if (blockStartTimer) {
|
||||
// BUG: uint32 overflowing; this will break every once in a while. Don't know how to fix this other than ugly global variables
|
||||
if (getMillis() > blockStartTimer) {
|
||||
sendBlockData();
|
||||
blockStartTimer = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t cCount = 0; cCount < MAX_PENDING_MACS; cCount++) {
|
||||
if (pendingDataArr[cCount].attemptsLeft == 1) {
|
||||
if (pendingDataArr[cCount].availdatainfo.dataType != DATATYPE_NOUPDATE) {
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
#include <esp_mac.h>
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "radio.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/uart.h"
|
||||
#include "esp_err.h"
|
||||
@@ -13,28 +10,31 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/task.h"
|
||||
#include "led.h"
|
||||
#include "main.h"
|
||||
#include "proto.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/uart_struct.h"
|
||||
#include "soc/lp_uart_reg.h"
|
||||
#include "radio.h"
|
||||
#include "soc/uart_struct.h"
|
||||
#include "utils.h"
|
||||
#include "led.h"
|
||||
#include <esp_mac.h>
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
static const char *TAG = "RADIO";
|
||||
|
||||
uint8_t mSelfMac[8];
|
||||
volatile uint8_t isInTransmit = 0;
|
||||
QueueHandle_t packet_bufer = NULL;
|
||||
QueueHandle_t packet_buffer = NULL;
|
||||
|
||||
void esp_ieee802154_receive_done(uint8_t *frame, esp_ieee802154_frame_info_t *frame_info) {
|
||||
ESP_EARLY_LOGI(TAG, "RX <- : %d", frame[0]);
|
||||
BaseType_t xHigherPriorityTaskWoken ;
|
||||
static uint8_t inner_rxPKT[130];
|
||||
ESP_EARLY_LOGI(TAG, "RX %d", frame[0]);
|
||||
BaseType_t xHigherPriorityTaskWoken;
|
||||
static uint8_t inner_rxPKT[130];
|
||||
memcpy(inner_rxPKT, &frame[0], frame[0] + 1);
|
||||
xQueueSendFromISR(packet_bufer, (void *) &inner_rxPKT, &xHigherPriorityTaskWoken );
|
||||
portYIELD_FROM_ISR_ARG(xHigherPriorityTaskWoken );
|
||||
xQueueSendFromISR(packet_buffer, (void *)&inner_rxPKT, &xHigherPriorityTaskWoken);
|
||||
portYIELD_FROM_ISR_ARG(xHigherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
void esp_ieee802154_transmit_failed(const uint8_t *frame, esp_ieee802154_tx_error_t error) {
|
||||
@@ -43,13 +43,12 @@ void esp_ieee802154_transmit_failed(const uint8_t *frame, esp_ieee802154_tx_erro
|
||||
}
|
||||
|
||||
void esp_ieee802154_transmit_done(const uint8_t *frame, const uint8_t *ack, esp_ieee802154_frame_info_t *ack_frame_info) {
|
||||
isInTransmit = 0;
|
||||
ESP_EARLY_LOGI(TAG, "TX -> : %d", frame[0]);
|
||||
isInTransmit = 0;
|
||||
ESP_EARLY_LOGI(TAG, "TX %d", frame[0]);
|
||||
}
|
||||
|
||||
void radio_init()
|
||||
{
|
||||
packet_bufer = xQueueCreate(32, 130);
|
||||
void radio_init() {
|
||||
packet_buffer = xQueueCreate(32, 130);
|
||||
esp_ieee802154_enable();
|
||||
radioSetChannel(11);
|
||||
esp_ieee802154_set_panid(PROTO_PAN_ID);
|
||||
@@ -64,19 +63,17 @@ void radio_init()
|
||||
}
|
||||
|
||||
uint32_t lastZbTx = 0;
|
||||
bool radioTx(uint8_t *packet)
|
||||
{
|
||||
static uint8_t txPKT[130];
|
||||
led_set(LED2, 1);
|
||||
bool radioTx(uint8_t *packet) {
|
||||
static uint8_t txPKT[130];
|
||||
while (isInTransmit) {
|
||||
}
|
||||
while (getMillis() - lastZbTx < 6) {
|
||||
}
|
||||
led_flash(1);
|
||||
memcpy(txPKT, packet, packet[0]);
|
||||
isInTransmit = 1;
|
||||
lastZbTx = getMillis();
|
||||
lastZbTx = getMillis();
|
||||
esp_ieee802154_transmit(txPKT, false);
|
||||
led_set(LED2, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -85,11 +82,10 @@ void radioSetChannel(uint8_t ch) { esp_ieee802154_set_channel(ch); }
|
||||
void radioSetTxPower(uint8_t power) {}
|
||||
|
||||
int8_t commsRxUnencrypted(uint8_t *data) {
|
||||
static uint8_t inner_rxPKT_out[130];
|
||||
if (xQueueReceive(packet_bufer, (void *) &inner_rxPKT_out, pdMS_TO_TICKS(100)) == pdTRUE) {
|
||||
memcpy(data, &inner_rxPKT_out[1], inner_rxPKT_out[0] + 1);
|
||||
static uint8_t inner_rxPKT_out[130];
|
||||
if (xQueueReceive(packet_buffer, (void *)&inner_rxPKT_out, pdMS_TO_TICKS(100)) == pdTRUE) {
|
||||
memcpy(data, &inner_rxPKT_out[1], inner_rxPKT_out[0] + 1);
|
||||
return inner_rxPKT_out[0] - 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#pragma once
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
extern uint8_t mSelfMac[8];
|
||||
|
||||
void radio_init();
|
||||
bool radioTx(uint8_t *packet);
|
||||
bool radioTx(uint8_t *packet);
|
||||
void radioSetChannel(uint8_t ch);
|
||||
void radioSetTxPower(uint8_t power);
|
||||
int8_t commsRxUnencrypted(uint8_t *data);
|
||||
@@ -51,6 +51,18 @@ void init_second_uart() {
|
||||
xTaskCreate(uart_event_task, "uart_event_task", 16384, NULL, 12, NULL);
|
||||
}
|
||||
|
||||
void uart_switch_speed(int baudrate) {
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = baudrate,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.source_clk = UART_SCLK_DEFAULT,
|
||||
};
|
||||
ESP_ERROR_CHECK(uart_param_config(1, &uart_config));
|
||||
}
|
||||
|
||||
void uartTx(uint8_t data) { uart_write_bytes(1, (const char *) &data, 1); }
|
||||
|
||||
|
||||
@@ -90,171 +102,16 @@ static void uart_event_task(void *pvParameters) {
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
static void printchar(char **str, int c) {
|
||||
if (str) {
|
||||
**str = c;
|
||||
++(*str);
|
||||
} else {
|
||||
uart_write_bytes(1, (const char *) &c, 1);
|
||||
}
|
||||
}
|
||||
void uart_printf(const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
#define PAD_RIGHT 1
|
||||
#define PAD_ZERO 2
|
||||
char buffer[128];
|
||||
int len = vsnprintf(buffer, sizeof(buffer), format, args);
|
||||
|
||||
static int prints(char **out, const char *string, int width, int pad) {
|
||||
register int pc = 0, padchar = ' ';
|
||||
va_end(args);
|
||||
|
||||
if (width > 0) {
|
||||
register int len = 0;
|
||||
register const char *ptr;
|
||||
for (ptr = string; *ptr; ++ptr) ++len;
|
||||
if (len >= width)
|
||||
width = 0;
|
||||
else
|
||||
width -= len;
|
||||
if (pad & PAD_ZERO) padchar = '0';
|
||||
}
|
||||
if (!(pad & PAD_RIGHT)) {
|
||||
for (; width > 0; --width) {
|
||||
printchar(out, padchar);
|
||||
++pc;
|
||||
}
|
||||
}
|
||||
for (; *string; ++string) {
|
||||
printchar(out, *string);
|
||||
++pc;
|
||||
}
|
||||
for (; width > 0; --width) {
|
||||
printchar(out, padchar);
|
||||
++pc;
|
||||
}
|
||||
|
||||
return pc;
|
||||
}
|
||||
|
||||
/* the following should be enough for 32 bit int */
|
||||
#define PRINT_BUF_LEN 12
|
||||
|
||||
static int printi(char **out, int i, int b, int sg, int width, int pad, int letbase) {
|
||||
char print_buf[PRINT_BUF_LEN];
|
||||
register char *s;
|
||||
register int t, neg = 0, pc = 0;
|
||||
register unsigned int u = i;
|
||||
|
||||
if (i == 0) {
|
||||
print_buf[0] = '0';
|
||||
print_buf[1] = '\0';
|
||||
return prints(out, print_buf, width, pad);
|
||||
}
|
||||
|
||||
if (sg && b == 10 && i < 0) {
|
||||
neg = 1;
|
||||
u = -i;
|
||||
}
|
||||
|
||||
s = print_buf + PRINT_BUF_LEN - 1;
|
||||
*s = '\0';
|
||||
|
||||
while (u) {
|
||||
t = u % b;
|
||||
if (t >= 10) t += letbase - '0' - 10;
|
||||
*--s = t + '0';
|
||||
u /= b;
|
||||
}
|
||||
|
||||
if (neg) {
|
||||
if (width && (pad & PAD_ZERO)) {
|
||||
printchar(out, '-');
|
||||
++pc;
|
||||
--width;
|
||||
} else {
|
||||
*--s = '-';
|
||||
}
|
||||
}
|
||||
|
||||
return pc + prints(out, s, width, pad);
|
||||
}
|
||||
|
||||
static int print(char **out, const char *format, va_list args) {
|
||||
register int width, pad;
|
||||
register int pc = 0;
|
||||
char scr[2];
|
||||
|
||||
for (; *format != 0; ++format) {
|
||||
if (*format == '%') {
|
||||
++format;
|
||||
width = pad = 0;
|
||||
if (*format == '\0') break;
|
||||
if (*format == '%') goto out;
|
||||
if (*format == '-') {
|
||||
++format;
|
||||
pad = PAD_RIGHT;
|
||||
}
|
||||
while (*format == '0') {
|
||||
++format;
|
||||
pad |= PAD_ZERO;
|
||||
}
|
||||
for (; *format >= '0' && *format <= '9'; ++format) {
|
||||
width *= 10;
|
||||
width += *format - '0';
|
||||
}
|
||||
if (*format == 's') {
|
||||
register char *s = (char *) va_arg(args, int);
|
||||
pc += prints(out, s ? s : "(null)", width, pad);
|
||||
continue;
|
||||
}
|
||||
if (*format == 'd') {
|
||||
pc += printi(out, va_arg(args, int), 10, 1, width, pad, 'a');
|
||||
continue;
|
||||
}
|
||||
if (*format == 'x') {
|
||||
pc += printi(out, va_arg(args, int), 16, 0, width, pad, 'a');
|
||||
continue;
|
||||
}
|
||||
if (*format == 'X') {
|
||||
pc += printi(out, va_arg(args, int), 16, 0, width, pad, 'A');
|
||||
continue;
|
||||
}
|
||||
if (*format == 'u') {
|
||||
pc += printi(out, va_arg(args, int), 10, 0, width, pad, 'a');
|
||||
continue;
|
||||
}
|
||||
if (*format == 'c') {
|
||||
/* char are converted to int then pushed on the stack */
|
||||
scr[0] = (char) va_arg(args, int);
|
||||
scr[1] = '\0';
|
||||
pc += prints(out, scr, width, pad);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
out:
|
||||
printchar(out, *format);
|
||||
++pc;
|
||||
}
|
||||
}
|
||||
if (out) **out = '\0';
|
||||
va_end(args);
|
||||
return pc;
|
||||
}
|
||||
|
||||
int u_printf(const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
print(0, format, args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int u_sprintf(char *out, const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
return print(&out, format, args);
|
||||
}
|
||||
|
||||
void u_array_printf(unsigned char *data, unsigned int len) {
|
||||
u_printf("{");
|
||||
for (int i = 0; i < len; ++i) {
|
||||
u_printf("%X%s", data[i], i < (len) -1 ? ":" : " ");
|
||||
}
|
||||
u_printf("}\n");
|
||||
if (len > 0) {
|
||||
uart_write_bytes(1, buffer, len);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
void init_second_uart();
|
||||
void uart_switch_speed(int baudrate);
|
||||
|
||||
void uartTx(uint8_t data);
|
||||
bool getRxCharSecond(uint8_t *newChar);
|
||||
|
||||
int u_printf(const char *fmt, ...);
|
||||
int u_sprintf(char *s, const char *fmt, ...);
|
||||
void u_array_printf(unsigned char *data, unsigned int len);
|
||||
void uart_printf(const char *format, ...);
|
||||
|
||||
#define pr u_printf
|
||||
#define sprf u_sprintf
|
||||
#define array_prf u_array_printf
|
||||
#define pr uart_printf
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "TFT 320x170",
|
||||
"name": "TFT 320x172",
|
||||
"width": 320,
|
||||
"height": 170,
|
||||
"height": 172,
|
||||
"rotatebuffer": 0,
|
||||
"bpp": 16,
|
||||
"colors": 4,
|
||||
@@ -16,14 +16,14 @@
|
||||
"usetemplate": 1,
|
||||
"template": {
|
||||
"21": [
|
||||
{ "box": [ 0, 0, 320, 170, 1 ] },
|
||||
{ "text": [ 5, 5, "OpenEpaperLink AP", "calibrib30", 2, 0, 0, 1 ] },
|
||||
{ "text": [ 5, 60, "IP address:", "bahnschrift20", "#888888", 0, 0, 1 ] },
|
||||
{ "text": [ 120, 60, "{ap_ip}", "bahnschrift20", 0, 0, 0, 1 ] },
|
||||
{ "text": [ 5, 85, "Channel:", "bahnschrift20", "#888888", 0, 0, 1 ] },
|
||||
{ "text": [ 120, 85, "{ap_ch}", "bahnschrift20", 0, 0, 0, "1" ] },
|
||||
{ "text": [ 5, 110, "Tag count:", "bahnschrift20", "#888888", 0, 0, 1 ] },
|
||||
{ "text": [ 120, 110, "{ap_tagcount}", "bahnschrift20", 0, 0, 0, "1" ] }
|
||||
{ "box": [ 0, 0, 320, 172, 1 ] },
|
||||
{ "text": [ 10, 15, "OpenEpaperLink AP", "calibrib30", 2, 0, 0, 1 ] },
|
||||
{ "text": [ 10, 70, "IP address:", "bahnschrift20", "#888888", 0, 0, 1 ] },
|
||||
{ "text": [ 120, 70, "{ap_ip}", "bahnschrift20", 0, 0, 0, 1 ] },
|
||||
{ "text": [ 10, 95, "Channel:", "bahnschrift20", "#888888", 0, 0, 1 ] },
|
||||
{ "text": [ 120, 95, "{ap_ch}", "bahnschrift20", 0, 0, 0, "1" ] },
|
||||
{ "text": [ 10, 120, "Tag count:", "bahnschrift20", "#888888", 0, 0, 1 ] },
|
||||
{ "text": [ 120, 120, "{ap_tagcount}", "bahnschrift20", 0, 0, 0, "1" ] }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -126,4 +126,20 @@ struct tagsettings {
|
||||
uint8_t fixedChannel; // default 0; if set to a valid channel number, the tag will stick to that channel
|
||||
} __packed;
|
||||
|
||||
struct ledFlash {
|
||||
uint8_t mode : 4;
|
||||
uint8_t flashDuration : 4;
|
||||
uint8_t color1;
|
||||
uint8_t flashCount1 : 4;
|
||||
uint8_t delay1 : 4;
|
||||
uint8_t color2;
|
||||
uint8_t flashCount2 : 4;
|
||||
uint8_t delay2 : 4;
|
||||
uint8_t color3;
|
||||
uint8_t flashCount3 : 4;
|
||||
uint8_t delay3 : 4;
|
||||
uint8_t repeats;
|
||||
uint8_t spare;
|
||||
} __packed;
|
||||
|
||||
#pragma pack(pop)
|
||||
12
ESP32_AP-Flasher/include/ips_display.h
Normal file
12
ESP32_AP-Flasher/include/ips_display.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#include <Arduino.h>
|
||||
#include <TFT_eSPI.h>
|
||||
|
||||
#ifdef YELLOW_IPS_AP
|
||||
|
||||
extern TFT_eSPI tft2;
|
||||
extern int32_t tftid;
|
||||
extern uint8_t YellowSense;
|
||||
|
||||
void TFTLog(String text);
|
||||
|
||||
#endif
|
||||
@@ -13,7 +13,7 @@ extern void processXferComplete(struct espXferComplete* xfc, bool local);
|
||||
extern void processXferTimeout(struct espXferComplete* xfc, bool local);
|
||||
extern void processDataReq(struct espAvailDataReq* adr, bool local);
|
||||
|
||||
extern bool sendTagCommand(const uint8_t* dst, uint8_t cmd, bool local);
|
||||
extern bool sendTagCommand(const uint8_t* dst, uint8_t cmd, bool local, const uint8_t* payload = nullptr);
|
||||
extern bool sendAPSegmentedData(const uint8_t* dst, String data, uint16_t icons, bool inverted, bool local);
|
||||
extern bool showAPSegmentedInfo(const uint8_t* dst, bool local);
|
||||
extern void updateTaginfoitem(struct TagInfo* taginfoitem, IPAddress remoteIP);
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#define WAKEUP_REASON_BOOT 1
|
||||
#define WAKEUP_REASON_GPIO 2
|
||||
#define WAKEUP_REASON_NFC 3
|
||||
#define WAKEUP_REASON_BUTTON1 4
|
||||
#define WAKEUP_REASON_BUTTON2 5
|
||||
#define WAKEUP_REASON_FIRSTBOOT 0xFC
|
||||
#define WAKEUP_REASON_NETWORK_SCAN 0xFD
|
||||
#define WAKEUP_REASON_WDT_RESET 0xFE
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#define WAKEUP_REASON_BOOTUP 1
|
||||
#define WAKEUP_REASON_GPIO 2
|
||||
#define WAKEUP_REASON_NFC 3
|
||||
#define WAKEUP_REASON_BUTTON1 4
|
||||
#define WAKEUP_REASON_BUTTON2 5
|
||||
|
||||
#define RUNSTATUS_STOP 0
|
||||
#define RUNSTATUS_PAUSE 1
|
||||
|
||||
@@ -40,6 +40,7 @@ class WifiManager {
|
||||
|
||||
bool waitForConnection();
|
||||
void pollSerial();
|
||||
static void terminalLog(String text);
|
||||
|
||||
public:
|
||||
WifiManager();
|
||||
|
||||
@@ -280,9 +280,13 @@ build_flags =
|
||||
-D FLASHER_AP_TEST=-1
|
||||
-D FLASHER_AP_TXD=17
|
||||
-D FLASHER_AP_RXD=18
|
||||
-D FLASHER_LED=14
|
||||
-D FLASHER_DEBUG_TXD=19
|
||||
-D FLASHER_DEBUG_RXD=20
|
||||
-D FLASHER_LED=16
|
||||
-D HAS_RGB_LED
|
||||
-D FLASHER_RGB_LED=48
|
||||
-D ST7789_DRIVER
|
||||
-D TFT_WIDTH=170
|
||||
-D TFT_WIDTH=172
|
||||
-D TFT_HEIGHT=320
|
||||
-D TFT_MISO=-1
|
||||
-D TFT_MOSI=13
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#ifdef YELLOW_IPS_AP
|
||||
#include <Arduino.h>
|
||||
#include <FS.h>
|
||||
#include <TFT_eSPI.h>
|
||||
#include <WiFi.h>
|
||||
|
||||
#include "commstructs.h"
|
||||
@@ -9,11 +7,45 @@
|
||||
#include "storage.h"
|
||||
#include "tag_db.h"
|
||||
|
||||
#ifdef YELLOW_IPS_AP
|
||||
|
||||
#include "ips_display.h"
|
||||
|
||||
#define YELLOW_SENSE 8 // sense AP hardware
|
||||
#define TFT_BACKLIGHT 14
|
||||
|
||||
TFT_eSPI tft2 = TFT_eSPI();
|
||||
bool first_run = 0;
|
||||
time_t last_update = 0;
|
||||
time_t last_checkin = 0;
|
||||
int32_t tftid = -1;
|
||||
uint8_t YellowSense = 0;
|
||||
bool tftLogscreen = true;
|
||||
|
||||
void TFTLog(String text) {
|
||||
if (tftLogscreen == false) {
|
||||
tft2.fillScreen(TFT_BLACK);
|
||||
tft2.setCursor(0, 5, 2);
|
||||
tftLogscreen = true;
|
||||
}
|
||||
if (text.isEmpty()) return;
|
||||
tft2.setTextColor(TFT_SILVER);
|
||||
if (text.startsWith("!")) {
|
||||
tft2.setTextColor(TFT_RED);
|
||||
text = text.substring(1);
|
||||
} else if (text.indexOf("http") != -1) {
|
||||
int httpIndex = text.indexOf("http");
|
||||
tft2.print(text.substring(0, httpIndex));
|
||||
tft2.setTextColor(TFT_YELLOW);
|
||||
text = text.substring(httpIndex);
|
||||
} else if (text.indexOf(":") != -1) {
|
||||
int colonIndex = text.indexOf(":");
|
||||
tft2.setTextColor(TFT_SILVER);
|
||||
tft2.print(text.substring(0, colonIndex + 1));
|
||||
tft2.setTextColor(TFT_WHITE);
|
||||
text = text.substring(colonIndex + 1);
|
||||
} else if (text.endsWith("!")) {
|
||||
tft2.setTextColor(TFT_GREEN);
|
||||
}
|
||||
tft2.println(text);
|
||||
}
|
||||
|
||||
int32_t findId(uint8_t mac[8]) {
|
||||
for (uint32_t c = 0; c < tagDB.size(); c++) {
|
||||
@@ -42,28 +74,43 @@ void sendAvail(uint8_t wakeupReason) {
|
||||
}
|
||||
|
||||
void yellow_ap_display_init(void) {
|
||||
|
||||
pinMode(YELLOW_SENSE, INPUT_PULLDOWN);
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
if (digitalRead(YELLOW_SENSE) == HIGH) YellowSense = 1;
|
||||
|
||||
pinMode(TFT_BACKLIGHT, OUTPUT);
|
||||
digitalWrite(TFT_BACKLIGHT, HIGH);
|
||||
|
||||
ledcSetup(6, 5000, 8);
|
||||
ledcAttachPin(TFT_BACKLIGHT, 6);
|
||||
ledcWrite(6, 255); // config.led
|
||||
|
||||
tft2.init();
|
||||
tft2.setRotation(3);
|
||||
tft2.setRotation(YellowSense == 1 ? 1 : 3);
|
||||
|
||||
tft2.fillScreen(TFT_BLACK);
|
||||
tft2.setCursor(0, 0, 2);
|
||||
tft2.setCursor(10, 5, 2);
|
||||
tft2.setTextColor(TFT_WHITE);
|
||||
tft2.println(" Init\n");
|
||||
tft2.println("*** Initialising... ***");
|
||||
tftLogscreen = true;
|
||||
}
|
||||
|
||||
void yellow_ap_display_loop(void) {
|
||||
static bool first_run = 0;
|
||||
static time_t last_checkin = 0;
|
||||
static time_t last_update = 0;
|
||||
|
||||
if (millis() - last_checkin >= 60000) {
|
||||
sendAvail(0);
|
||||
last_checkin = millis();
|
||||
tftLogscreen = false;
|
||||
}
|
||||
if (first_run == 0) {
|
||||
sendAvail(0xFC);
|
||||
first_run = 1;
|
||||
}
|
||||
if (millis() - last_update >= 1000) {
|
||||
if (first_run == 0) {
|
||||
sendAvail(0xFC);
|
||||
first_run = 1;
|
||||
}
|
||||
|
||||
// if ((uint32_t)WiFi.localIP() == (uint32_t)0) {}
|
||||
|
||||
tagRecord* tag = tagDB.at(tftid);
|
||||
if (tag->pending) {
|
||||
String filename = tag->filename;
|
||||
@@ -82,6 +129,7 @@ void yellow_ap_display_loop(void) {
|
||||
size_t bytesRead = file.readBytes((char*)spriteData, spr.width() * spr.height() * 2);
|
||||
file.close();
|
||||
spr.pushSprite(0, 0);
|
||||
tftLogscreen = false;
|
||||
|
||||
struct espXferComplete xfc = {0};
|
||||
memcpy(xfc.src, tag->mac, 8);
|
||||
|
||||
@@ -149,6 +149,9 @@ void rgbIdleStep() {
|
||||
|
||||
void setBrightness(int brightness) {
|
||||
maxledbrightness = brightness;
|
||||
#ifdef YELLOW_IPS_AP
|
||||
// ledcWrite(6, config.led);
|
||||
#endif
|
||||
#ifdef HAS_RGB_LED
|
||||
FastLED.setBrightness(maxledbrightness);
|
||||
#endif
|
||||
@@ -180,10 +183,10 @@ void addFadeMono(uint8_t value) {
|
||||
}
|
||||
|
||||
void showMono(uint8_t brightness) {
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S2
|
||||
ledcWrite(7, gamma8[brightness]);
|
||||
#else
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
ledcWrite(7, 255 - gamma8[brightness]);
|
||||
#else
|
||||
ledcWrite(7, gamma8[brightness]);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -209,8 +209,9 @@ void spr2buffer(TFT_eSprite &spr, String &fileout, imgParam &imageParams) {
|
||||
Storage.begin();
|
||||
|
||||
#ifdef YELLOW_IPS_AP
|
||||
extern uint8_t YellowSense;
|
||||
if (fileout == "direct") {
|
||||
tft.setRotation(3);
|
||||
tft.setRotation(YellowSense == 1 ? 1 : 3);
|
||||
spr.pushSprite(0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -600,12 +600,16 @@ bool showAPSegmentedInfo(const uint8_t* dst, bool local) {
|
||||
}
|
||||
}
|
||||
|
||||
bool sendTagCommand(const uint8_t* dst, uint8_t cmd, bool local) {
|
||||
bool sendTagCommand(const uint8_t* dst, uint8_t cmd, bool local, const uint8_t* payload) {
|
||||
struct pendingData pending = {0};
|
||||
memcpy(pending.targetMac, dst, 8);
|
||||
pending.availdatainfo.dataType = DATATYPE_COMMAND_DATA;
|
||||
pending.availdatainfo.dataTypeArgument = cmd;
|
||||
pending.availdatainfo.nextCheckIn = 0;
|
||||
if (payload != nullptr) {
|
||||
memcpy(&pending.availdatainfo.dataVer, payload, sizeof(uint64_t));
|
||||
memcpy(&pending.availdatainfo.dataSize, payload + sizeof(uint64_t), sizeof(uint32_t));
|
||||
}
|
||||
pending.attemptsLeft = 120;
|
||||
Serial.printf(">Tag CMD %02X%02X%02X%02X%02X%02X%02X%02X\n\0", dst[7], dst[6], dst[5], dst[4], dst[3], dst[2], dst[1], dst[0]);
|
||||
if (local) {
|
||||
|
||||
@@ -88,7 +88,7 @@ void txEnd() {
|
||||
}
|
||||
bool waitCmdReply() {
|
||||
uint32_t val = millis();
|
||||
while (millis() < val + 100) {
|
||||
while (millis() < val + 200) {
|
||||
switch (cmdReplyValue) {
|
||||
case CMD_REPLY_WAIT:
|
||||
break;
|
||||
@@ -135,6 +135,7 @@ void APEnterEarlyReset() {
|
||||
|
||||
// Reset the tag
|
||||
void APTagReset() {
|
||||
Serial.println("Resetting tag");
|
||||
uint8_t powerPins = sizeof(APpowerPins);
|
||||
if (powerPins > 0 && APpowerPins[0] == -1)
|
||||
powerPins = 0;
|
||||
@@ -193,7 +194,7 @@ blksend:
|
||||
for (c = 0; c < 32; c++) {
|
||||
AP_SERIAL_PORT.write(0xF5);
|
||||
}
|
||||
delay(10);
|
||||
if (apInfo.type != ESP32_C6) delay(10);
|
||||
txEnd();
|
||||
return bd->checksum;
|
||||
}
|
||||
@@ -250,6 +251,8 @@ bool sendChannelPower(struct espSetChannelPower* scp) {
|
||||
}
|
||||
if (waitCmdReply()) {
|
||||
txEnd();
|
||||
apInfo.channel = scp->channel;
|
||||
apInfo.power = scp->power;
|
||||
return true;
|
||||
}
|
||||
Serial.printf("SCP send failed in try %d\n", attempt);
|
||||
@@ -259,10 +262,27 @@ bool sendChannelPower(struct espSetChannelPower* scp) {
|
||||
return false;
|
||||
}
|
||||
bool sendPing() {
|
||||
Serial.print("ping");
|
||||
int t = millis();
|
||||
if (!txStart()) return false;
|
||||
for (uint8_t attempt = 0; attempt < 5; attempt++) {
|
||||
cmdReplyValue = CMD_REPLY_WAIT;
|
||||
AP_SERIAL_PORT.print("RDY?");
|
||||
if (waitCmdReply()) {
|
||||
txEnd();
|
||||
Serial.printf(" ok, %dms\n", millis() - t);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
txEnd();
|
||||
Serial.println(" failed");
|
||||
return false;
|
||||
}
|
||||
bool sendGetInfo() {
|
||||
if (!txStart()) return false;
|
||||
for (uint8_t attempt = 0; attempt < 5; attempt++) {
|
||||
cmdReplyValue = CMD_REPLY_WAIT;
|
||||
AP_SERIAL_PORT.print("NFO?");
|
||||
if (waitCmdReply()) {
|
||||
txEnd();
|
||||
return true;
|
||||
@@ -271,11 +291,11 @@ bool sendPing() {
|
||||
txEnd();
|
||||
return false;
|
||||
}
|
||||
bool sendGetInfo() {
|
||||
bool sendHighspeed() {
|
||||
if (!txStart()) return false;
|
||||
for (uint8_t attempt = 0; attempt < 5; attempt++) {
|
||||
cmdReplyValue = CMD_REPLY_WAIT;
|
||||
AP_SERIAL_PORT.print("NFO?");
|
||||
AP_SERIAL_PORT.print("HSPD");
|
||||
if (waitCmdReply()) {
|
||||
txEnd();
|
||||
return true;
|
||||
@@ -312,17 +332,15 @@ void rxCmdProcessor(void* parameter) {
|
||||
processBlockRequest((struct espBlockRequest*)rxcmd->data);
|
||||
#ifdef HAS_RGB_LED
|
||||
shortBlink(CRGB::Blue);
|
||||
#else
|
||||
quickBlink(3);
|
||||
#endif
|
||||
quickBlink(3);
|
||||
break;
|
||||
case RX_CMD_ADR:
|
||||
processDataReq((struct espAvailDataReq*)rxcmd->data, true);
|
||||
#ifdef HAS_RGB_LED
|
||||
shortBlink(CRGB::Aqua);
|
||||
#else
|
||||
quickBlink(1);
|
||||
#endif
|
||||
quickBlink(1);
|
||||
break;
|
||||
case RX_CMD_XFC:
|
||||
processXferComplete((struct espXferComplete*)rxcmd->data, true);
|
||||
@@ -336,6 +354,7 @@ void rxCmdProcessor(void* parameter) {
|
||||
case RX_CMD_RSET:
|
||||
Serial.println("AP did reset, resending pending\n");
|
||||
refreshAllPending();
|
||||
sendChannelPower(&curChannel);
|
||||
break;
|
||||
}
|
||||
if (rxcmd->data) free(rxcmd->data);
|
||||
@@ -357,7 +376,7 @@ void rxSerialTask(void* parameter) {
|
||||
lastchar = AP_SERIAL_PORT.read();
|
||||
switch (RXState) {
|
||||
case ZBS_RX_WAIT_HEADER:
|
||||
// Serial.write(lastchar);
|
||||
Serial.write(lastchar);
|
||||
// shift characters in
|
||||
for (uint8_t c = 0; c < 3; c++) {
|
||||
cmdbuffer[c] = cmdbuffer[c + 1];
|
||||
@@ -413,6 +432,7 @@ void rxSerialTask(void* parameter) {
|
||||
pktindex = 0;
|
||||
packetp = (uint8_t*)calloc(sizeof(struct espBlockRequest) + 8, 1);
|
||||
memset(cmdbuffer, 0x00, 4);
|
||||
lastAPActivity = millis();
|
||||
}
|
||||
if (strncmp(cmdbuffer, "ADR>", 4) == 0) {
|
||||
RXState = ZBS_RX_WAIT_DATA_REQ;
|
||||
@@ -420,6 +440,7 @@ void rxSerialTask(void* parameter) {
|
||||
pktindex = 0;
|
||||
packetp = (uint8_t*)calloc(sizeof(struct espAvailDataReq) + 8, 1);
|
||||
memset(cmdbuffer, 0x00, 4);
|
||||
lastAPActivity = millis();
|
||||
}
|
||||
if (strncmp(cmdbuffer, "XFC>", 4) == 0) {
|
||||
RXState = ZBS_RX_WAIT_XFERCOMPLETE;
|
||||
@@ -536,21 +557,26 @@ void rxSerialTask(void* parameter) {
|
||||
} // end of while(1)
|
||||
}
|
||||
|
||||
#ifdef FLASHER_DEBUG_RXD
|
||||
void rxSerialTask2(void* parameter) {
|
||||
char lastchar = 0;
|
||||
Serial2.begin(115200, SERIAL_8N1, FLASHER_DEBUG_TXD, FLASHER_DEBUG_RXD);
|
||||
while (1) {
|
||||
while (Serial2.available()) {
|
||||
lastchar = Serial2.read();
|
||||
Serial.write(lastchar);
|
||||
}
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void ShowAPInfo() {
|
||||
Serial.printf("| AP Info - type %02X |\n", apInfo.type);
|
||||
Serial.printf("\n| AP Info - type %02X |\n", apInfo.type);
|
||||
Serial.printf("| Ch | 0x%02X |\n", apInfo.channel);
|
||||
Serial.printf("| Power| %02X |\n", apInfo.power);
|
||||
Serial.printf("| MAC | %02X%02X%02X%02X%02X%02X%02X%02X |\n", apInfo.mac[7], apInfo.mac[6], apInfo.mac[5], apInfo.mac[4], apInfo.mac[3], apInfo.mac[2], apInfo.mac[1], apInfo.mac[0]);
|
||||
Serial.printf("| Ver | 0x%04X |\n", apInfo.version);
|
||||
|
||||
/*if (apInfo.type == SOLUM_154_SSD1619 || apInfo.type == SOLUM_29_SSD1619 || apInfo.type == SOLUM_29_UC8151 || apInfo.type == 0xE0) {
|
||||
tagRecord* taginfo = nullptr;
|
||||
taginfo = tagRecord::findByMAC(apInfo.mac);
|
||||
if (taginfo != nullptr) {
|
||||
taginfo->contentMode = 21;
|
||||
taginfo->nextupdate = 0;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
void notifySegmentedFlash() {
|
||||
@@ -595,14 +621,24 @@ void segmentedShowIp() {
|
||||
bool bringAPOnline() {
|
||||
apInfo.isOnline = false;
|
||||
apInfo.state = AP_STATE_OFFLINE;
|
||||
APTagReset();
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
// try without rebooting
|
||||
AP_SERIAL_PORT.updateBaudRate(115200);
|
||||
uint32_t bootTimeout = millis();
|
||||
bool APrdy = false;
|
||||
while ((!APrdy) && (millis() - bootTimeout < 10 * 1000)) {
|
||||
while ((!APrdy) && (millis() - bootTimeout < 3 * 1000)) {
|
||||
APrdy = sendPing();
|
||||
vTaskDelay(300 / portTICK_PERIOD_MS);
|
||||
}
|
||||
if (!APrdy) {
|
||||
APTagReset();
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
bootTimeout = millis();
|
||||
APrdy = false;
|
||||
while ((!APrdy) && (millis() - bootTimeout < 10 * 1000)) {
|
||||
APrdy = sendPing();
|
||||
vTaskDelay(300 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
if (!APrdy) {
|
||||
return false;
|
||||
} else {
|
||||
@@ -613,6 +649,15 @@ bool bringAPOnline() {
|
||||
apInfo.state = AP_STATE_OFFLINE;
|
||||
return false;
|
||||
}
|
||||
if (apInfo.type == ESP32_C6) {
|
||||
if (sendHighspeed()) {
|
||||
AP_SERIAL_PORT.flush();
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
AP_SERIAL_PORT.updateBaudRate(2000000);
|
||||
Serial.println("switched to 2000000 baud");
|
||||
}
|
||||
}
|
||||
|
||||
vTaskDelay(200 / portTICK_PERIOD_MS);
|
||||
apInfo.isOnline = true;
|
||||
apInfo.state = AP_STATE_ONLINE;
|
||||
@@ -623,6 +668,9 @@ bool bringAPOnline() {
|
||||
void APTask(void* parameter) {
|
||||
xTaskCreate(rxCmdProcessor, "rxCmdProcessor", 4000, NULL, configMAX_PRIORITIES - 10, NULL);
|
||||
xTaskCreate(rxSerialTask, "rxSerialTask", 1750, NULL, configMAX_PRIORITIES - 4, NULL);
|
||||
#ifdef FLASHER_DEBUG_RXD
|
||||
xTaskCreate(rxSerialTask2, "rxSerialTask2", 1750, NULL, configMAX_PRIORITIES - 4, NULL);
|
||||
#endif
|
||||
|
||||
#if (AP_PROCESS_PORT == FLASHER_AP_PORT)
|
||||
AP_SERIAL_PORT.begin(115200, SERIAL_8N1, FLASHER_AP_RXD, FLASHER_AP_TXD);
|
||||
@@ -638,7 +686,7 @@ void APTask(void* parameter) {
|
||||
|
||||
bringAPOnline();
|
||||
|
||||
if (checkForcedAPFlash()) {
|
||||
if (checkForcedAPFlash() && FLASHER_AP_MOSI != -1) {
|
||||
if (apInfo.type == SOLUM_SEG_UK && apInfo.isOnline) {
|
||||
notifySegmentedFlash();
|
||||
}
|
||||
@@ -666,7 +714,7 @@ void APTask(void* parameter) {
|
||||
|
||||
uint16_t fsversion;
|
||||
fsversion = getAPUpdateVersion(apInfo.type);
|
||||
if ((fsversion) && (apInfo.version != fsversion)) {
|
||||
if ((fsversion) && (apInfo.version != fsversion) && (FLASHER_AP_MOSI != -1)) {
|
||||
Serial.printf("Firmware version on LittleFS: %04X\n", fsversion);
|
||||
|
||||
Serial.printf("We're going to try to update the AP's FW in\n");
|
||||
@@ -708,72 +756,74 @@ void APTask(void* parameter) {
|
||||
// AP unavailable, maybe time to flash?
|
||||
apInfo.isOnline = false;
|
||||
apInfo.state = AP_STATE_OFFLINE;
|
||||
Serial.println("I wasn't able to connect to a ZBS (AP) tag.\n");
|
||||
Serial.printf("This could be the first time this AP is booted and the AP-tag may be unflashed. We'll try to flash it!\n");
|
||||
Serial.printf("I wasn't able to connect to a ZBS (AP) tag.\n");
|
||||
Serial.printf("This could be the first time this AP is booted and the AP-tag may be unflashed.\n");
|
||||
Serial.printf("If this tag was previously flashed succesfully but this message still shows up, there's probably something wrong with the serial connections.\n");
|
||||
Serial.printf("The build of this firmware expects an AP tag with TXD/RXD on ESP32 pins %d and %d, does this match with your wiring?\n", FLASHER_AP_RXD, FLASHER_AP_TXD);
|
||||
Serial.printf("Performing firmware flash in about %d seconds!\n", FLASH_TIMEOUT);
|
||||
flashCountDown(FLASH_TIMEOUT);
|
||||
if (doAPFlash()) {
|
||||
checkWaitPowerCycle();
|
||||
if (bringAPOnline()) {
|
||||
// AP works
|
||||
ShowAPInfo();
|
||||
if (apInfo.type == SOLUM_SEG_UK) {
|
||||
segmentedShowIp();
|
||||
showAPSegmentedInfo(apInfo.mac, true);
|
||||
}
|
||||
refreshAllPending();
|
||||
} else {
|
||||
Serial.printf("Failed to bring up the AP after successful flashing... That's not supposed to happen!\n");
|
||||
Serial.printf("This generally means that the flasher connections (MISO/MOSI/CLK/RESET/CS) are okay,\n");
|
||||
Serial.printf("but we can't (yet) talk to the AP over serial lines. Verify the pins mentioned above.\n\n");
|
||||
if (FLASHER_AP_MOSI != -1) {
|
||||
Serial.printf("Performing firmware flash in about %d seconds!\n", FLASH_TIMEOUT);
|
||||
flashCountDown(FLASH_TIMEOUT);
|
||||
if (doAPFlash()) {
|
||||
checkWaitPowerCycle();
|
||||
if (bringAPOnline()) {
|
||||
// AP works
|
||||
ShowAPInfo();
|
||||
if (apInfo.type == SOLUM_SEG_UK) {
|
||||
segmentedShowIp();
|
||||
showAPSegmentedInfo(apInfo.mac, true);
|
||||
}
|
||||
refreshAllPending();
|
||||
} else {
|
||||
Serial.printf("Failed to bring up the AP after successful flashing... That's not supposed to happen!\n");
|
||||
Serial.printf("This generally means that the flasher connections (MISO/MOSI/CLK/RESET/CS) are okay,\n");
|
||||
Serial.printf("but we can't (yet) talk to the AP over serial lines. Verify the pins mentioned above.\n\n");
|
||||
|
||||
#ifndef POWER_NO_SOFT_POWER
|
||||
Serial.printf("The firmware you're using expects soft power control over the AP tag; if it can't\n");
|
||||
Serial.printf("power-cycle the AP-tag using GPIO pin %d, this can cause this very same issue.\n", APpowerPins[0]);
|
||||
Serial.printf("The firmware you're using expects soft power control over the AP tag; if it can't\n");
|
||||
Serial.printf("power-cycle the AP-tag using GPIO pin %d, this can cause this very same issue.\n", APpowerPins[0]);
|
||||
#endif
|
||||
|
||||
#ifdef HAS_RGB_LED
|
||||
showColorPattern(CRGB::Red, CRGB::Yellow, CRGB::Red);
|
||||
showColorPattern(CRGB::Red, CRGB::Yellow, CRGB::Red);
|
||||
#endif
|
||||
apInfo.isOnline = false;
|
||||
apInfo.state = AP_STATE_FAILED;
|
||||
}
|
||||
} else {
|
||||
// failed to flash
|
||||
#ifdef HAS_RGB_LED
|
||||
showColorPattern(CRGB::Red, CRGB::Red, CRGB::Red);
|
||||
#endif
|
||||
apInfo.isOnline = false;
|
||||
apInfo.state = AP_STATE_FAILED;
|
||||
}
|
||||
} else {
|
||||
// failed to flash
|
||||
#ifdef HAS_RGB_LED
|
||||
showColorPattern(CRGB::Red, CRGB::Red, CRGB::Red);
|
||||
#endif
|
||||
apInfo.isOnline = false;
|
||||
apInfo.state = AP_STATE_FAILED;
|
||||
Serial.println("Failed to flash the AP :(");
|
||||
Serial.println("Seems like you're running into some issues with the wiring, or (very small chance) the tag itself");
|
||||
Serial.println("This ESP32-build expects the following pins connected to the ZBS243:");
|
||||
Serial.println("--- ZBS243 based tag ESP32 ---");
|
||||
Serial.printf(" TXD ---------------- %02d\n", FLASHER_AP_RXD);
|
||||
Serial.printf(" RXD ---------------- %02d\n", FLASHER_AP_TXD);
|
||||
Serial.printf(" CS/SS ---------------- %02d\n", FLASHER_AP_SS);
|
||||
Serial.printf(" MOSI ---------------- %02d\n", FLASHER_AP_MOSI);
|
||||
Serial.printf(" MISO ---------------- %02d\n", FLASHER_AP_MISO);
|
||||
Serial.printf(" CLK ---------------- %02d\n", FLASHER_AP_CLK);
|
||||
Serial.printf(" RSET ---------------- %02d\n", FLASHER_AP_RESET);
|
||||
Serial.println("Failed to flash the AP :(");
|
||||
Serial.println("Seems like you're running into some issues with the wiring, or (very small chance) the tag itself");
|
||||
Serial.println("This ESP32-build expects the following pins connected to the ZBS243:");
|
||||
Serial.println("--- ZBS243 based tag ESP32 ---");
|
||||
Serial.printf(" TXD ---------------- %02d\n", FLASHER_AP_RXD);
|
||||
Serial.printf(" RXD ---------------- %02d\n", FLASHER_AP_TXD);
|
||||
Serial.printf(" CS/SS ---------------- %02d\n", FLASHER_AP_SS);
|
||||
Serial.printf(" MOSI ---------------- %02d\n", FLASHER_AP_MOSI);
|
||||
Serial.printf(" MISO ---------------- %02d\n", FLASHER_AP_MISO);
|
||||
Serial.printf(" CLK ---------------- %02d\n", FLASHER_AP_CLK);
|
||||
Serial.printf(" RSET ---------------- %02d\n", FLASHER_AP_RESET);
|
||||
#ifdef POWER_NO_SOFT_POWER
|
||||
Serial.printf("Your firmware is configured without soft power control. This means you'll have to manually power-cycle the tag after flashing.\n");
|
||||
Serial.printf("Your firmware is configured without soft power control. This means you'll have to manually power-cycle the tag after flashing.\n");
|
||||
#else
|
||||
Serial.printf(" POWER ---------------- %02d\n", APpowerPins[0]);
|
||||
Serial.printf(" POWER ---------------- %02d\n", APpowerPins[0]);
|
||||
#endif
|
||||
Serial.println("Please verify your wiring and try again!");
|
||||
}
|
||||
Serial.println("Please verify your wiring and try again!");
|
||||
}
|
||||
#ifdef HAS_SDCARD
|
||||
if (SD_CARD_CLK == FLASHER_AP_CLK ||
|
||||
SD_CARD_MISO == FLASHER_AP_MISO ||
|
||||
SD_CARD_MOSI == FLASHER_AP_MOSI) {
|
||||
Serial.println("Reseting in 30 seconds to restore SPI state!\n");
|
||||
flashCountDown(30);
|
||||
ESP.restart();
|
||||
}
|
||||
if (SD_CARD_CLK == FLASHER_AP_CLK ||
|
||||
SD_CARD_MISO == FLASHER_AP_MISO ||
|
||||
SD_CARD_MOSI == FLASHER_AP_MOSI) {
|
||||
Serial.println("Reseting in 30 seconds to restore SPI state!\n");
|
||||
flashCountDown(30);
|
||||
ESP.restart();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t attempts = 0;
|
||||
|
||||
@@ -77,14 +77,16 @@ void wsSendSysteminfo() {
|
||||
time_t now;
|
||||
time(&now);
|
||||
static int freeSpaceLastRun = 0;
|
||||
static size_t freeSpace = Storage.freeSpace();
|
||||
sys["currtime"] = now;
|
||||
sys["heap"] = ESP.getFreeHeap();
|
||||
sys["recordcount"] = tagDB.size();
|
||||
sys["dbsize"] = dbSize();
|
||||
if (millis() - freeSpaceLastRun > 30000) {
|
||||
sys["littlefsfree"] = Storage.freeSpace();
|
||||
freeSpace = Storage.freeSpace();
|
||||
freeSpaceLastRun = millis();
|
||||
}
|
||||
sys["littlefsfree"] = freeSpace;
|
||||
sys["apstate"] = apInfo.state;
|
||||
sys["runstate"] = config.runStatus;
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32)
|
||||
@@ -98,7 +100,7 @@ void wsSendSysteminfo() {
|
||||
setVarDB("ap_ch", String(apInfo.channel));
|
||||
|
||||
static uint32_t tagcounttimer = 0;
|
||||
if (millis() - tagcounttimer > 60000) {
|
||||
if (millis() - tagcounttimer > 60000 || tagcounttimer == 0) {
|
||||
uint32_t timeoutcount = 0;
|
||||
uint32_t tagcount = getTagCount(timeoutcount);
|
||||
char result[40];
|
||||
@@ -318,9 +320,11 @@ void init_web() {
|
||||
if (strcmp(cmdValue, "deepsleep") == 0) {
|
||||
sendTagCommand(mac, CMD_DO_DEEPSLEEP, !taginfo->isExternal);
|
||||
}
|
||||
if (strcmp(cmdValue, "ledflash") == 0) {
|
||||
}
|
||||
request->send(200, "text/plain", "Ok, done");
|
||||
} else {
|
||||
request->send(200, "text/plain", "Error: mac not found");
|
||||
request->send(400, "text/plain", "Error: mac not found");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -328,6 +332,55 @@ void init_web() {
|
||||
}
|
||||
});
|
||||
|
||||
server.on("/led_flash", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||
// color picker: https://roger-random.github.io/RGB332_color_wheel_three.js/
|
||||
// http GET to /led_flash?mac=000000000000&pattern=3/0x1C,4,5/0xE0,3,1/0x4F,5,10/5
|
||||
// (flashDuration/color1,flashCount1,delay1/color2,flashCount2,delay2/color3,flashCount3,delay3/repeats)
|
||||
if (request->hasParam("mac")) {
|
||||
String dst = request->getParam("mac")->value();
|
||||
uint8_t mac[8];
|
||||
if (hex2mac(dst, mac)) {
|
||||
tagRecord *taginfo = tagRecord::findByMAC(mac);
|
||||
if (taginfo != nullptr) {
|
||||
if (request->hasParam("pattern")) {
|
||||
String pattern = request->getParam("pattern")->value();
|
||||
struct ledFlash flashData;
|
||||
|
||||
int values[13];
|
||||
int numValues = sscanf(
|
||||
pattern.c_str(),
|
||||
"%i/%i,%i,%i/%i,%i,%i/%i,%i,%i/%i",
|
||||
&values[1], &values[2], &values[3], &values[4], &values[5],
|
||||
&values[6], &values[7], &values[8], &values[9], &values[10], &values[11]);
|
||||
|
||||
if (numValues != 11) {
|
||||
request->send(400, "text/plain", "Error: wrong number of inputs in pattern");
|
||||
return;
|
||||
} else {
|
||||
flashData.mode = 0;
|
||||
flashData.flashDuration = values[1] & 0x0F;
|
||||
flashData.color1 = values[2];
|
||||
flashData.flashCount1 = values[3] & 0x0F;
|
||||
flashData.delay1 = values[4] & 0x0F;
|
||||
flashData.color2 = values[5];
|
||||
flashData.flashCount2 = values[6] & 0x0F;
|
||||
flashData.delay2 = values[7] & 0x0F;
|
||||
flashData.color3 = values[8];
|
||||
flashData.flashCount3 = values[9] & 0x0F;
|
||||
flashData.delay3 = values[10] & 0x0F;
|
||||
flashData.repeats = values[11];
|
||||
flashData.spare = 0;
|
||||
|
||||
const uint8_t *payload = reinterpret_cast<const uint8_t *>(&flashData);
|
||||
sendTagCommand(mac, CMD_DO_LEDFLASH, !taginfo->isExternal, payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
request->send(400, "text/plain", "parameters are missing");
|
||||
});
|
||||
|
||||
server.on("/get_ap_config", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||
UDPcomm udpsync;
|
||||
udpsync.getAPList();
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "tag_db.h"
|
||||
#include "udp.h"
|
||||
#include "web.h"
|
||||
#include "ips_display.h"
|
||||
|
||||
uint8_t WifiManager::apClients = 0;
|
||||
uint8_t x_buffer[100];
|
||||
@@ -29,10 +30,17 @@ WifiManager::WifiManager() {
|
||||
WiFi.onEvent(WiFiEvent);
|
||||
}
|
||||
|
||||
void WifiManager::terminalLog(String text) {
|
||||
Serial.println(text);
|
||||
#ifdef YELLOW_IPS_AP
|
||||
TFTLog(text);
|
||||
#endif
|
||||
}
|
||||
|
||||
void WifiManager::poll() {
|
||||
if (wifiStatus == AP && millis() > _nextReconnectCheck && _ssid != "") {
|
||||
if (apClients == 0) {
|
||||
Serial.println("Attempting to reconnect to WiFi.");
|
||||
terminalLog("Attempting to reconnect to WiFi.");
|
||||
logLine("Attempting to reconnect to WiFi.");
|
||||
_APstarted = false;
|
||||
wifiStatus = NOINIT;
|
||||
@@ -45,7 +53,7 @@ void WifiManager::poll() {
|
||||
if (wifiStatus == CONNECTED && millis() > _nextReconnectCheck) {
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
_connected = false;
|
||||
Serial.println("WiFi connection lost. Attempting to reconnect.");
|
||||
terminalLog("WiFi connection lost. Attempting to reconnect.");
|
||||
logLine("WiFi connection lost. Attempting to reconnect.");
|
||||
WiFi.reconnect();
|
||||
waitForConnection();
|
||||
@@ -63,12 +71,12 @@ bool WifiManager::connectToWifi() {
|
||||
_ssid = preferences.getString("ssid", WiFi_SSID());
|
||||
_pass = preferences.getString("pw", WiFi_psk());
|
||||
if (_ssid == "") {
|
||||
Serial.println("No connection information specified");
|
||||
logLine("No connection information specified");
|
||||
terminalLog("No connection information saved");
|
||||
logLine("No connection information saved");
|
||||
startManagementServer();
|
||||
return false;
|
||||
}
|
||||
Serial.println("Stored ssid: " + String(_ssid));
|
||||
terminalLog("Stored ssid: " + String(_ssid));
|
||||
|
||||
String ip = preferences.getString("ip", "");
|
||||
String mask = preferences.getString("mask", "");
|
||||
@@ -80,7 +88,7 @@ bool WifiManager::connectToWifi() {
|
||||
if (staticIP.fromString(ip) && subnetMask.fromString(mask) && gatewayIP.fromString(gw)) {
|
||||
if (dns.length() > 0) dnsIP.fromString(dns);
|
||||
WiFi.config(staticIP, gatewayIP, subnetMask, dnsIP);
|
||||
Serial.println("Setting static IP");
|
||||
terminalLog("Setting static IP: " + ip);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +106,7 @@ bool WifiManager::connectToWifi(String ssid, String pass, bool savewhensuccessfu
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.setSleep(WIFI_PS_NONE);
|
||||
|
||||
Serial.println("Connecting to WiFi...");
|
||||
terminalLog("Connecting to WiFi...");
|
||||
logLine("Connecting to WiFi...");
|
||||
WiFi.persistent(savewhensuccessfull);
|
||||
WiFi.begin(_ssid.c_str(), _pass.c_str());
|
||||
@@ -112,7 +120,7 @@ bool WifiManager::waitForConnection() {
|
||||
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
if (millis() > timeout) {
|
||||
Serial.println("Unable to connect to WiFi");
|
||||
terminalLog("!Unable to connect to WiFi");
|
||||
logLine("Unable to connect to WiFi");
|
||||
startManagementServer();
|
||||
return false;
|
||||
@@ -131,8 +139,8 @@ bool WifiManager::waitForConnection() {
|
||||
WiFi.setAutoReconnect(true);
|
||||
WiFi.persistent(true);
|
||||
IPAddress IP = WiFi.localIP();
|
||||
Serial.printf("Connected! IP Address: %s\n", IP.toString().c_str());
|
||||
logLine("Connected! IP Address: " + String(IP.toString().c_str()));
|
||||
terminalLog("Connected!");
|
||||
logLine("Connected!");
|
||||
_nextReconnectCheck = millis() + _reconnectIntervalCheck;
|
||||
wifiStatus = CONNECTED;
|
||||
return true;
|
||||
@@ -140,13 +148,13 @@ bool WifiManager::waitForConnection() {
|
||||
|
||||
void WifiManager::startManagementServer() {
|
||||
if (!_APstarted) {
|
||||
Serial.println("Starting configuration AP, ssid OpenEPaperLink");
|
||||
terminalLog("Starting configuration AP, ssid: OpenEPaperLink");
|
||||
logLine("Starting configuration AP, ssid OpenEPaperLink");
|
||||
WiFi.mode(WIFI_AP);
|
||||
WiFi.softAP("OpenEPaperLink", "", 1, false);
|
||||
WiFi.softAPsetHostname("OpenEPaperLink");
|
||||
IPAddress IP = WiFi.softAPIP();
|
||||
Serial.printf("IP Address: %s\n", IP.toString().c_str());
|
||||
terminalLog("Connect to it, visit http://" + String(IP.toString().c_str()) + "/setup");
|
||||
_APstarted = true;
|
||||
_nextReconnectCheck = millis() + _retryIntervalCheck;
|
||||
wifiStatus = AP;
|
||||
@@ -194,7 +202,7 @@ void WifiManager::WiFiEvent(WiFiEvent_t event) {
|
||||
eventname = "Connected to access point";
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
|
||||
eventname = "Disconnected from WiFi access point";
|
||||
// eventname = "Disconnected from WiFi access point";
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE:
|
||||
eventname = "Authentication mode of access point has changed";
|
||||
@@ -208,27 +216,27 @@ void WifiManager::WiFiEvent(WiFiEvent_t event) {
|
||||
break;
|
||||
|
||||
case ARDUINO_EVENT_WIFI_AP_START:
|
||||
eventname = "WiFi access point started";
|
||||
// eventname = "WiFi access point started";
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_AP_STOP:
|
||||
eventname = "WiFi access point stopped";
|
||||
// eventname = "WiFi access point stopped";
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_AP_STACONNECTED:
|
||||
apClients++;
|
||||
eventname = "Client connected";
|
||||
// eventname = "Client connected";
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_AP_STADISCONNECTED:
|
||||
apClients--;
|
||||
eventname = "Client disconnected";
|
||||
// eventname = "Client disconnected";
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED:
|
||||
eventname = "Assigned IP address to client";
|
||||
// eventname = "Assigned IP address to client";
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
Serial.println(eventname);
|
||||
terminalLog(eventname);
|
||||
logLine("WiFi event [" + String(event) + "]: " + eventname);
|
||||
}
|
||||
|
||||
|
||||
@@ -195,6 +195,8 @@
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
const $ = document.querySelector.bind(document);
|
||||
|
||||
if (typeof XMLHttpRequest === "undefined") {
|
||||
XMLHttpRequest = function () {
|
||||
try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e) { }
|
||||
@@ -403,8 +405,81 @@
|
||||
|
||||
edfname.value = filename + "." + ext;
|
||||
ge("editor").style.display = "none";
|
||||
|
||||
preview.style.display = "block";
|
||||
preview.innerHTML = '<img src="/edit?edit=' + path + '&_cb=' + Date.now() + '" style="max-width:100%; max-height:100%; margin:auto; display:block;" />';
|
||||
if (ext == "raw" || ext == "pending") {
|
||||
let storedTagTypes = localStorage.getItem("tagTypes");
|
||||
let tagTypes = JSON.parse(storedTagTypes);
|
||||
let mac = name.substring(name.lastIndexOf('/') + 1);
|
||||
let targetDiv = null;
|
||||
if (window.opener && !window.opener.closed) {
|
||||
targetDiv = window.opener.document.querySelector(`div[data-mac="${mac}"]`);
|
||||
} else {
|
||||
preview.innerHTML = `<p class=\"tvu\">I cannot reach the window with the tag overview. Close this window, and open it again from the tag overview.</p>`;
|
||||
return;
|
||||
}
|
||||
if (targetDiv) {
|
||||
preview.innerHTML = `<p class=\"tvu\">Preview image for tag ${mac}<p><p><canvas id=\"previewimg\"></p>`;
|
||||
var hwtype = targetDiv.getAttribute("data-hwtype");
|
||||
console.log("data-hwtype:", hwtype);
|
||||
|
||||
const canvas = $('#previewimg');
|
||||
canvas.style.display = 'block';
|
||||
fetch(path)
|
||||
.then(response => response.arrayBuffer())
|
||||
.then(buffer => {
|
||||
[canvas.width, canvas.height] = [tagTypes[hwtype].width, tagTypes[hwtype].height] || [0, 0];
|
||||
if (tagTypes[hwtype].rotatebuffer) [canvas.width, canvas.height] = [canvas.height, canvas.width];
|
||||
const ctx = canvas.getContext('2d');
|
||||
const imageData = ctx.createImageData(canvas.width, canvas.height);
|
||||
const data = new Uint8ClampedArray(buffer);
|
||||
if (data.length == 0) canvas.style.display = 'none';
|
||||
|
||||
if (tagTypes[hwtype].bpp == 16) {
|
||||
const is16Bit = data.length == tagTypes[hwtype].width * tagTypes[hwtype].height * 2;
|
||||
for (let i = 0; i < min(tagTypes[hwtype].width * tagTypes[hwtype].height, data.length); i++) {
|
||||
const dataIndex = is16Bit ? i * 2 : i;
|
||||
const rgb = is16Bit ? (data[dataIndex] << 8) | data[dataIndex + 1] : data[dataIndex];
|
||||
|
||||
imageData.data[i * 4] = is16Bit ? ((rgb >> 11) & 0x1F) << 3 : (((rgb >> 5) & 0x07) << 5) * 1.13;
|
||||
imageData.data[i * 4 + 1] = is16Bit ? ((rgb >> 5) & 0x3F) << 2 : (((rgb >> 2) & 0x07) << 5) * 1.13;
|
||||
imageData.data[i * 4 + 2] = is16Bit ? (rgb & 0x1F) << 3 : ((rgb & 0x03) << 6) * 1.3;
|
||||
imageData.data[i * 4 + 3] = 255;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
const offsetRed = (data.length >= (canvas.width * canvas.height / 8) * 2) ? canvas.width * canvas.height / 8 : 0;
|
||||
let pixelValue = 0;
|
||||
const colorTable = tagTypes[hwtype].colortable;
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
for (let j = 0; j < 8; j++) {
|
||||
const pixelIndex = i * 8 + j;
|
||||
if (offsetRed) {
|
||||
pixelValue = ((data[i] & (1 << (7 - j))) ? 1 : 0) | (((data[i + offsetRed] & (1 << (7 - j))) ? 1 : 0) << 1);
|
||||
} else {
|
||||
pixelValue = ((data[i] & (1 << (7 - j))) ? 1 : 0);
|
||||
}
|
||||
imageData.data[pixelIndex * 4] = colorTable[pixelValue][0];
|
||||
imageData.data[pixelIndex * 4 + 1] = colorTable[pixelValue][1];
|
||||
imageData.data[pixelIndex * 4 + 2] = colorTable[pixelValue][2];
|
||||
imageData.data[pixelIndex * 4 + 3] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx.putImageData(imageData, 0, 0);
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
|
||||
} else {
|
||||
preview.innerHTML = `<p class=\"tvu\">No current tag found with this mac. You can safely delete this file.</p>`;
|
||||
}
|
||||
} else {
|
||||
preview.innerHTML = '<img src="/edit?edit=' + path + '&_cb=' + Date.now() + '" style="max-width:100%; max-height:100%; margin:auto; display:block;" />';
|
||||
}
|
||||
}
|
||||
|
||||
function fillFileMenu(el, path) {
|
||||
@@ -596,6 +671,7 @@
|
||||
case "gif":
|
||||
case "bmp":
|
||||
case "pending":
|
||||
case "raw":
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,6 +82,7 @@
|
||||
<label for="apcfgledbrightness">LED brightness</label>
|
||||
<select id="apcfgledbrightness">
|
||||
<option value="-1">off</option>
|
||||
<option value="20">10%</option>
|
||||
<option value="64">25%</option>
|
||||
<option value="128" selected>50%</option>
|
||||
<option value="192">75%</option>
|
||||
|
||||
@@ -4,6 +4,8 @@ const WAKEUP_REASON_TIMED = 0;
|
||||
const WAKEUP_REASON_BOOT = 1;
|
||||
const WAKEUP_REASON_GPIO = 2;
|
||||
const WAKEUP_REASON_NFC = 3;
|
||||
const WAKEUP_REASON_BUTTON1 = 4;
|
||||
const WAKEUP_REASON_BUTTON2 = 5;
|
||||
const WAKEUP_REASON_FIRSTBOOT = 0xFC;
|
||||
const WAKEUP_REASON_NETWORK_SCAN = 0xFD;
|
||||
const WAKEUP_REASON_WDT_RESET = 0xFE;
|
||||
@@ -250,6 +252,14 @@ function processTags(tagArray) {
|
||||
$('#tag' + tagmac + ' .nextcheckin').innerHTML = "GPIO wakeup"
|
||||
$('#tag' + tagmac).style.background = "#c8f1bb";
|
||||
break;
|
||||
case WAKEUP_REASON_BUTTON1:
|
||||
$('#tag' + tagmac + ' .nextcheckin').innerHTML = "Button 1 pressed"
|
||||
$('#tag' + tagmac).style.background = "#c8f1bb";
|
||||
break;
|
||||
case WAKEUP_REASON_BUTTON2:
|
||||
$('#tag' + tagmac + ' .nextcheckin').innerHTML = "Button 2 pressed"
|
||||
$('#tag' + tagmac).style.background = "#c8f1bb";
|
||||
break;
|
||||
case WAKEUP_REASON_NFC:
|
||||
$('#tag' + tagmac + ' .nextcheckin').innerHTML = "NFC wakeup"
|
||||
break;
|
||||
@@ -933,6 +943,7 @@ async function getTagtype(hwtype) {
|
||||
busy: false
|
||||
};
|
||||
tagTypes[hwtype] = data;
|
||||
localStorage.setItem("tagTypes", JSON.stringify(tagTypes));
|
||||
getTagtypeBusy = false;
|
||||
return data;
|
||||
|
||||
@@ -1063,7 +1074,6 @@ function dropUpload() {
|
||||
const contextMenu = $('#context-menu');
|
||||
|
||||
$('#taglist').addEventListener('contextmenu', (e) => {
|
||||
console.log("contextmenu");
|
||||
e.preventDefault();
|
||||
|
||||
const clickedGridItem = e.target.closest('.tagcard');
|
||||
@@ -1095,7 +1105,10 @@ $('#taglist').addEventListener('contextmenu', (e) => {
|
||||
});
|
||||
contextMenu.appendChild(li);
|
||||
});
|
||||
const contextMenuPosition = { left: e.clientX, top: e.clientY };
|
||||
const contextMenuPosition = {
|
||||
left: e.clientX + window.scrollX,
|
||||
top: e.clientY + window.scrollY
|
||||
};
|
||||
contextMenu.style.left = `${contextMenuPosition.left}px`;
|
||||
contextMenu.style.top = `${contextMenuPosition.top}px`;
|
||||
contextMenu.style.display = 'block';
|
||||
|
||||
25
Tag_Flasher/patch_mac.py
Normal file
25
Tag_Flasher/patch_mac.py
Normal file
@@ -0,0 +1,25 @@
|
||||
import argparse
|
||||
|
||||
def patch_mac(file_path, mac):
|
||||
try:
|
||||
with open(file_path, "r+b") as file:
|
||||
offset = 0x0148
|
||||
mac_bytes = bytearray.fromhex(mac)
|
||||
mac_bytes.reverse() # Reverse the byte order
|
||||
|
||||
file.seek(offset)
|
||||
file.write(mac_bytes)
|
||||
print(f"MAC address patched successfully.")
|
||||
except FileNotFoundError:
|
||||
print("Error: File not found.")
|
||||
except Exception as e:
|
||||
print(f"An error occurred: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Patch MAC address in a binary firmware file for the 88MZ100 7.4 inch esl")
|
||||
parser.add_argument("-mac", required=True, help="MAC address (without colons)")
|
||||
parser.add_argument("filename", help="Binary file to patch")
|
||||
|
||||
args = parser.parse_args()
|
||||
patch_mac(args.filename, args.mac)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#define SOLUM_SEG_UK 0xF0
|
||||
#define SOLUM_SEG_EU 0xF1
|
||||
#define SOLUM_NODISPLAY 0xFF
|
||||
#define ESP32_C6 0xC6
|
||||
|
||||
#define SOLUM_M2_BWR_16 0x20
|
||||
#define SOLUM_M2_BWR_29 0x23
|
||||
@@ -55,10 +56,13 @@
|
||||
#define CMD_DO_SCAN 1
|
||||
#define CMD_DO_RESET_SETTINGS 2
|
||||
#define CMD_DO_DEEPSLEEP 3
|
||||
#define CMD_DO_LEDFLASH 4
|
||||
|
||||
#define WAKEUP_REASON_TIMED 0
|
||||
#define WAKEUP_REASON_GPIO 2
|
||||
#define WAKEUP_REASON_NFC 3
|
||||
#define WAKEUP_REASON_BUTTON1 4
|
||||
#define WAKEUP_REASON_BUTTON2 5
|
||||
#define WAKEUP_REASON_FIRSTBOOT 0xFC
|
||||
#define WAKEUP_REASON_NETWORK_SCAN 0xFD
|
||||
#define WAKEUP_REASON_WDT_RESET 0xFE
|
||||
|
||||
Reference in New Issue
Block a user