diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_sys.c b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_sys.c index 3608e36..9ec9509 100644 --- a/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_sys.c +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_sys.c @@ -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 - diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH583SFR.h b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH583SFR.h index 86fa854..05ee89d 100644 --- a/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH583SFR.h +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH583SFR.h @@ -123,12 +123,6 @@ typedef volatile unsigned long long *PUINT64V; #define max(a,b) (((a) > (b)) ? (a) : (b)) #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 */ #define FIELD_OFFSET(Type, Field) ((UINT16)&(((Type *)0)->Field)) diff --git a/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_common.h b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_common.h index 965cac6..b51fe14 100644 --- a/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_common.h +++ b/CH5xx_ble_firmware_library/StdPeriphDriver/inc/CH58x_common.h @@ -36,15 +36,6 @@ #endif #endif -#define Debug_UART0 0 -#define Debug_UART1 1 -#define Debug_UART2 2 -#define Debug_UART3 3 - -#ifdef DEBUG -#include -#endif - /** * @brief 系统主频时钟(Hz) */ diff --git a/Makefile b/Makefile index e81e396..82e715a 100644 --- a/Makefile +++ b/Makefile @@ -47,25 +47,25 @@ CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_clk.c \ CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_uart0.c \ CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_timer1.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_usbhostBase.c \ CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_timer3.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_uart1.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/RVMSIS/core_riscv.c \ src/main.c \ +src/debug.c \ src/leddrv.c \ src/button.c \ src/bmlist.c \ src/ble/profile/legacy.c \ src/ble/profile/batt.c \ src/ble/profile/devinfo.c \ +src/ble/profile/ng.c \ +src/config.c \ +src/ngctrl.c \ src/ble/setup.c \ src/ble/peripheral.c \ src/data.c \ @@ -129,6 +129,7 @@ C_INCLUDES = \ ASFLAGS = $(MCU) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections CFLAGS = $(MCU) $(C_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections +CFLAGS += -Werror=implicit-function-declaration ifeq ($(DEBUG), 1) CFLAGS += -g -gdwarf-2 -DDEBUG=$(DEBUG) diff --git a/src/ble/peripheral.c b/src/ble/peripheral.c index f9c5e58..b9bd4ae 100644 --- a/src/ble/peripheral.c +++ b/src/ble/peripheral.c @@ -1,5 +1,6 @@ #include "CH58xBLE_LIB.h" #include "setup.h" +#include "../config.h" #define ADV_UUID (0xFEE0) @@ -24,29 +25,6 @@ typedef struct #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) // keep short, save energy, save the planet static uint8 advertData[] = { @@ -210,21 +188,58 @@ void ble_disable_advertise() 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() { GAPRole_PeripheralInit(); - static uint16 desired_min_interval = 6; - static uint16 desired_max_interval = 500; + uint16_t min_interval = 6; + uint16_t max_interval = 500; // Set the GAP Role Parameters - GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, sizeof(scanRspData), scanRspData); + setup_scan_rsp(badge_cfg.ble.devname.ptr, badge_cfg.ble.devname.len); GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData); - GAPRole_SetParameter(GAPROLE_MIN_CONN_INTERVAL, sizeof(uint16), &desired_min_interval); - GAPRole_SetParameter(GAPROLE_MAX_CONN_INTERVAL, sizeof(uint16), &desired_max_interval); + GAPRole_SetParameter(GAPROLE_MIN_CONN_INTERVAL, sizeof(uint16), &min_interval); + GAPRole_SetParameter(GAPROLE_MAX_CONN_INTERVAL, sizeof(uint16), &max_interval); // Set the GAP Characteristics - GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, devName); + GGS_SetParameter(GGS_DEVICE_NAME_ATT, badge_cfg.ble.devname.len, + badge_cfg.ble.devname.ptr); GAP_SetParamValue(TGAP_DISC_ADV_INT_MIN, MIN_ADV_INTERVAL); GAP_SetParamValue(TGAP_DISC_ADV_INT_MAX, MAX_ADV_INTERVAL); diff --git a/src/ble/profile.h b/src/ble/profile.h index 1472a3d..39e7e79 100644 --- a/src/ble/profile.h +++ b/src/ble/profile.h @@ -4,5 +4,8 @@ int legacy_registerService(); int devInfo_registerService(); int batt_registerService(); +int ng_registerService(); + +bStatus_t ng_notify(uint8_t *pValue, uint8_t len); #endif /* __BLE_UART_SERVICE_H__ */ diff --git a/src/ble/profile/ng.c b/src/ble/profile/ng.c new file mode 100644 index 0000000..7ab96ce --- /dev/null +++ b/src/ble/profile/ng.c @@ -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; +} diff --git a/src/ble/setup.c b/src/ble/setup.c index 7049acb..8a8e015 100644 --- a/src/ble/setup.c +++ b/src/ble/setup.c @@ -6,28 +6,39 @@ #include "CH58x_common.h" #ifndef BLE_BUFF_LEN -#define BLE_BUFF_LEN 27 -#endif -#ifndef BLE_BUFF_NUM -#define BLE_BUFF_NUM 5 +// MTU = 64 but clients should request new MTU, otherwise default will be 23 +#define BLE_BUFF_LEN (64 + 4) #endif + #ifndef BLE_TX_NUM_EVENT #define BLE_TX_NUM_EVENT 1 #endif + #ifndef BLE_TX_POWER #define BLE_TX_POWER LL_TX_POWEER_6_DBM +// #define BLE_TX_POWER LL_TX_POWEER_MINUS_16_DBM #endif + #ifndef BLE_MEMHEAP_SIZE -#define BLE_MEMHEAP_SIZE (1024*6) +#define BLE_MEMHEAP_SIZE (1024 * 6) #endif + #ifndef CENTRAL_MAX_CONNECTION -#define CENTRAL_MAX_CONNECTION 3 +#define CENTRAL_MAX_CONNECTION 1 #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 #define PERIPHERAL_MAX_CONNECTION 1 #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) { diff --git a/src/config.c b/src/config.c new file mode 100644 index 0000000..44157a5 --- /dev/null +++ b/src/config.c @@ -0,0 +1,163 @@ +#include "config.h" +#include "resource.h" +#include "res/foss-asia-2.xbm" + +#include "ISP583.h" +#include + +#define __ble_name "LED Badge Magic" +// static sfmem_t ble_name = {sizeof(__ble_name) - 1, (uint8_t *)__ble_name}; + +// Default configuration +badge_cfg_t badge_cfg = { + .ble.always_on = 1, + .ble.devname.len = sizeof(__ble_name) - 1, + .ble.devname.ptr = __ble_name, + + .led.brightness = 0, + .led.scan_freq = 2000, + + .splash.bm.bits = foss_asia_2_bits, + .splash.bm.w = 44, + .splash.bm.h = 22, + .splash.bm.fh = 11, + .splash.speed_t = 30, // ms +}; + +// uint32_t cfglen(badge_cfg_t cfg) +// { +// uint32_t len = sizeof(badge_cfg_t); +// uint32_t len = sizeof(splash_cfg_t); +// uint32_t len = sizeof(led_cfg_t); +// uint32_t len = sizeof(ble_cfg_t); +// } + +static int flash_write(uint8_t *buf, uint32_t base_addr, uint16_t len) +{ + return EEPROM_WRITE(base_addr, buf, len); +} + +static int flash_read(uint8_t *buf, uint32_t base_addr, uint16_t len) +{ + return EEPROM_READ(base_addr, buf, len); +} + +static int ble_cfg_write(ble_cfg_t *cfg, uint32_t base_addr) +{ + int ret; + ret = flash_write(cfg, base_addr, sizeof(ble_cfg_t)); + if (ret) { + return ret; + } + + base_addr += sizeof(ble_cfg_t); + ret = flash_write(cfg->devname.ptr, base_addr, cfg->devname.len); + if (ret) { + return ret; + } + + return 0; +} + +static int ble_cfg_read(ble_cfg_t *cfg, uint32_t base_addr) +{ + int ret; + ret = flash_read(cfg, base_addr, sizeof(ble_cfg_t)); + if (ret) { + return ret; + } + + uint32_t devname_offs = (uint32_t)cfg->devname.ptr; + ret = flash_read(cfg->devname.ptr, devname_offs, cfg->devname.len); + if (ret) { + return ret; + } + + return 0; +} + +#define XBM_BYTE_PER_ROW(xbm) xbm.w / 8 + ((xbm.w % 8)>0) // Number of bytes in a row + +static int splash_cfg_read(splash_cfg_t *cfg, uint32_t base_addr) +{ + int ret; + ret = flash_read(cfg, base_addr, sizeof(splash_cfg_t)); + if (ret) { + return ret; + } + + uint32_t devname_offs = (uint32_t) cfg->bm.bits; + int len = XBM_BYTE_PER_ROW(cfg->bm) * cfg->bm.h; + ret = flash_read(cfg->bm.bits, devname_offs, len); + if (ret) { + return ret; + } + + return 0; +} + +// cfg.bm.bits will be written next to cfg header and its pointer will be +// modified to be cfg.xbm.bits = base_addr + sizeof(splash_cfg_t) instead of +// pointer in memory +static int splash_cfg_write(splash_cfg_t *cfg, uint32_t base_addr) +{ + int ret; + + // write bits next to splash cfg + int len = XBM_BYTE_PER_ROW(cfg->bm) * (cfg->bm.h); + int bits_offs = base_addr + sizeof(splash_cfg_t); + ret = flash_write(cfg->bm.bits, bits_offs, len); + if (ret) { + return ret; + } + + // point to eeprom offset instead of mem + cfg->bm.bits = base_addr + sizeof(splash_cfg_t); + + // write splash cfg + ret = flash_write(cfg, base_addr, sizeof(splash_cfg_t)); + if (ret) { + return ret; + } + + return 0; +} + +int cfg_read(badge_cfg_t *cfg, uint32_t base_addr) +{ + int ret = flash_read(cfg, base_addr, sizeof(badge_cfg_t)); + if (ret) { + return ret; + } + return 0; +} + +int cfg_init() +{ + +} + +int cfg_read_alloc(badge_cfg_t **buf, uint32_t base_addr) +{ + int ret; + *buf = malloc(sizeof(badge_cfg_t)); + ret = cfg_read(base_addr, *buf); + if (ret) { + return ret; + } + + (*buf)->ble.devname.ptr = malloc(sizeof((*buf)->ble.devname.len)); + ret = ble_cfg_read((*buf)->ble.devname.ptr, (*buf)->ble.devname.len); + if (ret) { + return ret; + } + + int rb = XBM_BYTE_PER_ROW((*buf)->splash.bm); + (*buf)->splash.bm.bits = malloc(rb); + ret = splash_cfg_read((*buf)->splash.bm.bits, rb); + if (ret) { + return ret; + } + + return 0; +} \ No newline at end of file diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..99575e9 --- /dev/null +++ b/src/config.h @@ -0,0 +1,40 @@ +#ifndef __CONFIG_H__ +#define __CONFIG_H__ + +#include + +#include "xbm.h" + +// safe mem +typedef struct { + uint16_t len; + uint8_t *ptr; +} __attribute__((packed)) sfmem_t; + +typedef struct { + uint8_t always_on; // keep BLE on in normal mode + // Turn on Bluetooth while in Normal mode and disable Downloads mode + sfmem_t devname; +} __attribute__((packed)) ble_cfg_t; + +typedef struct { + xbm_t bm; + // Speed in period of micro second. The lower value, the higher speed + uint16_t speed_t; +} __attribute__((packed)) splash_cfg_t; + +typedef struct { + uint8_t brightness; + uint16_t scan_freq; // Scan frequency +} __attribute__((packed)) led_cfg_t; + +typedef struct { + ble_cfg_t ble; + splash_cfg_t splash; + led_cfg_t led; + // uint8_t reset_after_complete_download; +} __attribute__((packed)) badge_cfg_t; + +extern badge_cfg_t badge_cfg; + +#endif /* __CONFIG_H__ */ diff --git a/src/debug.c b/src/debug.c new file mode 100644 index 0000000..e0137af --- /dev/null +++ b/src/debug.c @@ -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 \ No newline at end of file diff --git a/src/debug.h b/src/debug.h new file mode 100644 index 0000000..6378f4b --- /dev/null +++ b/src/debug.h @@ -0,0 +1,15 @@ +#ifndef __DEBUG_H__ +#define __DEBUG_H__ + +#include + +#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__ */ diff --git a/src/main.c b/src/main.c index e22b5a3..315c549 100644 --- a/src/main.c +++ b/src/main.c @@ -11,15 +11,14 @@ #include "power.h" #include "data.h" +#include "config.h" +#include "debug.h" #include "ble/setup.h" #include "ble/profile.h" #include "usb/usb.h" -#define SCAN_F (2000) -#define SCAN_T (FREQ_SYS / SCAN_F) - #define NEXT_STATE(v, min, max) \ (v)++; \ if ((v) >= (max)) \ @@ -81,10 +80,10 @@ static void bm_transition() 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) { - DelayMs(30); + DelayMs(spT); } } @@ -205,11 +204,15 @@ void ble_setup() tmos_clockInit(); peripheral_init(); - ble_disable_advertise(); + + if (! badge_cfg.ble.always_on) { + ble_disable_advertise(); + } devInfo_registerService(); legacy_registerService(); batt_registerService(); + ng_registerService(); } static void usb_receive(uint8_t *buf, uint16_t len) @@ -246,7 +249,7 @@ static void usb_receive(uint8_t *buf, uint16_t len) } } -void spawn_tasks() +static void spawn_tasks() { common_taskid = TMOS_ProcessEventRegister(common_tasks); @@ -257,16 +260,69 @@ void spawn_tasks() tmos_start_task(common_taskid, ANI_NEXT_STEP, 500000 / 625); } -void ble_start() +static void start_ble_animation() +{ + tmos_stop_task(common_taskid, ANI_NEXT_STEP); + tmos_stop_task(common_taskid, ANI_MARQUE); + tmos_stop_task(common_taskid, ANI_FLASH); + memset(fb, 0, sizeof(fb)); + + tmos_start_reload_task(common_taskid, BLE_NEXT_STEP, 500000 / 625); +} + +static void ble_start() { ble_enable_advertise(); + start_ble_animation(); +} + +static void start_normal_animation() +{ + tmos_start_reload_task(common_taskid, ANI_MARQUE, ANI_MARQUE_SPEED_T / 625); + tmos_start_reload_task(common_taskid, ANI_FLASH, ANI_FLASH_SPEED_T / 625); + tmos_start_task(common_taskid, ANI_NEXT_STEP, 500000 / 625); +} +static void resume_normal() +{ + if (badge_cfg.ble.always_on) { + start_normal_animation(); + } else { + start_ble_animation(); + } +} + +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)); +} - tmos_start_reload_task(common_taskid, BLE_NEXT_STEP, 500000 / 625); +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_normal(); + 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; } void handle_mode_transition() @@ -277,6 +333,9 @@ void handle_mode_transition() switch (mode) { case DOWNLOAD: + if (badge_cfg.ble.always_on) { + poweroff(); + } // Disable bitmap transition while in download mode btn_onOnePress(KEY2, NULL); @@ -375,7 +434,7 @@ int main() usb_start(); led_init(); - TMR0_TimerInit(SCAN_T / 4); + TMR0_TimerInit((FREQ_SYS / 2000) / 2); TMR0_ITCfg(ENABLE, TMR0_3_IT_CYC_END); PFIC_EnableIRQ(TMR0_IRQn); @@ -387,8 +446,9 @@ int main() btn_onLongPress(KEY1, change_brightness); disp_charging(); - - play_splash(&splash, 0, 0); + + xbm_t a = badge_cfg.splash.bm; + play_splash(&a, 0, 0, badge_cfg.splash.speed_t); load_bmlist(); diff --git a/src/ngctrl.c b/src/ngctrl.c new file mode 100644 index 0000000..7db4e90 --- /dev/null +++ b/src/ngctrl.c @@ -0,0 +1,67 @@ +#include "ngctrl.h" + +#include "CH58xBLE_LIB.h" +#include "CH583SFR.h" + +#include "ble/profile.h" +#include "power.h" +#include "debug.h" + +uint8_t next_packet(uint8_t *val, uint16_t len) +{ + PRINT(__func__); + PRINT(": to be implemented\n"); + return 0; +} + +uint8_t power_switch(uint8_t *val, uint16_t len) +{ + PRINT(__func__); + PRINT(": to be implemented\n"); + poweroff(); + return 0; +} + +uint8_t ble_setting(uint8_t *val, uint16_t len) +{ + PRINT(__func__); + PRINT(": to be implemented\n"); + return 0; +} + +uint8_t flash_splash_screen(uint8_t *val, uint16_t len) +{ + PRINT(__func__); + PRINT(": to be implemented\n"); + return 0; +} + +const uint8_t (*cmd_lut[])(uint8_t *val, uint16_t len) = { + next_packet, + power_switch, + streaming_setting, + stream_bitmap, + ble_setting, // always-on, adv name + flash_splash_screen +}; + +#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; +} \ No newline at end of file diff --git a/src/ngctrl.h b/src/ngctrl.h new file mode 100644 index 0000000..aa80e08 --- /dev/null +++ b/src/ngctrl.h @@ -0,0 +1,20 @@ +#ifndef __NG_CTRL_H__ +#define __NG_CTRL_H__ + +#include + +// enum NG_STATUS { + +// }; + +uint8_t next_packet(uint8_t *val, uint16_t len); +uint8_t power_switch(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__ */ diff --git a/src/power.c b/src/power.c index 0192f8a..f1d6d41 100644 --- a/src/power.c +++ b/src/power.c @@ -1,7 +1,8 @@ -#include +#include #include "power.h" #include "button.h" +#include "debug.h" void poweroff() { diff --git a/src/usb/debug.c b/src/usb/debug.c index 0c9f443..95d756e 100644 --- a/src/usb/debug.c +++ b/src/usb/debug.c @@ -1,4 +1,4 @@ -#include "CH58x_common.h" +#include "debug.h" void print_setuppk(USB_SETUP_REQ *request) { diff --git a/src/usb/debug.h b/src/usb/debug.h index 1279115..0aa0ebb 100644 --- a/src/usb/debug.h +++ b/src/usb/debug.h @@ -1,14 +1,11 @@ -#ifndef __DEBUG_H__ -#define __DEBUG_H__ +#ifndef __USB_DEBUG_H__ +#define __USB_DEBUG_H__ #include "CH58x_common.h" - - -#define _TRACE() PRINT("> "); PRINT(__FILE__);PRINT(": "); PRINT(__func__); \ - PRINT("()\n") +#include "../debug.h" void print_setuppk(USB_SETUP_REQ *setup_req_pk); void print_status_reg(); void print_intflag_reg(); -#endif /* __DEBUG_H__ */ +#endif /* __USB_DEBUG_H__ */