Add next gen profile and configurations (#67)
* fix: crash in picture animation * ble: add next gen profile * force read header from flash anyway * fix: bmlist: mem leak * feat: add reset option after legacy transfers
This commit is contained in:
committed by
GitHub
parent
512134607b
commit
4e556ab11f
@@ -369,28 +369,3 @@ void mDelaymS(uint16_t t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
int _write(int fd, char *buf, int size)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for(i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
#if DEBUG == Debug_UART0
|
|
||||||
while(R8_UART0_TFC == UART_FIFO_SIZE); /* 等待数据发送 */
|
|
||||||
R8_UART0_THR = *buf++; /* 发送数据 */
|
|
||||||
#elif DEBUG == Debug_UART1
|
|
||||||
while(R8_UART1_TFC == UART_FIFO_SIZE); /* 等待数据发送 */
|
|
||||||
R8_UART1_THR = *buf++; /* 发送数据 */
|
|
||||||
#elif DEBUG == Debug_UART2
|
|
||||||
while(R8_UART2_TFC == UART_FIFO_SIZE); /* 等待数据发送 */
|
|
||||||
R8_UART2_THR = *buf++; /* 发送数据 */
|
|
||||||
#elif DEBUG == Debug_UART3
|
|
||||||
while(R8_UART3_TFC == UART_FIFO_SIZE); /* 等待数据发送 */
|
|
||||||
R8_UART3_THR = *buf++; /* 发送数据 */
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|||||||
@@ -123,12 +123,6 @@ typedef volatile unsigned long long *PUINT64V;
|
|||||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
#define PRINT(X...) printf(X)
|
|
||||||
#else
|
|
||||||
#define PRINT(X...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Calculate the byte offset of a field in a structure of type */
|
/* Calculate the byte offset of a field in a structure of type */
|
||||||
#define FIELD_OFFSET(Type, Field) ((UINT16)&(((Type *)0)->Field))
|
#define FIELD_OFFSET(Type, Field) ((UINT16)&(((Type *)0)->Field))
|
||||||
|
|
||||||
|
|||||||
@@ -36,15 +36,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define Debug_UART0 0
|
|
||||||
#define Debug_UART1 1
|
|
||||||
#define Debug_UART2 2
|
|
||||||
#define Debug_UART3 3
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
#include <stdio.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 系统主频时钟(Hz)
|
* @brief 系统主频时钟(Hz)
|
||||||
*/
|
*/
|
||||||
|
|||||||
10
Makefile
10
Makefile
@@ -47,25 +47,27 @@ CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_clk.c \
|
|||||||
CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_uart0.c \
|
CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_uart0.c \
|
||||||
CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_timer1.c \
|
CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_timer1.c \
|
||||||
CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_pwm.c \
|
CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_pwm.c \
|
||||||
CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_usbhostClass.c \
|
|
||||||
CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_adc.c \
|
CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_adc.c \
|
||||||
CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_usbhostBase.c \
|
|
||||||
CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_timer3.c \
|
CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_timer3.c \
|
||||||
CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_timer0.c \
|
CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_timer0.c \
|
||||||
CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_usb2hostClass.c \
|
|
||||||
CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_flash.c \
|
CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_flash.c \
|
||||||
CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_uart1.c \
|
CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_uart1.c \
|
||||||
CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_usb2dev.c \
|
CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_usb2dev.c \
|
||||||
CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_usb2hostBase.c \
|
|
||||||
CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_spi1.c \
|
CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_spi1.c \
|
||||||
CH5xx_ble_firmware_library/RVMSIS/core_riscv.c \
|
CH5xx_ble_firmware_library/RVMSIS/core_riscv.c \
|
||||||
src/main.c \
|
src/main.c \
|
||||||
|
src/debug.c \
|
||||||
src/leddrv.c \
|
src/leddrv.c \
|
||||||
src/button.c \
|
src/button.c \
|
||||||
src/bmlist.c \
|
src/bmlist.c \
|
||||||
src/ble/profile/legacy.c \
|
src/ble/profile/legacy.c \
|
||||||
src/ble/profile/batt.c \
|
src/ble/profile/batt.c \
|
||||||
src/ble/profile/devinfo.c \
|
src/ble/profile/devinfo.c \
|
||||||
|
src/ble/profile/ng.c \
|
||||||
|
src/config.c \
|
||||||
|
src/legacyctrl.c \
|
||||||
|
src/util/crc.c \
|
||||||
|
src/ngctrl.c \
|
||||||
src/ble/setup.c \
|
src/ble/setup.c \
|
||||||
src/ble/peripheral.c \
|
src/ble/peripheral.c \
|
||||||
src/data.c \
|
src/data.c \
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "xbm.h"
|
#include "xbm.h"
|
||||||
#include "leddrv.h"
|
#include "leddrv.h"
|
||||||
#include "bmlist.h"
|
#include "bmlist.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
#define ANI_ANIMATION_STEPS (5) // steps
|
#define ANI_ANIMATION_STEPS (5) // steps
|
||||||
#define ANI_FIXED_STEPS (LED_COLS) // steps
|
#define ANI_FIXED_STEPS (LED_COLS) // steps
|
||||||
@@ -404,7 +405,7 @@ static void picture(bm_t *bm, uint16_t *fb, int step, int frame)
|
|||||||
int hc = LED_COLS / 2;
|
int hc = LED_COLS / 2;
|
||||||
int range = mod(step - 1, LED_COLS);
|
int range = mod(step - 1, LED_COLS);
|
||||||
|
|
||||||
if (range > LED_COLS/2) {
|
if (range > hc) {
|
||||||
still(bm, fb, frame);
|
still(bm, fb, frame);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -418,15 +419,10 @@ static void picture(bm_t *bm, uint16_t *fb, int step, int frame)
|
|||||||
0 : bm->buf[hc - i + frame];
|
0 : bm->buf[hc - i + frame];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i >= LED_COLS)
|
if (i >= hc)
|
||||||
return;
|
return;
|
||||||
fb[hc + i - 1] = -1;
|
fb[hc + i - 1] = -1;
|
||||||
fb[hc - i] = -1;
|
fb[hc - i] = -1;
|
||||||
|
|
||||||
for (i++; i< LED_COLS; i++) {
|
|
||||||
fb[hc + i - 1] = 0;
|
|
||||||
fb[hc - i] = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void picture_out(bm_t *bm, uint16_t *fb, int step)
|
static void picture_out(bm_t *bm, uint16_t *fb, int step)
|
||||||
@@ -442,7 +438,7 @@ static void picture_out(bm_t *bm, uint16_t *fb, int step)
|
|||||||
fb[hc + i - 1] = 0;
|
fb[hc + i - 1] = 0;
|
||||||
fb[hc - i] = 0;
|
fb[hc - i] = 0;
|
||||||
}
|
}
|
||||||
if (i >= LED_COLS)
|
if (i >= hc)
|
||||||
return;
|
return;
|
||||||
fb[hc + i - 1] = -1;
|
fb[hc + i - 1] = -1;
|
||||||
fb[hc - i] = -1;
|
fb[hc - i] = -1;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "CH58xBLE_LIB.h"
|
#include "CH58xBLE_LIB.h"
|
||||||
#include "setup.h"
|
#include "setup.h"
|
||||||
|
#include "../config.h"
|
||||||
|
|
||||||
#define ADV_UUID (0xFEE0)
|
#define ADV_UUID (0xFEE0)
|
||||||
|
|
||||||
@@ -24,29 +25,6 @@ typedef struct
|
|||||||
|
|
||||||
#define CONN_TIMEOUT 100 // Supervision timeout (units of 10ms)
|
#define CONN_TIMEOUT 100 // Supervision timeout (units of 10ms)
|
||||||
|
|
||||||
// GAP - SCAN RSP data (max size = 31 bytes)
|
|
||||||
static uint8 scanRspData[] = {
|
|
||||||
// complete name
|
|
||||||
16, // length of this section
|
|
||||||
GAP_ADTYPE_LOCAL_NAME_COMPLETE,
|
|
||||||
'L', 'E','D', ' ',
|
|
||||||
'B', 'a','d', 'g', 'e', ' ',
|
|
||||||
'M', 'a','g', 'i', 'c',
|
|
||||||
|
|
||||||
// connection interval range
|
|
||||||
0x05, // length of this section
|
|
||||||
GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE,
|
|
||||||
LO_UINT16(MIN_CONN_INTERVAL),
|
|
||||||
HI_UINT16(MIN_CONN_INTERVAL),
|
|
||||||
LO_UINT16(MAX_CONN_INTERVAL),
|
|
||||||
HI_UINT16(MAX_CONN_INTERVAL),
|
|
||||||
|
|
||||||
// Tx power level
|
|
||||||
0x02, // length of this data
|
|
||||||
GAP_ADTYPE_POWER_LEVEL,
|
|
||||||
9 // 9dBm
|
|
||||||
};
|
|
||||||
|
|
||||||
// GAP - Advertisement data (max size = 31 bytes)
|
// GAP - Advertisement data (max size = 31 bytes)
|
||||||
// keep short, save energy, save the planet
|
// keep short, save energy, save the planet
|
||||||
static uint8 advertData[] = {
|
static uint8 advertData[] = {
|
||||||
@@ -61,9 +39,6 @@ static uint8 advertData[] = {
|
|||||||
HI_UINT16(ADV_UUID)
|
HI_UINT16(ADV_UUID)
|
||||||
};
|
};
|
||||||
|
|
||||||
// GAP GATT Attributes
|
|
||||||
static uint8 devName[GAP_DEVICE_NAME_LEN] = "LED Badge Magic";
|
|
||||||
|
|
||||||
// Connection item list
|
// Connection item list
|
||||||
static peripheralConnItem_t conn_list;
|
static peripheralConnItem_t conn_list;
|
||||||
|
|
||||||
@@ -210,21 +185,58 @@ void ble_disable_advertise()
|
|||||||
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8), &e);
|
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8), &e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// len should not exceed 20 chars excluding null-terminate char. Otherwise it
|
||||||
|
// will be trimmed off and return -1
|
||||||
|
static int setup_scan_rsp(char *name, uint8_t len)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
// GAP - SCAN RSP data (max size = 31 bytes)
|
||||||
|
uint8_t scanRspData[31] = {
|
||||||
|
// connection interval range
|
||||||
|
0x05, // length of this section
|
||||||
|
GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE,
|
||||||
|
LO_UINT16(MIN_CONN_INTERVAL),
|
||||||
|
HI_UINT16(MIN_CONN_INTERVAL),
|
||||||
|
LO_UINT16(MAX_CONN_INTERVAL),
|
||||||
|
HI_UINT16(MAX_CONN_INTERVAL),
|
||||||
|
|
||||||
|
// Tx power level
|
||||||
|
0x02, // length of this data
|
||||||
|
GAP_ADTYPE_POWER_LEVEL,
|
||||||
|
9, // 9dBm
|
||||||
|
|
||||||
|
len + 1,
|
||||||
|
GAP_ADTYPE_LOCAL_NAME_COMPLETE,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (len < (31 - 11)) {
|
||||||
|
tmos_memcpy(&scanRspData[11], name, len);
|
||||||
|
ret = -1;
|
||||||
|
} else {
|
||||||
|
tmos_memcpy(&scanRspData[11], name, 20);
|
||||||
|
}
|
||||||
|
int total_len = 11 + len;
|
||||||
|
tmos_memset(&scanRspData[total_len], 0, 31 - total_len);
|
||||||
|
GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, total_len, scanRspData);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static void gap_init()
|
static void gap_init()
|
||||||
{
|
{
|
||||||
GAPRole_PeripheralInit();
|
GAPRole_PeripheralInit();
|
||||||
|
|
||||||
static uint16 desired_min_interval = 6;
|
uint16_t min_interval = 6;
|
||||||
static uint16 desired_max_interval = 500;
|
uint16_t max_interval = 500;
|
||||||
|
|
||||||
// Set the GAP Role Parameters
|
// Set the GAP Role Parameters
|
||||||
GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, sizeof(scanRspData), scanRspData);
|
setup_scan_rsp(badge_cfg.ble_devname, 20);
|
||||||
GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData);
|
GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData);
|
||||||
GAPRole_SetParameter(GAPROLE_MIN_CONN_INTERVAL, sizeof(uint16), &desired_min_interval);
|
GAPRole_SetParameter(GAPROLE_MIN_CONN_INTERVAL, sizeof(uint16), &min_interval);
|
||||||
GAPRole_SetParameter(GAPROLE_MAX_CONN_INTERVAL, sizeof(uint16), &desired_max_interval);
|
GAPRole_SetParameter(GAPROLE_MAX_CONN_INTERVAL, sizeof(uint16), &max_interval);
|
||||||
|
|
||||||
// Set the GAP Characteristics
|
// Set the GAP Characteristics
|
||||||
GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, devName);
|
GGS_SetParameter(GGS_DEVICE_NAME_ATT, 20,
|
||||||
|
badge_cfg.ble_devname);
|
||||||
GAP_SetParamValue(TGAP_DISC_ADV_INT_MIN, MIN_ADV_INTERVAL);
|
GAP_SetParamValue(TGAP_DISC_ADV_INT_MIN, MIN_ADV_INTERVAL);
|
||||||
GAP_SetParamValue(TGAP_DISC_ADV_INT_MAX, MAX_ADV_INTERVAL);
|
GAP_SetParamValue(TGAP_DISC_ADV_INT_MAX, MAX_ADV_INTERVAL);
|
||||||
|
|
||||||
|
|||||||
@@ -4,5 +4,8 @@
|
|||||||
int legacy_registerService();
|
int legacy_registerService();
|
||||||
int devInfo_registerService();
|
int devInfo_registerService();
|
||||||
int batt_registerService();
|
int batt_registerService();
|
||||||
|
int ng_registerService();
|
||||||
|
|
||||||
|
bStatus_t ng_notify(uint8_t *pValue, uint8_t len);
|
||||||
|
|
||||||
#endif /* __BLE_UART_SERVICE_H__ */
|
#endif /* __BLE_UART_SERVICE_H__ */
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#include "../../data.h"
|
#include "../../legacyctrl.h"
|
||||||
#include "../../power.h"
|
|
||||||
#include "../../leddrv.h"
|
|
||||||
|
|
||||||
static const uint16_t ServiceUUID = 0xFEE0;
|
static const uint16_t ServiceUUID = 0xFEE0;
|
||||||
static const gattAttrType_t service = {2, (uint8_t *)&ServiceUUID};
|
static const gattAttrType_t service = {2, (uint8_t *)&ServiceUUID};
|
||||||
@@ -18,39 +16,6 @@ static gattAttribute_t attr_table[] = {
|
|||||||
CHAR_VAL_DECLAR(&RxCharUUID, 2, GATT_PERMIT_WRITE, RxCharVal),
|
CHAR_VAL_DECLAR(&RxCharUUID, 2, GATT_PERMIT_WRITE, RxCharVal),
|
||||||
};
|
};
|
||||||
|
|
||||||
static bStatus_t receive(uint8_t *val, uint16_t len)
|
|
||||||
{
|
|
||||||
static uint16_t c, data_len, n;
|
|
||||||
static uint8_t *data;
|
|
||||||
if (len != LEGACY_TRANSFER_WIDTH) {
|
|
||||||
return ATT_ERR_INVALID_VALUE_SIZE;
|
|
||||||
}
|
|
||||||
if (c == 0) {
|
|
||||||
if (memcmp(val, "wang\0\0", 6)) {
|
|
||||||
return ATT_ERR_INVALID_VALUE;
|
|
||||||
} else {
|
|
||||||
data = malloc(sizeof(data_legacy_t));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(data + c * len, val, len);
|
|
||||||
|
|
||||||
if (c == 1) {
|
|
||||||
data_legacy_t *d = (data_legacy_t *)data;
|
|
||||||
n = bigendian16_sum(d->sizes, 8);
|
|
||||||
data_len = LEGACY_HEADER_SIZE + LED_ROWS * n;
|
|
||||||
data = realloc(data, data_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c > 2 && ((c+1) * LEGACY_TRANSFER_WIDTH) >= data_len) {
|
|
||||||
data_flatSave(data, data_len);
|
|
||||||
reset_jump();
|
|
||||||
}
|
|
||||||
|
|
||||||
c++;
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bStatus_t write_handler(uint16 connHandle, gattAttribute_t *pAttr,
|
static bStatus_t write_handler(uint16 connHandle, gattAttribute_t *pAttr,
|
||||||
uint8 *pValue, uint16 len, uint16 offset, uint8 method)
|
uint8 *pValue, uint16 len, uint16 offset, uint8 method)
|
||||||
{
|
{
|
||||||
@@ -60,7 +25,10 @@ static bStatus_t write_handler(uint16 connHandle, gattAttribute_t *pAttr,
|
|||||||
|
|
||||||
uint16_t uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
|
uint16_t uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
|
||||||
if(uuid == RxCharUUID) {
|
if(uuid == RxCharUUID) {
|
||||||
return receive(pValue, len);
|
if (legacy_ble_rx(pValue, len)) {
|
||||||
|
return ATT_ERR_UNLIKELY;
|
||||||
|
}
|
||||||
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
return ATT_ERR_ATTR_NOT_FOUND;
|
return ATT_ERR_ATTR_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|||||||
160
src/ble/profile/ng.c
Normal file
160
src/ble/profile/ng.c
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#include "CH583SFR.h"
|
||||||
|
|
||||||
|
#include "../../power.h"
|
||||||
|
#include "../../ngctrl.h"
|
||||||
|
#include "../../debug.h"
|
||||||
|
|
||||||
|
static const uint16_t ServiceUUID = 0xF055;
|
||||||
|
static const gattAttrType_t service = {2, (uint8_t *)&ServiceUUID};
|
||||||
|
|
||||||
|
static const uint16_t TxCharUUID = 0xF056;
|
||||||
|
static uint8_t TxCharProps = GATT_PROP_READ | GATT_PROP_NOTIFY;
|
||||||
|
static uint8_t TxCharVal[256];
|
||||||
|
static uint16_t TxLen;
|
||||||
|
|
||||||
|
static const uint16_t RxCharUUID = 0xF057;
|
||||||
|
static uint8_t RxCharProps = GATT_PROP_WRITE;
|
||||||
|
#define RxCharVal TxCharVal
|
||||||
|
static gattCharCfg_t TxCCCD[1];
|
||||||
|
|
||||||
|
static gattAttribute_t attr_table[] = {
|
||||||
|
ATTR_DECLAR(primaryServiceUUID, 2, GATT_PERMIT_READ, &service),
|
||||||
|
|
||||||
|
CHAR_DECLAR(&RxCharProps),
|
||||||
|
CHAR_VAL_DECLAR(&RxCharUUID, 2, GATT_PERMIT_WRITE, RxCharVal),
|
||||||
|
|
||||||
|
CHAR_DECLAR(&TxCharProps),
|
||||||
|
CHAR_VAL_DECLAR(&TxCharUUID, 2, GATT_PERMIT_READ, TxCharVal),
|
||||||
|
ATTR_DECLAR(clientCharCfgUUID, 2, GATT_PERMIT_READ | GATT_PERMIT_WRITE, TxCCCD),
|
||||||
|
};
|
||||||
|
|
||||||
|
#define notiAttr attr_table[4]
|
||||||
|
|
||||||
|
|
||||||
|
static bStatus_t write_handler(uint16 connHandle, gattAttribute_t *pAttr,
|
||||||
|
uint8 *pValue, uint16 len, uint16 offset, uint8 method)
|
||||||
|
{
|
||||||
|
PRINT("ble: write_handler(): connHandle: %04X\n", connHandle);
|
||||||
|
|
||||||
|
if (!gattPermitWrite(pAttr->permissions)) {
|
||||||
|
return ATT_ERR_WRITE_NOT_PERMITTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
|
||||||
|
if(uuid == GATT_CLIENT_CHAR_CFG_UUID) {
|
||||||
|
bStatus_t ret = GATTServApp_ProcessCCCWriteReq(connHandle, pAttr, pValue, len,
|
||||||
|
offset, GATT_CLIENT_CFG_NOTIFY);
|
||||||
|
PRINT("ble: CCCD changed: %02X\n", TxCCCD->value);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uuid == RxCharUUID) {
|
||||||
|
return ng_parse(pValue, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ATT_ERR_ATTR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bStatus_t read_handler(uint16_t connHandle, gattAttribute_t *pAttr,
|
||||||
|
uint8_t *pValue, uint16_t *pLen, uint16_t offset,
|
||||||
|
uint16_t maxLen, uint8_t method)
|
||||||
|
{
|
||||||
|
if (!gattPermitRead(pAttr->permissions)) {
|
||||||
|
return ATT_ERR_READ_NOT_PERMITTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
|
||||||
|
if(uuid == GATT_CLIENT_CHAR_CFG_UUID) {
|
||||||
|
*pLen = 2;
|
||||||
|
tmos_memcpy(pValue, pAttr->pValue, *pLen);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uuid == TxCharUUID) {
|
||||||
|
*pLen = MIN(TxLen-offset, maxLen);
|
||||||
|
tmos_memcpy(pValue, &pAttr->pValue[offset], *pLen);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ATT_ERR_ATTR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gattServiceCBs_t service_handlers = {
|
||||||
|
read_handler,
|
||||||
|
write_handler,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static void connStatus_handler(uint16 connHandle, uint8 changeType)
|
||||||
|
{
|
||||||
|
if(connHandle == LOOPBACK_CONNHANDLE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Reset ClientCharConfig if connection has dropped
|
||||||
|
if((changeType == LINKDB_STATUS_UPDATE_REMOVED)
|
||||||
|
|| ((changeType == LINKDB_STATUS_UPDATE_STATEFLAGS)
|
||||||
|
&& (!linkDB_Up(connHandle)))) {
|
||||||
|
GATTServApp_InitCharCfg(connHandle, TxCCCD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ng_registerService()
|
||||||
|
{
|
||||||
|
uint8 status = SUCCESS;
|
||||||
|
GATTServApp_InitCharCfg(INVALID_CONNHANDLE, TxCCCD);
|
||||||
|
linkDB_Register(connStatus_handler);
|
||||||
|
|
||||||
|
status = GATTServApp_RegisterService(attr_table,
|
||||||
|
GATT_NUM_ATTRS(attr_table),
|
||||||
|
GATT_MAX_ENCRYPT_KEY_SIZE,
|
||||||
|
&service_handlers);
|
||||||
|
return (status);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8 isNotifyEnabled(uint16 connHandle)
|
||||||
|
{
|
||||||
|
uint16_t val = GATTServApp_ReadCharCfg(connHandle, TxCCCD);
|
||||||
|
return val & GATT_CLIENT_CFG_NOTIFY;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @brief Send notify to client. Currently support one client connection
|
||||||
|
* only.
|
||||||
|
*
|
||||||
|
* @param val Value to be sent
|
||||||
|
* @param len length of val. This should not be larger than MTU.
|
||||||
|
* @return bStatus_t
|
||||||
|
*/
|
||||||
|
bStatus_t ng_notify(uint8_t *val, uint8_t len)
|
||||||
|
{
|
||||||
|
if(!isNotifyEnabled(TxCCCD->connHandle)) {
|
||||||
|
PRINT("ble: ng_notify() notify is not enabled\n");
|
||||||
|
return bleIncorrectMode;
|
||||||
|
}
|
||||||
|
if(len > ATT_GetMTU(TxCCCD->connHandle)) {
|
||||||
|
return bleInvalidRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
attHandleValueNoti_t noti = {
|
||||||
|
.handle = notiAttr.handle,
|
||||||
|
.len = len
|
||||||
|
};
|
||||||
|
noti.pValue = GATT_bm_alloc(TxCCCD->connHandle, ATT_HANDLE_VALUE_NOTI,
|
||||||
|
len, NULL, 0);
|
||||||
|
if (noti.pValue == NULL) {
|
||||||
|
return bleMemAllocError;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmos_memcpy(noti.pValue, val, len);
|
||||||
|
|
||||||
|
bStatus_t ret = GATT_Notification(TxCCCD->connHandle, ¬i, FALSE);
|
||||||
|
GATT_bm_free((gattMsg_t *)¬i, ATT_HANDLE_VALUE_NOTI);
|
||||||
|
if (ret != SUCCESS) {
|
||||||
|
PRINT("ble: noti sending failed\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRINT("ble: noti sent\n");
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
@@ -6,28 +6,39 @@
|
|||||||
#include "CH58x_common.h"
|
#include "CH58x_common.h"
|
||||||
|
|
||||||
#ifndef BLE_BUFF_LEN
|
#ifndef BLE_BUFF_LEN
|
||||||
#define BLE_BUFF_LEN 27
|
// MTU = 64 but clients should request new MTU, otherwise default will be 23
|
||||||
#endif
|
#define BLE_BUFF_LEN (64 + 4)
|
||||||
#ifndef BLE_BUFF_NUM
|
|
||||||
#define BLE_BUFF_NUM 5
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef BLE_TX_NUM_EVENT
|
#ifndef BLE_TX_NUM_EVENT
|
||||||
#define BLE_TX_NUM_EVENT 1
|
#define BLE_TX_NUM_EVENT 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef BLE_TX_POWER
|
#ifndef BLE_TX_POWER
|
||||||
#define BLE_TX_POWER LL_TX_POWEER_6_DBM
|
#define BLE_TX_POWER LL_TX_POWEER_6_DBM
|
||||||
|
// #define BLE_TX_POWER LL_TX_POWEER_MINUS_16_DBM
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef BLE_MEMHEAP_SIZE
|
#ifndef BLE_MEMHEAP_SIZE
|
||||||
#define BLE_MEMHEAP_SIZE (1024*6)
|
#define BLE_MEMHEAP_SIZE (1024 * 6)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CENTRAL_MAX_CONNECTION
|
#ifndef CENTRAL_MAX_CONNECTION
|
||||||
#define CENTRAL_MAX_CONNECTION 3
|
#define CENTRAL_MAX_CONNECTION 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef BLE_BUFF_NUM
|
||||||
|
// The BLE lib automatically stack up Write Long messages in Write handler.
|
||||||
|
// A connection will be disconnected if this number is some how not enough.
|
||||||
|
#define BLE_BUFF_NUM (512 / 23)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef PERIPHERAL_MAX_CONNECTION
|
#ifndef PERIPHERAL_MAX_CONNECTION
|
||||||
#define PERIPHERAL_MAX_CONNECTION 1
|
#define PERIPHERAL_MAX_CONNECTION 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static __attribute__((aligned(4))) uint32_t MEM_BUF[BLE_MEMHEAP_SIZE / 4];
|
static __attribute__((aligned(4), section(".noinit")))
|
||||||
|
uint32_t MEM_BUF[BLE_MEMHEAP_SIZE / 4];
|
||||||
|
|
||||||
static void lsi_calib(void)
|
static void lsi_calib(void)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ bm_t *bmlist_drop(bm_t *bm)
|
|||||||
head = bm->next;
|
head = bm->next;
|
||||||
if (bm == tail)
|
if (bm == tail)
|
||||||
tail = bm->prev;
|
tail = bm->prev;
|
||||||
|
free(bm);
|
||||||
return bm->next;
|
return bm->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
87
src/config.c
Normal file
87
src/config.c
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
/**
|
||||||
|
* TODO: needs constraints checking as some of the config fields may have
|
||||||
|
* invalid values which will make the badge broke.
|
||||||
|
*/
|
||||||
|
#include "config.h"
|
||||||
|
#include "resource.h"
|
||||||
|
#include "res/foss-asia-2.xbm"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "util/crc.h"
|
||||||
|
|
||||||
|
#include "ISP583.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define CFG_SIZE sizeof(badge_cfg_t)
|
||||||
|
#define CFG_DEF_FLASH_OFFS (EEPROM_MAX_SIZE - CFG_SIZE - 1) // Default offset
|
||||||
|
|
||||||
|
badge_cfg_t badge_cfg;
|
||||||
|
|
||||||
|
/* In case of first time firmware upgrading */
|
||||||
|
void cfg_fallback()
|
||||||
|
{
|
||||||
|
badge_cfg.ble_always_on = 1;
|
||||||
|
memcpy(badge_cfg.ble_devname, "LED Badge Magic\0\0\0\0", 20);
|
||||||
|
/* OEM app testing: */
|
||||||
|
// memcpy(badge_cfg.ble_devname, "LSLED\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20);
|
||||||
|
|
||||||
|
badge_cfg.led_brightness = 0;
|
||||||
|
badge_cfg.led_scan_freq = 2000;
|
||||||
|
|
||||||
|
badge_cfg.splash_speedT = 30; // ms
|
||||||
|
|
||||||
|
int splash_size = ALIGN_1BYTE(splash.w) * splash.h;
|
||||||
|
memcpy(badge_cfg.splash_bm_bits, splash.bits, splash_size);
|
||||||
|
badge_cfg.splash_bm_w = splash.w;
|
||||||
|
badge_cfg.splash_bm_h = splash.h;
|
||||||
|
badge_cfg.splash_bm_fh = splash.fh;
|
||||||
|
|
||||||
|
badge_cfg.reset_rx = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cfg_update_crc(badge_cfg_t *cfg)
|
||||||
|
{
|
||||||
|
cfg->crc = crc_cal((uint8_t *)cfg, CFG_SIZE - 1);
|
||||||
|
PRINT(__func__);
|
||||||
|
PRINT(": crc: %02X\n", cfg->crc);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cfg_writeflash(uint16_t flash_offs, badge_cfg_t *cfg)
|
||||||
|
{
|
||||||
|
if (flash_offs + CFG_SIZE > EEPROM_MAX_SIZE) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
cfg_update_crc(&badge_cfg);
|
||||||
|
return EEPROM_WRITE(flash_offs, cfg, CFG_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cfg_readflash(uint16_t flash_offs, badge_cfg_t *cfg)
|
||||||
|
{
|
||||||
|
int ret = EEPROM_READ(flash_offs, cfg, CFG_SIZE);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return crc_cal((uint8_t *)cfg, CFG_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cfg_readflash_def(badge_cfg_t *cfg)
|
||||||
|
{
|
||||||
|
return cfg_readflash(CFG_DEF_FLASH_OFFS, cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cfg_writeflash_def(badge_cfg_t *cfg)
|
||||||
|
{
|
||||||
|
return cfg_writeflash(CFG_DEF_FLASH_OFFS, cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cfg_init()
|
||||||
|
{
|
||||||
|
badge_cfg_t cfg;
|
||||||
|
int r = cfg_readflash_def(&cfg);
|
||||||
|
if (r) {
|
||||||
|
cfg_fallback();
|
||||||
|
PRINT("configuration falling back: %02x\n", r);
|
||||||
|
} else {
|
||||||
|
memcpy(&badge_cfg, &cfg, CFG_SIZE);
|
||||||
|
PRINT("configuration read from flash successfully\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
42
src/config.h
Normal file
42
src/config.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
#ifndef __CONFIG_H__
|
||||||
|
#define __CONFIG_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "xbm.h"
|
||||||
|
#include "leddrv.h"
|
||||||
|
|
||||||
|
#define SPLASH_MAX_WIDTH (48) // pixels
|
||||||
|
#define SPLASH_MAX_HEIGHT (44) // pixels
|
||||||
|
#define SPLASH_MAX_SIZE (ALIGN_1BYTE(SPLASH_MAX_WIDTH) * SPLASH_MAX_HEIGHT)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
// Turn on Bluetooth while in Normal mode and disable Downloads mode
|
||||||
|
uint8_t ble_always_on;
|
||||||
|
char ble_devname[20];
|
||||||
|
|
||||||
|
uint8_t led_brightness;
|
||||||
|
uint16_t led_scan_freq; // Scan frequency
|
||||||
|
|
||||||
|
uint8_t splash_bm_bits[SPLASH_MAX_SIZE]; // Up to 48x44 (Width x Height)
|
||||||
|
uint8_t splash_bm_w;
|
||||||
|
uint8_t splash_bm_h;
|
||||||
|
uint8_t splash_bm_fh;
|
||||||
|
|
||||||
|
// Speed in period of micro second. The lower value, the higher speed
|
||||||
|
uint16_t splash_speedT;
|
||||||
|
uint8_t reset_rx; // Reset after bitmap received
|
||||||
|
|
||||||
|
uint8_t crc;
|
||||||
|
} __attribute__((packed)) badge_cfg_t;
|
||||||
|
|
||||||
|
extern badge_cfg_t badge_cfg;
|
||||||
|
|
||||||
|
void cfg_init();
|
||||||
|
int cfg_writeflash(uint16_t flash_offs, badge_cfg_t *cfg);
|
||||||
|
int cfg_readflash(uint16_t flash_offs, badge_cfg_t *cfg);
|
||||||
|
int cfg_writeflash_def(badge_cfg_t *cfg);
|
||||||
|
int cfg_readflash_def(badge_cfg_t *cfg);
|
||||||
|
void cfg_fallback();
|
||||||
|
|
||||||
|
#endif /* __CONFIG_H__ */
|
||||||
32
src/data.c
32
src/data.c
@@ -24,34 +24,25 @@ uint32_t data_flatSave(uint8_t *data, uint32_t len)
|
|||||||
return EEPROM_WRITE(0, data, len);
|
return EEPROM_WRITE(0, data, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
data_legacy_t *data_get_header(int read_anyway)
|
void data_get_header(data_legacy_t *buf)
|
||||||
{
|
{
|
||||||
static data_legacy_t *cache;
|
EEPROM_READ(0, buf, LEGACY_HEADER_SIZE);
|
||||||
|
|
||||||
if (cache == NULL) {
|
|
||||||
cache = malloc(sizeof(data_legacy_t));
|
|
||||||
read_anyway = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (read_anyway) {
|
|
||||||
EEPROM_READ(0, cache, LEGACY_HEADER_SIZE);
|
|
||||||
}
|
|
||||||
return cache;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t data_flash2newmem(uint8_t **chunk, uint32_t n)
|
uint16_t data_flash2newmem(uint8_t **chunk, uint32_t n)
|
||||||
{
|
{
|
||||||
data_legacy_t *header = data_get_header(0);
|
data_legacy_t header;
|
||||||
|
data_get_header(&header);
|
||||||
|
|
||||||
if (memcmp(header->header, "wang", 5))
|
if (memcmp(header.header, "wang", 5))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
uint16_t size = bswap16(header->sizes[n]) * LED_ROWS;
|
uint16_t size = bswap16(header.sizes[n]) * LED_ROWS;
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
uint16_t offs = LEGACY_HEADER_SIZE
|
uint16_t offs = LEGACY_HEADER_SIZE
|
||||||
+ bigendian16_sum(header->sizes, n) * LED_ROWS;
|
+ bigendian16_sum(header.sizes, n) * LED_ROWS;
|
||||||
|
|
||||||
*chunk = malloc(size);
|
*chunk = malloc(size);
|
||||||
EEPROM_READ(offs, *chunk, size);
|
EEPROM_READ(offs, *chunk, size);
|
||||||
@@ -98,11 +89,12 @@ bm_t *flash2newbm(uint32_t n)
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
bm_t *bm = chunk2newbm(buf, size);
|
bm_t *bm = chunk2newbm(buf, size);
|
||||||
data_legacy_t *header = data_get_header(0);
|
data_legacy_t header;
|
||||||
|
data_get_header(&header);
|
||||||
|
|
||||||
bm->is_flash = (header->flash & (1 << n)) != 0;
|
bm->is_flash = (header.flash & (1 << n)) != 0;
|
||||||
bm->is_marquee = (header->marquee & (1 << n)) != 0;
|
bm->is_marquee = (header.marquee & (1 << n)) != 0;
|
||||||
bm->modes = header->modes[n];
|
bm->modes = header.modes[n];
|
||||||
|
|
||||||
free(buf);
|
free(buf);
|
||||||
return bm;
|
return bm;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ typedef struct {
|
|||||||
uint8_t separator[16];
|
uint8_t separator[16];
|
||||||
|
|
||||||
uint8_t *bitmapdata;
|
uint8_t *bitmapdata;
|
||||||
} data_legacy_t;
|
} __attribute__((packed)) data_legacy_t;
|
||||||
|
|
||||||
#define LEGACY_TRANSFER_WIDTH (16)
|
#define LEGACY_TRANSFER_WIDTH (16)
|
||||||
#define LEGACY_HEADER_SIZE (sizeof(data_legacy_t) - sizeof(uint8_t *))
|
#define LEGACY_HEADER_SIZE (sizeof(data_legacy_t) - sizeof(uint8_t *))
|
||||||
@@ -47,7 +47,7 @@ uint32_t bigendian16_sum(uint16_t *s, int len);
|
|||||||
uint32_t data_flatSave(uint8_t *data, uint32_t len);
|
uint32_t data_flatSave(uint8_t *data, uint32_t len);
|
||||||
uint16_t data_flash2newmem(uint8_t **chunk, uint32_t n);
|
uint16_t data_flash2newmem(uint8_t **chunk, uint32_t n);
|
||||||
|
|
||||||
data_legacy_t *data_get_header(int read_anyway);
|
void data_get_header(data_legacy_t *buf);
|
||||||
|
|
||||||
void chunk2buffer(uint8_t *chunk, uint16_t size, uint16_t *buf);
|
void chunk2buffer(uint8_t *chunk, uint16_t size, uint16_t *buf);
|
||||||
void chunk2bm(uint8_t *chunk, uint16_t size, bm_t *bm);
|
void chunk2bm(uint8_t *chunk, uint16_t size, bm_t *bm);
|
||||||
|
|||||||
35
src/debug.c
Normal file
35
src/debug.c
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#include "debug.h"
|
||||||
|
#include "CH583SFR.h"
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
|
||||||
|
#define Debug_UART0 0
|
||||||
|
#define Debug_UART1 1
|
||||||
|
#define Debug_UART2 2
|
||||||
|
#define Debug_UART3 3
|
||||||
|
|
||||||
|
int _write(int fd, char *buf, int size)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
#if DEBUG == Debug_UART0
|
||||||
|
while(R8_UART0_TFC == UART_FIFO_SIZE);
|
||||||
|
R8_UART0_THR = *buf++;
|
||||||
|
#elif DEBUG == Debug_UART1
|
||||||
|
while(R8_UART1_TFC == UART_FIFO_SIZE);
|
||||||
|
R8_UART1_THR = *buf++;
|
||||||
|
#elif DEBUG == Debug_UART2
|
||||||
|
while(R8_UART2_TFC == UART_FIFO_SIZE);
|
||||||
|
R8_UART2_THR = *buf++;
|
||||||
|
#elif DEBUG == Debug_UART3
|
||||||
|
while(R8_UART3_TFC == UART_FIFO_SIZE);
|
||||||
|
R8_UART3_THR = *buf++;
|
||||||
|
#else
|
||||||
|
#error "Please specify a debug port for uart"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
15
src/debug.h
Normal file
15
src/debug.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#ifndef __DEBUG_H__
|
||||||
|
#define __DEBUG_H__
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define PRINT(X...) printf(X)
|
||||||
|
#else
|
||||||
|
#define PRINT(X...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define _TRACE() PRINT("> "); PRINT(__FILE__); PRINT(": "); PRINT(__func__); \
|
||||||
|
PRINT("()\n")
|
||||||
|
|
||||||
|
#endif /* __DEBUG_H__ */
|
||||||
110
src/legacyctrl.c
Normal file
110
src/legacyctrl.c
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
#include "data.h"
|
||||||
|
#include "power.h"
|
||||||
|
#include "leddrv.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "legacyctrl.h"
|
||||||
|
|
||||||
|
int legacy_ble_rx(uint8_t *val, uint16_t len)
|
||||||
|
{
|
||||||
|
_TRACE();
|
||||||
|
static uint16_t c, data_len, n;
|
||||||
|
static uint8_t *data;
|
||||||
|
|
||||||
|
if (len != LEGACY_TRANSFER_WIDTH) {
|
||||||
|
PRINT("Transfer width is not matched\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRINT("val[%d]: ", len);
|
||||||
|
for (int i=0; i<len; i++) {
|
||||||
|
PRINT("%02X ", val[i]);
|
||||||
|
}
|
||||||
|
PRINT("\n");
|
||||||
|
|
||||||
|
if (c == 0) {
|
||||||
|
if (memcmp(val, "wang", 5)) {
|
||||||
|
PRINT("Not a header\n");
|
||||||
|
return -2;
|
||||||
|
} else {
|
||||||
|
free(data);
|
||||||
|
data = malloc(sizeof(data_legacy_t));
|
||||||
|
if (!data) {
|
||||||
|
PRINT("insufficient memory\n");
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { // Re attempt after a failed transfer
|
||||||
|
if (!memcmp(val, "wang", 5)) {
|
||||||
|
free(data);
|
||||||
|
c = 0;
|
||||||
|
data = malloc(sizeof(data_legacy_t));
|
||||||
|
if (!data) {
|
||||||
|
PRINT("insufficient memory\n");
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PRINT("Copying BLE value\n");
|
||||||
|
memcpy(data + c * len, val, len);
|
||||||
|
|
||||||
|
if (c == 1) {
|
||||||
|
data_legacy_t *d = (data_legacy_t *)data;
|
||||||
|
n = bigendian16_sum(d->sizes, 8);
|
||||||
|
data_len = LEGACY_HEADER_SIZE + LED_ROWS * n;
|
||||||
|
PRINT("Data len: %d\n", data_len);
|
||||||
|
data = realloc(data, data_len);
|
||||||
|
if (!data) {
|
||||||
|
PRINT("insufficient memory\n");
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c > 2 && ((c+1) * LEGACY_TRANSFER_WIDTH) >= data_len) {
|
||||||
|
PRINT("All bitmaps data received successfully\nWriting to flash.. ");
|
||||||
|
data_flatSave(data, data_len);
|
||||||
|
free(data);
|
||||||
|
data = NULL;
|
||||||
|
handle_after_rx();
|
||||||
|
PRINT("Done\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
c++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int legacy_usb_rx(uint8_t *buf, uint16_t len)
|
||||||
|
{
|
||||||
|
static uint16_t rx_len, data_len;
|
||||||
|
static uint8_t *data;
|
||||||
|
|
||||||
|
PRINT("dump first 8 bytes: %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||||
|
buf[0], buf[1], buf[2], buf[3],
|
||||||
|
buf[4], buf[5], buf[6], buf[7]);
|
||||||
|
|
||||||
|
if (rx_len == 0) {
|
||||||
|
if (memcmp(buf, "wang", 5))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
int init_len = len > LEGACY_HEADER_SIZE ? len : sizeof(data_legacy_t);
|
||||||
|
init_len += MAX_PACKET_SIZE;
|
||||||
|
data = malloc(init_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(data + rx_len, buf, len);
|
||||||
|
rx_len += len;
|
||||||
|
|
||||||
|
if (!data_len) {
|
||||||
|
data_legacy_t *d = (data_legacy_t *)data;
|
||||||
|
uint16_t n = bigendian16_sum(d->sizes, 8);
|
||||||
|
data_len = LEGACY_HEADER_SIZE + LED_ROWS * n;
|
||||||
|
data = realloc(data, data_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rx_len > LEGACY_HEADER_SIZE) && rx_len >= data_len) {
|
||||||
|
data_flatSave(data, data_len);
|
||||||
|
free(data);
|
||||||
|
handle_after_rx();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
10
src/legacyctrl.h
Normal file
10
src/legacyctrl.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#ifndef __LEGACYCTRL_H__
|
||||||
|
#define __LEGACYCTRL_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void handle_after_rx();
|
||||||
|
int legacy_ble_rx(uint8_t *val, uint16_t len);
|
||||||
|
int legacy_usb_rx(uint8_t *buf, uint16_t len);
|
||||||
|
|
||||||
|
#endif /* __LEGACYCTRL_H__ */
|
||||||
207
src/main.c
207
src/main.c
@@ -11,14 +11,14 @@
|
|||||||
|
|
||||||
#include "power.h"
|
#include "power.h"
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
#include "ble/setup.h"
|
#include "ble/setup.h"
|
||||||
#include "ble/profile.h"
|
#include "ble/profile.h"
|
||||||
|
|
||||||
#include "usb/usb.h"
|
#include "usb/usb.h"
|
||||||
|
#include "legacyctrl.h"
|
||||||
#define SCAN_F (2000)
|
|
||||||
#define SCAN_T (FREQ_SYS / SCAN_F)
|
|
||||||
|
|
||||||
#define NEXT_STATE(v, min, max) \
|
#define NEXT_STATE(v, min, max) \
|
||||||
(v)++; \
|
(v)++; \
|
||||||
@@ -60,10 +60,22 @@ static void change_brightness()
|
|||||||
NEXT_STATE(brightness, 0, BRIGHTNESS_LEVELS);
|
NEXT_STATE(brightness, 0, BRIGHTNESS_LEVELS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mode_setup_download();
|
||||||
|
static void mode_setup_normal();
|
||||||
|
|
||||||
__HIGH_CODE
|
__HIGH_CODE
|
||||||
static void change_mode()
|
static void change_mode()
|
||||||
{
|
{
|
||||||
NEXT_STATE(mode, 0, MODES_COUNT);
|
NEXT_STATE(mode, 0, MODES_COUNT);
|
||||||
|
const static void (*modes[])(void) = {
|
||||||
|
NULL,
|
||||||
|
mode_setup_normal,
|
||||||
|
mode_setup_download,
|
||||||
|
poweroff
|
||||||
|
};
|
||||||
|
|
||||||
|
if (modes[mode])
|
||||||
|
modes[mode]();
|
||||||
}
|
}
|
||||||
|
|
||||||
__HIGH_CODE
|
__HIGH_CODE
|
||||||
@@ -81,17 +93,19 @@ static void bm_transition()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void play_splash(xbm_t *xbm, int col, int row)
|
void play_splash(xbm_t *xbm, int col, int row, int spT)
|
||||||
{
|
{
|
||||||
while (ani_xbm_scrollup_pad(xbm, 11, 11, 11, fb, 0, 0) != 0) {
|
while (ani_xbm_scrollup_pad(xbm, 11, 11, 11, fb, 0, 0) != 0) {
|
||||||
DelayMs(30);
|
DelayMs(spT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_bmlist()
|
void load_bmlist()
|
||||||
{
|
{
|
||||||
if (data_get_header(0) == 0) // There is no bitmap stored in flash
|
data_legacy_t header;
|
||||||
return; // skip
|
data_get_header(&header);
|
||||||
|
if (memcmp(header.header, "wang", 5))
|
||||||
|
return; // There is no bitmap stored in flash
|
||||||
|
|
||||||
bm_t *curr_bm = bmlist_current();
|
bm_t *curr_bm = bmlist_current();
|
||||||
|
|
||||||
@@ -205,48 +219,18 @@ void ble_setup()
|
|||||||
tmos_clockInit();
|
tmos_clockInit();
|
||||||
|
|
||||||
peripheral_init();
|
peripheral_init();
|
||||||
ble_disable_advertise();
|
|
||||||
|
if (! badge_cfg.ble_always_on) {
|
||||||
|
ble_disable_advertise();
|
||||||
|
}
|
||||||
|
|
||||||
devInfo_registerService();
|
devInfo_registerService();
|
||||||
legacy_registerService();
|
legacy_registerService();
|
||||||
batt_registerService();
|
batt_registerService();
|
||||||
|
ng_registerService();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usb_receive(uint8_t *buf, uint16_t len)
|
static void spawn_tasks()
|
||||||
{
|
|
||||||
static uint16_t rx_len, data_len;
|
|
||||||
static uint8_t *data;
|
|
||||||
|
|
||||||
PRINT("dump first 8 bytes: %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
|
||||||
buf[0], buf[1], buf[2], buf[3],
|
|
||||||
buf[4], buf[5], buf[6], buf[7]);
|
|
||||||
|
|
||||||
if (rx_len == 0) {
|
|
||||||
if (memcmp(buf, "wang", 5))
|
|
||||||
return;
|
|
||||||
|
|
||||||
int init_len = len > LEGACY_HEADER_SIZE ? len : sizeof(data_legacy_t);
|
|
||||||
init_len += MAX_PACKET_SIZE;
|
|
||||||
data = malloc(init_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(data + rx_len, buf, len);
|
|
||||||
rx_len += len;
|
|
||||||
|
|
||||||
if (!data_len) {
|
|
||||||
data_legacy_t *d = (data_legacy_t *)data;
|
|
||||||
uint16_t n = bigendian16_sum(d->sizes, 8);
|
|
||||||
data_len = LEGACY_HEADER_SIZE + LED_ROWS * n;
|
|
||||||
data = realloc(data, data_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((rx_len > LEGACY_HEADER_SIZE) && rx_len >= data_len) {
|
|
||||||
data_flatSave(data, data_len);
|
|
||||||
SYS_ResetExecute();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void spawn_tasks()
|
|
||||||
{
|
{
|
||||||
common_taskid = TMOS_ProcessEventRegister(common_tasks);
|
common_taskid = TMOS_ProcessEventRegister(common_tasks);
|
||||||
|
|
||||||
@@ -257,10 +241,8 @@ void spawn_tasks()
|
|||||||
tmos_start_task(common_taskid, ANI_NEXT_STEP, 500000 / 625);
|
tmos_start_task(common_taskid, ANI_NEXT_STEP, 500000 / 625);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ble_start()
|
static void start_ble_animation()
|
||||||
{
|
{
|
||||||
ble_enable_advertise();
|
|
||||||
|
|
||||||
tmos_stop_task(common_taskid, ANI_NEXT_STEP);
|
tmos_stop_task(common_taskid, ANI_NEXT_STEP);
|
||||||
tmos_stop_task(common_taskid, ANI_MARQUE);
|
tmos_stop_task(common_taskid, ANI_MARQUE);
|
||||||
tmos_stop_task(common_taskid, ANI_FLASH);
|
tmos_stop_task(common_taskid, ANI_FLASH);
|
||||||
@@ -269,35 +251,54 @@ void ble_start()
|
|||||||
tmos_start_reload_task(common_taskid, BLE_NEXT_STEP, 500000 / 625);
|
tmos_start_reload_task(common_taskid, BLE_NEXT_STEP, 500000 / 625);
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_mode_transition()
|
static void start_normal_animation()
|
||||||
{
|
{
|
||||||
static int prev_mode;
|
tmos_start_reload_task(common_taskid, ANI_MARQUE, ANI_MARQUE_SPEED_T / 625);
|
||||||
if (prev_mode == mode) return;
|
tmos_start_reload_task(common_taskid, ANI_FLASH, ANI_FLASH_SPEED_T / 625);
|
||||||
|
tmos_start_task(common_taskid, ANI_NEXT_STEP, 500000 / 625);
|
||||||
|
tmos_stop_task(common_taskid, BLE_NEXT_STEP);
|
||||||
|
}
|
||||||
|
|
||||||
switch (mode)
|
static void resume_from_streaming()
|
||||||
{
|
{
|
||||||
case DOWNLOAD:
|
if (badge_cfg.ble_always_on) {
|
||||||
// Disable bitmap transition while in download mode
|
start_normal_animation();
|
||||||
btn_onOnePress(KEY2, NULL);
|
} else {
|
||||||
|
start_ble_animation();
|
||||||
// Take control of the current bitmap to display
|
|
||||||
// the Bluetooth animation
|
|
||||||
ble_start();
|
|
||||||
while (mode == DOWNLOAD) {
|
|
||||||
TMOS_SystemProcess();
|
|
||||||
}
|
|
||||||
// If not being flashed, pressing KEY1 again will
|
|
||||||
// make the badge goes off:
|
|
||||||
|
|
||||||
// fallthrough
|
|
||||||
case POWER_OFF:
|
|
||||||
poweroff();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
prev_mode = mode;
|
}
|
||||||
|
|
||||||
|
static void stop_all_animation()
|
||||||
|
{
|
||||||
|
tmos_stop_task(common_taskid, ANI_NEXT_STEP);
|
||||||
|
tmos_stop_task(common_taskid, ANI_MARQUE);
|
||||||
|
tmos_stop_task(common_taskid, ANI_FLASH);
|
||||||
|
tmos_stop_task(common_taskid, BLE_NEXT_STEP);
|
||||||
|
memset(fb, 0, sizeof(fb));
|
||||||
|
}
|
||||||
|
|
||||||
|
int streaming_enabled;
|
||||||
|
|
||||||
|
uint8_t streaming_setting(uint8_t *params, uint16_t len)
|
||||||
|
{
|
||||||
|
if (params[0] == 0x00) { // enter streaming mode
|
||||||
|
stop_all_animation();
|
||||||
|
streaming_enabled = 1;
|
||||||
|
} else if (params[0] == 0x01) { // return to normal mode
|
||||||
|
resume_from_streaming();
|
||||||
|
streaming_enabled = 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t stream_bitmap(uint8_t *params, uint16_t len)
|
||||||
|
{
|
||||||
|
if (! streaming_enabled) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmos_memcpy(fb, params, min(LED_COLS, len));
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void debug_init()
|
static void debug_init()
|
||||||
@@ -363,6 +364,51 @@ static void disp_charging()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mode_setup_download()
|
||||||
|
{
|
||||||
|
// If always-on BLE is enabled, then skip this mode, jump to next mode
|
||||||
|
if (badge_cfg.ble_always_on) {
|
||||||
|
change_mode();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable bitmap transition while in download mode
|
||||||
|
btn_onOnePress(KEY2, NULL);
|
||||||
|
|
||||||
|
// Take control of the current bitmap to display
|
||||||
|
// the Bluetooth animation
|
||||||
|
ble_enable_advertise();
|
||||||
|
start_ble_animation();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clean_bmlist()
|
||||||
|
{
|
||||||
|
bm_t *curr_bm = bmlist_current();
|
||||||
|
while (curr_bm->next != curr_bm)
|
||||||
|
bmlist_drop(curr_bm->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reload_bmlist()
|
||||||
|
{
|
||||||
|
clean_bmlist();
|
||||||
|
load_bmlist();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mode_setup_normal()
|
||||||
|
{
|
||||||
|
btn_onOnePress(KEY2, bm_transition);
|
||||||
|
reload_bmlist();
|
||||||
|
start_normal_animation();
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_after_rx()
|
||||||
|
{
|
||||||
|
if (badge_cfg.reset_rx) {
|
||||||
|
SYS_ResetExecute();
|
||||||
|
} else {
|
||||||
|
mode_setup_normal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
SetSysClock(CLK_SOURCE_PLL_60MHz);
|
SetSysClock(CLK_SOURCE_PLL_60MHz);
|
||||||
@@ -370,12 +416,12 @@ int main()
|
|||||||
debug_init();
|
debug_init();
|
||||||
PRINT("\nDebug console is on UART%d\n", DEBUG);
|
PRINT("\nDebug console is on UART%d\n", DEBUG);
|
||||||
|
|
||||||
cdc_onWrite(usb_receive);
|
cdc_onWrite(legacy_usb_rx);
|
||||||
hiddev_onWrite(usb_receive);
|
hiddev_onWrite(legacy_usb_rx);
|
||||||
usb_start();
|
usb_start();
|
||||||
|
|
||||||
led_init();
|
led_init();
|
||||||
TMR0_TimerInit(SCAN_T / 4);
|
TMR0_TimerInit((FREQ_SYS / 2000) / 2);
|
||||||
TMR0_ITCfg(ENABLE, TMR0_3_IT_CYC_END);
|
TMR0_ITCfg(ENABLE, TMR0_3_IT_CYC_END);
|
||||||
PFIC_EnableIRQ(TMR0_IRQn);
|
PFIC_EnableIRQ(TMR0_IRQn);
|
||||||
|
|
||||||
@@ -388,8 +434,14 @@ int main()
|
|||||||
|
|
||||||
power_init();
|
power_init();
|
||||||
disp_charging();
|
disp_charging();
|
||||||
|
cfg_init();
|
||||||
play_splash(&splash, 0, 0);
|
xbm_t spl = {
|
||||||
|
.bits = &(badge_cfg.splash_bm_bits),
|
||||||
|
.w = badge_cfg.splash_bm_w,
|
||||||
|
.h = badge_cfg.splash_bm_h,
|
||||||
|
.fh = badge_cfg.splash_bm_fh,
|
||||||
|
};
|
||||||
|
play_splash(&spl, 0, 0, badge_cfg.splash_speedT);
|
||||||
|
|
||||||
load_bmlist();
|
load_bmlist();
|
||||||
|
|
||||||
@@ -399,7 +451,6 @@ int main()
|
|||||||
|
|
||||||
mode = NORMAL;
|
mode = NORMAL;
|
||||||
while (1) {
|
while (1) {
|
||||||
handle_mode_transition();
|
|
||||||
TMOS_SystemProcess();
|
TMOS_SystemProcess();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
161
src/ngctrl.c
Normal file
161
src/ngctrl.c
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
#include "ngctrl.h"
|
||||||
|
|
||||||
|
#include "CH58xBLE_LIB.h"
|
||||||
|
#include "CH583SFR.h"
|
||||||
|
|
||||||
|
#include "ble/profile.h"
|
||||||
|
#include "power.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
// TODO: Some of configs can be added, just listing:
|
||||||
|
// - Remote brighness adjusting
|
||||||
|
// - Upload bitmap to ram
|
||||||
|
|
||||||
|
uint8_t next_packet(uint8_t *val, uint16_t len)
|
||||||
|
{
|
||||||
|
PRINT(__func__);
|
||||||
|
PRINT(": to be implemented\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cfg_reset_rx(uint8_t *state, uint16_t len)
|
||||||
|
{
|
||||||
|
badge_cfg.reset_rx = !!state[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void __poweroff(uint8_t *val, uint16_t len)
|
||||||
|
{
|
||||||
|
poweroff();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void __reset(uint8_t *val, uint16_t len)
|
||||||
|
{
|
||||||
|
SYS_ResetExecute();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Power off, reset after bitmap received.
|
||||||
|
uint8_t power_setting(uint8_t *val, uint16_t len)
|
||||||
|
{
|
||||||
|
PRINT(__func__);
|
||||||
|
PRINT("\n");
|
||||||
|
|
||||||
|
const void (*ble_lut[])(uint8_t *, uint16_t) = {
|
||||||
|
__poweroff,
|
||||||
|
cfg_reset_rx,
|
||||||
|
__reset,
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t fn = val[0];
|
||||||
|
if (fn >= (sizeof(ble_lut) / sizeof(ble_lut[0])))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ble_lut[fn](&val[1], len - 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cfg_ble_devname(uint8_t *name, uint16_t len)
|
||||||
|
{
|
||||||
|
tmos_memcpy(badge_cfg.ble_devname, name, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cfg_ble_alwayon(uint8_t *val, uint16_t len)
|
||||||
|
{
|
||||||
|
badge_cfg.ble_always_on = val[0] != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* always-on, adv name
|
||||||
|
Screen off/on can be archived by entering/leaving streaming mode
|
||||||
|
*/
|
||||||
|
uint8_t ble_setting(uint8_t *val, uint16_t len)
|
||||||
|
{
|
||||||
|
PRINT(__func__);
|
||||||
|
PRINT("\n");
|
||||||
|
|
||||||
|
const void (*ble_lut[])(uint8_t *, uint16_t) = {
|
||||||
|
cfg_ble_alwayon,
|
||||||
|
cfg_ble_devname
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t fn = val[0];
|
||||||
|
if (fn >= (sizeof(ble_lut) / sizeof(ble_lut[0])))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ble_lut[fn](&val[1], len - 1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t flash_splash_screen(uint8_t *val, uint16_t len)
|
||||||
|
{
|
||||||
|
PRINT(__func__);
|
||||||
|
PRINT("\n");
|
||||||
|
|
||||||
|
uint8_t w = val[0];
|
||||||
|
uint8_t h = val[1];
|
||||||
|
uint8_t fh = val[2];
|
||||||
|
uint8_t sz = len - 3;
|
||||||
|
|
||||||
|
if (w > SPLASH_MAX_WIDTH)
|
||||||
|
return -1;
|
||||||
|
if (h > SPLASH_MAX_HEIGHT)
|
||||||
|
return -2;
|
||||||
|
if (sz > SPLASH_MAX_SIZE)
|
||||||
|
return -3;
|
||||||
|
if (len < 3)
|
||||||
|
return -4;
|
||||||
|
|
||||||
|
tmos_memcpy(badge_cfg.splash_bm_bits, &val[3], sz);
|
||||||
|
badge_cfg.splash_bm_w = w;
|
||||||
|
badge_cfg.splash_bm_h = h;
|
||||||
|
badge_cfg.splash_bm_fh = fh;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t save_cfg(uint8_t *val, uint16_t len)
|
||||||
|
{
|
||||||
|
PRINT(__func__);
|
||||||
|
PRINT("\n");
|
||||||
|
return (uint8_t)cfg_writeflash_def(&badge_cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t load_fallback_cfg(uint8_t *val, uint16_t len)
|
||||||
|
{
|
||||||
|
PRINT(__func__);
|
||||||
|
PRINT("\n");
|
||||||
|
cfg_fallback(&badge_cfg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* TODO: add a way to read configs */
|
||||||
|
const uint8_t (*cmd_lut[])(uint8_t *val, uint16_t len) = {
|
||||||
|
next_packet, // Unsure if we need this
|
||||||
|
power_setting,
|
||||||
|
streaming_setting,
|
||||||
|
stream_bitmap,
|
||||||
|
ble_setting,
|
||||||
|
flash_splash_screen,
|
||||||
|
save_cfg,
|
||||||
|
load_fallback_cfg,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CMD_LUT_LEN (sizeof(cmd_lut) / sizeof(cmd_lut[0]))
|
||||||
|
|
||||||
|
uint8_t ng_parse(uint8_t *val, uint16_t len)
|
||||||
|
{
|
||||||
|
uint8_t cmd = val[0];
|
||||||
|
PRINT("LUT_LEN: %02x \n", CMD_LUT_LEN);
|
||||||
|
if (cmd >= CMD_LUT_LEN) {
|
||||||
|
PRINT("invalid command!\n");
|
||||||
|
return bleInvalidRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd_lut[cmd]) {
|
||||||
|
PRINT("executing [cmd %02x] \n", cmd);
|
||||||
|
uint8_t ret = (*cmd_lut[cmd])(val + 1, len - 1);
|
||||||
|
ng_notify(&ret, 1); // response to the client app
|
||||||
|
} else {
|
||||||
|
PRINT("function is not defined!\n");
|
||||||
|
}
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
20
src/ngctrl.h
Normal file
20
src/ngctrl.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#ifndef __NG_CTRL_H__
|
||||||
|
#define __NG_CTRL_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// enum NG_STATUS {
|
||||||
|
|
||||||
|
// };
|
||||||
|
|
||||||
|
uint8_t next_packet(uint8_t *val, uint16_t len);
|
||||||
|
uint8_t power_setting(uint8_t *val, uint16_t len);
|
||||||
|
uint8_t ble_setting(uint8_t *val, uint16_t len);
|
||||||
|
uint8_t streaming_setting(uint8_t *val, uint16_t len);
|
||||||
|
uint8_t stream_bitmap(uint8_t *val, uint16_t len);
|
||||||
|
uint8_t flash_splash_screen(uint8_t *val, uint16_t len);
|
||||||
|
|
||||||
|
extern const uint8_t (*cmd_lut[])(uint8_t *val, uint16_t len);
|
||||||
|
uint8_t ng_parse(uint8_t *val, uint16_t len);
|
||||||
|
|
||||||
|
#endif /* __NG_CTRL_H__ */
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
#include <CH58xBLE_LIB.h>
|
#include <CH58x_common.h>
|
||||||
|
|
||||||
#include "power.h"
|
#include "power.h"
|
||||||
#include "button.h"
|
#include "button.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
void poweroff()
|
void poweroff()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "CH58x_common.h"
|
#include "debug.h"
|
||||||
|
|
||||||
void print_setuppk(USB_SETUP_REQ *request)
|
void print_setuppk(USB_SETUP_REQ *request)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
#ifndef __DEBUG_H__
|
#ifndef __USB_DEBUG_H__
|
||||||
#define __DEBUG_H__
|
#define __USB_DEBUG_H__
|
||||||
|
|
||||||
#include "CH58x_common.h"
|
#include "CH58x_common.h"
|
||||||
|
#include "../debug.h"
|
||||||
|
|
||||||
#define _TRACE() PRINT("> "); PRINT(__FILE__);PRINT(": "); PRINT(__func__); \
|
|
||||||
PRINT("()\n")
|
|
||||||
|
|
||||||
void print_setuppk(USB_SETUP_REQ *setup_req_pk);
|
void print_setuppk(USB_SETUP_REQ *setup_req_pk);
|
||||||
void print_status_reg();
|
void print_status_reg();
|
||||||
void print_intflag_reg();
|
void print_intflag_reg();
|
||||||
|
|
||||||
#endif /* __DEBUG_H__ */
|
#endif /* __USB_DEBUG_H__ */
|
||||||
|
|||||||
25
src/util/crc.c
Normal file
25
src/util/crc.c
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#include "crc.h"
|
||||||
|
|
||||||
|
// Polynomial: x^8 + x^2 + x + 1 (0xE0)
|
||||||
|
uint8_t crc8_ccitt_update (uint8_t inCrc, uint8_t inData)
|
||||||
|
{
|
||||||
|
uint8_t data = inCrc ^ inData;
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
if (( data & 0x80 ) != 0 ) {
|
||||||
|
data <<= 1;
|
||||||
|
data ^= 0x07;
|
||||||
|
} else {
|
||||||
|
data <<= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t crc_cal(uint8_t *a, int len)
|
||||||
|
{
|
||||||
|
uint8_t crc = 0x00;
|
||||||
|
for (int i=0; i<len; i++) {
|
||||||
|
crc = crc8_ccitt_update(crc, a[i]);
|
||||||
|
}
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
9
src/util/crc.h
Normal file
9
src/util/crc.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#ifndef __UTIL_CRC_H__
|
||||||
|
#define __UTIL_CRC_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
uint8_t crc8_ccitt_update (uint8_t inCrc, uint8_t inData);
|
||||||
|
uint8_t crc_cal(uint8_t *a, int len);
|
||||||
|
|
||||||
|
#endif /* __UTIL_CRC_H__ */
|
||||||
10
src/xbm.c
10
src/xbm.c
@@ -2,15 +2,13 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
|
|
||||||
#define ALIGNBIT(x) (((x % 8)>0)*8 + (x / 8) * 8)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draw bitmap file to fb at (col, row)
|
* Draw bitmap file to fb at (col, row)
|
||||||
* if bitmap file larger than fb, it will be stripped out
|
* if bitmap file larger than fb, it will be stripped out
|
||||||
*/
|
*/
|
||||||
void xbm2fb(xbm_t *xbm, uint16_t *fb, int col, int row)
|
void xbm2fb(xbm_t *xbm, uint16_t *fb, int col, int row)
|
||||||
{
|
{
|
||||||
int W = ALIGNBIT(xbm->w);
|
int W = ALIGN_8BIT(xbm->w);
|
||||||
uint16_t *tmpfb = malloc(W * sizeof(uint16_t));
|
uint16_t *tmpfb = malloc(W * sizeof(uint16_t));
|
||||||
memset(tmpfb, 0, W * sizeof(uint16_t));
|
memset(tmpfb, 0, W * sizeof(uint16_t));
|
||||||
|
|
||||||
@@ -32,7 +30,7 @@ void xbm2fb(xbm_t *xbm, uint16_t *fb, int col, int row)
|
|||||||
void xbm2fb_dirty(xbm_t *xbm, uint16_t *fb, int col, int row)
|
void xbm2fb_dirty(xbm_t *xbm, uint16_t *fb, int col, int row)
|
||||||
{
|
{
|
||||||
// Byte align for xbm bytes
|
// Byte align for xbm bytes
|
||||||
int W = ALIGNBIT(xbm->w);
|
int W = ALIGN_8BIT(xbm->w);
|
||||||
|
|
||||||
for (int h = 0; h < xbm->h; h++) {
|
for (int h = 0; h < xbm->h; h++) {
|
||||||
for (int w = 0; w < W; w++) {
|
for (int w = 0; w < W; w++) {
|
||||||
@@ -48,8 +46,8 @@ void xbm2fb_dirty(xbm_t *xbm, uint16_t *fb, int col, int row)
|
|||||||
*/
|
*/
|
||||||
xbm_t *xbm_croph(xbm_t *xbm, xbm_t *frame, int from_row, int to_row)
|
xbm_t *xbm_croph(xbm_t *xbm, xbm_t *frame, int from_row, int to_row)
|
||||||
{
|
{
|
||||||
int rb = xbm->w / 8 + ((xbm->w % 8)>0); // Number of bytes in a row
|
int rb = ALIGN_1BYTE(xbm->w); // Number of bytes in a row
|
||||||
if (to_row * rb > rb * xbm->h)
|
if (to_row > xbm->h)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
frame->bits = &xbm->bits[rb * from_row];
|
frame->bits = &xbm->bits[rb * from_row];
|
||||||
|
|||||||
Reference in New Issue
Block a user