/* * Copyright 2015, Broadcom Corporation * All Rights Reserved. * * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; * the contents of this file may not be disclosed to third parties, copied * or duplicated in any form, in whole or in part, without the prior * written permission of Broadcom Corporation. */ /** @file * * uart demo for the anaren a20737-MSDB1 board. */ #define CONFIG_IN_NVRAM 1 #include "bleprofile.h" #include "bleapp.h" #include "gpiodriver.h" #include "stdio.h" #include "platform.h" #include "bleappconfig.h" #include "cfa.h" #include "spar_utils.h" #include "puart.h" #include "devicelpm.h" // To use PWM, we will need the auxiliary clock and the PWM drier. #include "aclk.h" #include "pwm.h" #include "i2cm.h" #include #include #include #include #include "utils.h" /****************************************************** * Constants ******************************************************/ // The GPIO to which an LED is assumed to be connected. Note that // the tag board does not have an LED connected to P26 by default. const BYTE RED_LED = GPIO_PIN_P26; const BYTE GREEN_LED = GPIO_PIN_P27; const BYTE BLUE_LED = GPIO_PIN_P28; const BYTE BUZZER = GPIO_PIN_P14; const BYTE IOEXPAND_INT = GPIO_PIN_2; BLE_PROFILE_CFG puart_control_cfg = {0}; // Please note that all UUIDs need to be reversed when publishing in the database #define SERVICE_1_UUID 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 #define SERVICE_1_CHARACTERISTIC_1_UUID 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 #define SERVICE_1_CHARACTERISTIC_2_UUID 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 #define SERVICE_1_CHARACTERISTIC_3_UUID 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 #define SERVICE_2_UUID 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 #define SERVICE_2_CHARACTERISTIC_1_UUID 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 #define SERVICE_3_UUID 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 #define SERVICE_4_UUID 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /****************************************************** * Types ******************************************************/ /****************************************************** * Function Prototypes ******************************************************/ static void app(void); static void timer_cb(UINT32 value); static void fine_timer_cb(UINT32 value); static UINT8* showActivity(UINT8 *buffer); static void ioexpand_int_handler(void *data, UINT8 pin); /****************************************************** * Variables Definitions ******************************************************/ const char BLE_NAME[] = "BCM20737"; const char DEV_VERSION[] = "0.01"; const UINT8 gatt_database[] = { //This service contains the device name //A read/write characteristic //The raw temp with ntf available PRIMARY_SERVICE_UUID128(0x0010,SERVICE_1_UUID), CHARACTERISTIC_UUID128(0x0011, 0x0012, SERVICE_1_CHARACTERISTIC_1_UUID, LEGATTDB_CHAR_PROP_READ, LEGATTDB_PERM_READABLE, 8), 'B','C','M','2','0','7','3','7', CHARACTERISTIC_UUID128_WRITABLE(0x0013, 0x0014, SERVICE_1_CHARACTERISTIC_2_UUID, LEGATTDB_CHAR_PROP_READ|LEGATTDB_CHAR_PROP_WRITE, LEGATTDB_PERM_READABLE|LEGATTDB_PERM_WRITABLE|LEGATTDB_PERM_WRITE_REQ, 16), 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, CHARACTERISTIC_UUID128_WRITABLE(0x0015, 0x0016, SERVICE_1_CHARACTERISTIC_3_UUID, LEGATTDB_CHAR_PROP_READ|LEGATTDB_CHAR_PROP_WRITE|LEGATTDB_CHAR_PROP_NOTIFY, LEGATTDB_PERM_READABLE|LEGATTDB_PERM_WRITABLE|LEGATTDB_PERM_WRITE_REQ, 18), 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, CHAR_DESCRIPTOR_UUID16_WRITABLE(0x17, UUID_DESCRIPTOR_CLIENT_CHARACTERISTIC_CONFIGURATION, LEGATTDB_PERM_READABLE | LEGATTDB_PERM_WRITE_CMD | LEGATTDB_PERM_WRITE_REQ, 2), 0x00,0x00, CHAR_DESCRIPTOR_UUID16(0x18, UUID_DESCRIPTOR_CHARACTERISTIC_USER_DESCRIPTION, LEGATTDB_PERM_READABLE, 11), 'T','e','m','p','e','r','a','t','u','r','e', //This service contains a characteristic to enable the buzzer PRIMARY_SERVICE_UUID128(0x0020,SERVICE_2_UUID), CHARACTERISTIC_UUID128_WRITABLE(0x0021, 0x0022, SERVICE_2_CHARACTERISTIC_1_UUID, LEGATTDB_CHAR_PROP_READ | LEGATTDB_CHAR_PROP_WRITE, LEGATTDB_PERM_READABLE|LEGATTDB_PERM_WRITABLE|LEGATTDB_PERM_WRITE_REQ, 1), 0x00, CHAR_DESCRIPTOR_UUID16(0x23, UUID_DESCRIPTOR_CHARACTERISTIC_USER_DESCRIPTION, LEGATTDB_PERM_READABLE, 6), 'B','u','z','z','e','r', PRIMARY_SERVICE_UUID128(0x0030,SERVICE_3_UUID), PRIMARY_SERVICE_UUID128(0x0040,SERVICE_4_UUID), }; BD_ADDR ble_device_addr = {0}; uint8_t run = 1; uint8_t temp = 0.0; UINT8 activityBuffer[4] = {'.',' ',' ',0}; char recvBuffer[20]; BYTE numConnectedClients = 0; /****************************************************** * Function Definitions ******************************************************/ static void serial_rxCb(void *unused) { UINT8 character = 0; uint8_t i = 0; while (puart_rxFifoNotEmpty() && puart_read(&character)) { puart_write(character); recvBuffer[i++ % 20] = character; bleapputils_delayUs(500); //Needed to let some time to the uart to receive the data } recvBuffer[i] = '\0'; // clear the interrupt P_UART_INT_CLEAR(P_UART_ISR_RX_AFF_MASK); // enable UART interrupt in the Main Interrupt Controller and RX Almost Full in the UART Interrupt Controller P_UART_INT_ENABLE |= P_UART_ISR_RX_AFF_MASK; if(memcmp(recvBuffer,"stop", 4) == 0) run = 0; else if(memcmp(recvBuffer,"start", 4) == 0) run = 1; } static void ioexpand_int_handler(void *data, UINT8 pin) { puart_print("IO int\n"); } static void ble_link_up(void) { puart_print("BLE Link up\n"); numConnectedClients++; } static void ble_link_down(void) { puart_print("BLE Link down\n"); //Mandatory to be able to reconnect once disconnected bleprofile_Discoverable(HIGH_UNDIRECTED_DISCOVERABLE, ble_device_addr); numConnectedClients--; if(!numConnectedClients)gpio_setPinOutput(PIN2PORT(RED_LED), PIN2PIN(RED_LED), 0); } static INT32 ble_write_handler(LEGATTDB_ENTRY_HDR *p) { UINT16 handle = legattdb_getHandle(p); int len = legattdb_getAttrValueLen(p), i = 0; UINT8 *buffer = legattdb_getAttrValue(p); puart_printf("Handle : 0x%02X\n", handle); puart_print("Client wrote (HEX) : #"); for(i = 0; i < len; i++) { puart_printf("0x%02X ",buffer[i]); } puart_print("#\n"); puart_print("Client wrote (ASCII) : #"); for(i = 0; i < len; i++) { puart_write(buffer[i]); } puart_print("#\n"); switch(handle) { case 0x17: if(len == 2) { if(buffer[0] & CCC_NOTIFICATION) puart_print("NTF enabled\n"); else puart_print("NTF disabled\n"); } break; case 0x22: if(buffer[0]) { puart_print("Buzzer on\n"); gpio_configurePin(PIN2PORT(BUZZER), PIN2PIN(BUZZER), PWM2_OUTPUT_ENABLE_P14 , 0); pwm_start(PWM2, PMU_CLK, 0x2FF, 0x200); } else { puart_print("Buzzer off\n"); gpio_configurePin(PIN2PORT(BUZZER), PIN2PIN(BUZZER), GPIO_OUTPUT_DISABLE | GPIO_PULL_DOWN, 0); pwm_setReset(PWM2, 1); } break; default: break; } return 0; } // Application initialization APPLICATION_INIT() { puart_control_cfg.fine_timer_interval = 1000; puart_control_cfg.default_adv = HIGH_UNDIRECTED_DISCOVERABLE; puart_control_cfg.button_adv_toggle = 0; puart_control_cfg.high_undirect_adv_interval = 32; puart_control_cfg.low_undirect_adv_interval = 1024; puart_control_cfg.high_undirect_adv_duration = 30; // seconds puart_control_cfg.low_undirect_adv_duration = 300; // seconds puart_control_cfg.high_direct_adv_interval = 0; // seconds puart_control_cfg.low_direct_adv_interval = 0; // seconds puart_control_cfg.high_direct_adv_duration = 0; // seconds puart_control_cfg.low_direct_adv_duration = 0; // seconds memcpy(puart_control_cfg.local_name, BLE_NAME, sizeof(BLE_NAME)); puart_control_cfg.cod[0] = (UINT8) APPEARANCE_GENERIC_TAG ; puart_control_cfg.cod[1] = APPEARANCE_GENERIC_TAG >> 8; memcpy(puart_control_cfg.ver, DEV_VERSION, sizeof(DEV_VERSION)); memset(puart_control_cfg.hdl, 0, HANDLE_NUM_MAX); memset(puart_control_cfg.serv, 0, HANDLE_NUM_MAX); memset(puart_control_cfg.cha, 0, HANDLE_NUM_MAX); puart_control_cfg.tx_power_level = 4; // max is +4 dBm... memset(recvBuffer, 0, sizeof(recvBuffer)); bleapp_set_cfg((UINT8 *)gatt_database, sizeof(gatt_database), (void *)&puart_control_cfg, (void *)NULL, (void *)NULL, app); } UINT32 uart_device_lpm_queriable(LowPowerModePollType type, UINT32 context) { // Disable sleep. return 0; } // Makes the little dot move at the end of the temperature string. UINT8* showActivity(UINT8 *buffer) { if(buffer[0] == '.') { buffer[0] = ' '; buffer[1] = '.'; buffer[2] = ' '; } else if(buffer[1] == '.') { buffer[0] = ' '; buffer[1] = ' '; buffer[2] = '.'; } else { buffer[0] = '.'; buffer[1] = ' '; buffer[2] = ' '; } return buffer; } void app(void) { devlpm_init(); //UART INIT SECTION puart_setBaudrate(0,0,115200); puart_selectUartPads(((GPIO_PIN_UART_RX / 16) << 5) | (GPIO_PIN_UART_RX % 16), ((GPIO_PIN_UART_TX / 16) << 5) | (GPIO_PIN_UART_TX % 16), 0 ,0); puart_init(); puart_flowOff(); devlpm_registerForLowPowerQueries(uart_device_lpm_queriable, 0); P_UART_INT_CLEAR(P_UART_ISR_RX_AFF_MASK); P_UART_WATER_MARK_RX_LEVEL(1); P_UART_INT_ENABLE |= P_UART_ISR_RX_AFF_MASK; puart_rxCb = serial_rxCb; puart_enableInterrupt(); //BLE INIT SECTION bleprofile_Init(bleprofile_p_cfg); bleprofile_regTimerCb(fine_timer_cb, timer_cb); bleprofile_StartTimer(); bleprofile_regAppEvtHandler(BLECM_APP_EVT_LINK_UP, ble_link_up); bleprofile_regAppEvtHandler(BLECM_APP_EVT_LINK_DOWN, ble_link_down); legattdb_regWriteHandleCb((LEGATTDB_WRITE_CB)ble_write_handler); bleprofile_Discoverable(HIGH_UNDIRECTED_DISCOVERABLE, ble_device_addr); gpio_configurePin(PIN2PORT(RED_LED), PIN2PIN(RED_LED), GPIO_OUTPUT_ENABLE, GPIO_PIN_OUTPUT_LOW); gpio_configurePin(PIN2PORT(GREEN_LED), PIN2PIN(GREEN_LED), GPIO_OUTPUT_ENABLE, GPIO_PIN_OUTPUT_LOW); gpio_configurePin(PIN2PORT(BLUE_LED), PIN2PIN(BLUE_LED), GPIO_OUTPUT_ENABLE, GPIO_PIN_OUTPUT_LOW); gpio_configurePin(PIN2PORT(IOEXPAND_INT), PIN2PIN(IOEXPAND_INT), GPIO_INPUT_ENABLE | GPIO_PULL_UP | GPIO_EN_INT_FALLING_EDGE, GPIO_PIN_INPUT_HIGH); //gpio_registerForInterrupt(NULL, ioexpand_int_handler, NULL); //Buzzer config aclk_configure(512000, ACLK1, ACLK_FREQ_24_MHZ); //I2C Bus init i2cm_init(); i2cm_setSpeed(I2CM_SPEED_400KHZ); puart_print("App init done\r\n"); } void timer_cb(UINT32 value) { static uint8_t state = 0; if(run) state++; switch(state%2) { case 0: gpio_setPinOutput(PIN2PORT(GREEN_LED), PIN2PIN(GREEN_LED), 1); gpio_setPinOutput(PIN2PORT(BLUE_LED), PIN2PIN(BLUE_LED), 0); break; default: gpio_setPinOutput(PIN2PORT(GREEN_LED), PIN2PIN(GREEN_LED), 0); gpio_setPinOutput(PIN2PORT(BLUE_LED), PIN2PIN(BLUE_LED), 1); //I2C test uint8_t reg = 0xFE; uint8_t ManuID[2]; uint16_t raw_temp = 0; if(i2cm_comboRead(ManuID, 2, ®, 1, 0x40 << 1) == I2CM_SUCCESS) { puart_print("I2C comboRead success\n"); puart_printf("Manu ID : 0x%02X%02X\n", ManuID[0], ManuID[1]); reg = 0x01; i2cm_comboRead(ManuID, 2, ®, 1, 0x40 << 1); raw_temp = (ManuID[0] << 6) + (ManuID[1] >> 2); temp = raw_temp / 32; puart_printf("Raw temp : 0x%02X%02X -> %u, %u\n", ManuID[0], ManuID[1], raw_temp, temp); } else puart_print("I2C comboRead failure\n"); } if(numConnectedClients) { gpio_togglePin(PIN2PORT(RED_LED), PIN2PIN(RED_LED)); } } void fine_timer_cb(UINT32 value) { BLEPROFILE_DB_PDU db_pdu; UINT8 buffer[18]; sprintf((char*)buffer,"temp : %u C%s", temp, showActivity(activityBuffer)); puart_printf("%s\nrecvBuffer : #%s#\n",buffer, recvBuffer); bleprofile_ReadHandle(0x0016, &db_pdu); memcpy(db_pdu.pdu, buffer, sizeof(buffer)); db_pdu.len = strlen(buffer); bleprofile_WriteHandle(0x0016, &db_pdu); bleprofile_sendNotification(0x0016, (UINT8 *)db_pdu.pdu, db_pdu.len); }