407 lines
12 KiB
C
407 lines
12 KiB
C
/*
|
|
* 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 <inttypes.h>
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#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 litle 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);
|
|
|
|
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);
|
|
}
|