#include #include #include "CH58x_common.h" #include "CH58x_sys.h" #include "CH58xBLE_LIB.h" #include "led.h" #include "wang.h" int ble_on = 0; int ble_connected = 0; void ble_toggle(void) { uint8_t ble_mode = ble_on ? FALSE : TRUE; GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(ble_mode), &ble_mode); ble_on = !ble_on; } // We use TMOS only for BLE things and wrap the rest. static __attribute__((aligned(4), section(".noinit"))) uint8_t BLE_BUF[1024 * 6]; static void ble_calib_cb(void) { Calibration_LSI(Level_128); } static uint8_t periph_task = INVALID_TASK_ID; static uint16_t peripheral_task(uint8_t task_id, uint16_t events) { if (events & SYS_EVENT_MSG) { uint8_t *pMsg = tmos_msg_receive(periph_task); if (pMsg) { // process the message. noop. tmos_msg_deallocate(pMsg); } return events ^ SYS_EVENT_MSG; } return 0; } static void gap_onParamUpdate(uint16_t a, uint16_t b, uint16_t c, uint16_t d) { } static void gap_onStateChange(gapRole_States_t a, gapRoleEvent_t *b) { } uint8_t advertData[] = { 0x02, GAP_ADTYPE_FLAGS, GAP_ADTYPE_FLAGS_GENERAL | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED, 0x03, GAP_ADTYPE_16BIT_MORE, LO_UINT16(0xFEE0), HI_UINT16(0xFEE0), }; uint8_t scanRspData[31] = { 0x05, GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE, LO_UINT16(100), HI_UINT16(100), LO_UINT16(200), HI_UINT16(200), 0x02, GAP_ADTYPE_POWER_LEVEL, 6, 19, GAP_ADTYPE_LOCAL_NAME_COMPLETE, 'L', 'S', 'L', 'E', 'D', ' ', 'B', 'a', 'd', 'g', 'e', ' ', 'W', 'i', 't', 'c', 'h', 0, 0, 0, }; static gapRolesBroadcasterCBs_t broadcast_handlers = { 0, 0, }; static gapRolesCBs_t gap_handlers = { gap_onStateChange, 0, gap_onParamUpdate, }; static gapBondCBs_t bond_managers = { 0, 0, }; static const uint8_t service_uuid[2] = {LO_UINT16(0xFEE0), HI_UINT16(0xFEE0)}; static const gattAttrType_t service = {2, service_uuid}; static const uint8_t rx_char_uuid[2] = {LO_UINT16(0xFEE1), HI_UINT16(0xFEE1)}; static uint8_t rx_char_props = GATT_PROP_WRITE; static uint8_t rx_char_val[16]; static gattAttribute_t attr_table[] = { {{2, primaryServiceUUID}, GATT_PERMIT_READ, 0, (uint8_t *)&service}, {{2, characterUUID}, GATT_PERMIT_READ, 0, &rx_char_props}, {{2, rx_char_uuid}, GATT_PERMIT_WRITE, 0, (uint8_t *)&rx_char_val}, }; uint16_t blefb[44] = {0}; static bStatus_t write_handler(uint16_t conn_handle, gattAttribute_t *pAttr, uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method) { if (gattPermitAuthorWrite(pAttr->permissions)) return ATT_ERR_INSUFFICIENT_AUTHOR; uint16_t uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]); if (uuid != 0xFEE1) return ATT_ERR_ATTR_NOT_FOUND; wang_rx(pValue, len); return SUCCESS; } static gattServiceCBs_t service_handlers = { 0, write_handler, 0, }; void ble_init(void) { bleConfig_t cfg = {0}; // BLE heap cfg.MEMAddr = (uint32_t) BLE_BUF; cfg.MEMLen = (uint32_t) sizeof(BLE_BUF); // not using the bonding information, as we do not support _bonding_. // This should be changed. but. you know. // TODO: magic numbers // amount of buffered packets cfg.BufNumber = (512 / 23); // maximum data length of each packet cfg.BufMaxLen = (64 + 4); cfg.TxNumEvent = 1; cfg.TxPower = LL_TX_POWEER_6_DBM; cfg.ConnectNumber = (1 & 3) | (1 << 2); cfg.SelRTCClock = 1 << 7; cfg.rcCB = ble_calib_cb; uint8_t m[6]; GetMACAddress(m); memcpy(cfg.MacAddr, m, 6); BLE_LibInit(&cfg); sys_safe_access_enable(); R8_CK32K_CONFIG &= ~(RB_CLK_OSC32K_XT | RB_CLK_XT32K_PON); sys_safe_access_enable(); R8_CK32K_CONFIG |= RB_CLK_INT32K_PON; sys_safe_access_disable(); Calibration_LSI(Level_128); RTC_InitTime(2020, 1, 1, 0, 0, 0); TMOS_TimerInit(0); periph_task = TMOS_ProcessEventRegister(peripheral_task); GAPRole_PeripheralInit(); // the GAP parameters all kinda suck to set. sooo #define SET_PARAM(a, b, c, d) do { static c val = d; a(b, sizeof(val), &val); } while(0) SET_PARAM(GAPRole_SetParameter, GAPROLE_ADVERT_ENABLED, uint8_t, FALSE); GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, 31, scanRspData); GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData); SET_PARAM(GAPRole_SetParameter, GAPROLE_MIN_CONN_INTERVAL, uint16_t, 6); SET_PARAM(GAPRole_SetParameter, GAPROLE_MAX_CONN_INTERVAL, uint16_t, 500); GGS_SetParameter(GGS_DEVICE_NAME_ATT, 20, "LED Badge Witch\0\0\0\0\0\0\0"); GAP_SetParamValue(TGAP_DISC_ADV_INT_MIN, 100); GAP_SetParamValue(TGAP_DISC_ADV_INT_MAX, 200); SET_PARAM(GAPBondMgr_SetParameter, GAPBOND_PERI_DEFAULT_PASSCODE, uint32_t, 0); SET_PARAM(GAPBondMgr_SetParameter, GAPBOND_PERI_PAIRING_MODE, uint8_t, GAPBOND_PAIRING_MODE_NO_PAIRING); SET_PARAM(GAPBondMgr_SetParameter, GAPBOND_PERI_MITM_PROTECTION, uint8_t, FALSE); SET_PARAM(GAPBondMgr_SetParameter, GAPBOND_PERI_IO_CAPABILITIES, uint8_t, GAPBOND_IO_CAP_DISPLAY_ONLY); SET_PARAM(GAPBondMgr_SetParameter, GAPBOND_PERI_BONDING_ENABLED, uint8_t, FALSE); GAPRole_BroadcasterSetCB(&broadcast_handlers); GGS_AddService(GATT_ALL_SERVICES); GATTServApp_AddService(GATT_ALL_SERVICES); GAPRole_PeripheralStartDevice(periph_task, &bond_managers, &gap_handlers); GATTServApp_RegisterService(attr_table, GATT_NUM_ATTRS(attr_table), GATT_MAX_ENCRYPT_KEY_SIZE, &service_handlers); } struct connection_data { uint16_t handle; uint16_t interval; uint16_t slave_latency; uint16_t timeout; };