388 lines
13 KiB
C
388 lines
13 KiB
C
|
#include <stdint.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#include "fr30xx.h"
|
||
|
|
||
|
#include "co_util.h"
|
||
|
|
||
|
#include "bt_types.h"
|
||
|
#include "me_api.h"
|
||
|
#include "hfg_api.h"
|
||
|
#include "gatt_api.h"
|
||
|
|
||
|
#include "app_at.h"
|
||
|
#include "app_task.h"
|
||
|
#include "app_ble.h"
|
||
|
|
||
|
#define AT_RECV_MAX_LEN 32
|
||
|
|
||
|
static uint8_t app_at_recv_char;
|
||
|
static uint8_t at_recv_buffer[AT_RECV_MAX_LEN];
|
||
|
static uint8_t at_recv_index = 0;
|
||
|
static uint8_t at_recv_state = 0;
|
||
|
|
||
|
void btdm_host_send_vendor_cmd(uint8_t type, uint8_t length, void *data);
|
||
|
|
||
|
void btdm_host_vendor_cmd_cmp_evt(uint8_t status, uint8_t len, uint8_t const *param)
|
||
|
{
|
||
|
printf("status: 0x%02x.\r\n", status);
|
||
|
for (uint32_t i=0; i<len; i++) {
|
||
|
printf("%02x ", param[i]);
|
||
|
}
|
||
|
printf("\r\n");
|
||
|
}
|
||
|
|
||
|
void btdm_host_recv_vendor_evt(uint8_t len, uint8_t *param)
|
||
|
{
|
||
|
if (param[1] == 0x10) {
|
||
|
float acc[3];
|
||
|
memcpy((void *)&acc[0], ¶m[3], sizeof(float) * 3);
|
||
|
printf("%0.6f, %0.6f, %0.6f\r\n", acc[0], acc[1], acc[2]);
|
||
|
return;
|
||
|
}
|
||
|
printf("EVENT: ");
|
||
|
for (uint32_t i=0; i<len; i++) {
|
||
|
printf("%02x ", param[i]);
|
||
|
}
|
||
|
printf("\r\n");
|
||
|
}
|
||
|
|
||
|
static void app_at_recv_cmd_A(uint8_t sub_cmd, uint8_t *data)
|
||
|
{
|
||
|
switch(sub_cmd)
|
||
|
{
|
||
|
// case 'A':
|
||
|
// {
|
||
|
// mac_addr_t addr;
|
||
|
// addr.addr[5] = ascii_strn2val((const char *)&data[0], 16, 2);
|
||
|
// addr.addr[4] = ascii_strn2val((const char *)&data[2], 16, 2);
|
||
|
// addr.addr[3] = ascii_strn2val((const char *)&data[4], 16, 2);
|
||
|
// addr.addr[2] = ascii_strn2val((const char *)&data[6], 16, 2);
|
||
|
// addr.addr[1] = ascii_strn2val((const char *)&data[8], 16, 2);
|
||
|
// addr.addr[0] = ascii_strn2val((const char *)&data[10], 16, 2);
|
||
|
// gap_start_conn(&addr, ascii_strn2val((const char *)&data[12], 16, 2), 64, 64, 0, 500);
|
||
|
// }
|
||
|
// break;
|
||
|
// case 'B':
|
||
|
// {
|
||
|
// gap_stop_conn();
|
||
|
// }
|
||
|
// break;
|
||
|
case 'A':
|
||
|
{
|
||
|
uint8_t addr = ascii_strn2val((const char *)&data[0], 16, 2);
|
||
|
btdm_host_send_vendor_cmd(0x00, 1, &addr);
|
||
|
}
|
||
|
printf("OK\r\n");
|
||
|
break;
|
||
|
case 'B':
|
||
|
{
|
||
|
uint8_t buffer[2];
|
||
|
buffer[0] = ascii_strn2val((const char *)&data[0], 16, 2);
|
||
|
buffer[1] = ascii_strn2val((const char *)&data[3], 16, 2);
|
||
|
btdm_host_send_vendor_cmd(0x01, 2, (void *)&buffer[0]);
|
||
|
}
|
||
|
printf("OK\r\n");
|
||
|
break;
|
||
|
case 'C':
|
||
|
{
|
||
|
uint32_t addr = ascii_strn2val((const char *)&data[0], 16, 8);
|
||
|
btdm_host_send_vendor_cmd(0x02, 4, (void *)&addr);
|
||
|
}
|
||
|
printf("OK\r\n");
|
||
|
break;
|
||
|
case 'D':
|
||
|
{
|
||
|
uint32_t buffer[2];
|
||
|
buffer[0] = ascii_strn2val((const char *)&data[0], 16, 8);
|
||
|
buffer[1] = ascii_strn2val((const char *)&data[9], 16, 8);
|
||
|
btdm_host_send_vendor_cmd(0x03, 8, (void *)&buffer[0]);
|
||
|
}
|
||
|
printf("OK\r\n");
|
||
|
break;
|
||
|
// case 'C':
|
||
|
// {
|
||
|
// btdm_host_send_vendor_cmd(0x15, 0, NULL);
|
||
|
// }
|
||
|
// printf("OK\r\n");
|
||
|
// break;
|
||
|
// case 'D':
|
||
|
// {
|
||
|
// uint8_t mode = ascii_strn2val((const char *)&data[0], 16, 2);
|
||
|
// btdm_host_send_vendor_cmd(0x14, 1, &mode);
|
||
|
// }
|
||
|
// printf("OK\r\n");
|
||
|
// break;
|
||
|
case 'E':
|
||
|
{
|
||
|
// btdm_host_send_vendor_cmd(0x11, 0, NULL);
|
||
|
|
||
|
uint8_t sleep_dur[2];
|
||
|
sleep_dur[0] = ascii_strn2val((const char *)&data[0], 16, 2);
|
||
|
sleep_dur[1] = ascii_strn2val((const char *)&data[3], 16, 2);
|
||
|
btdm_host_send_vendor_cmd(0x16, 2, &sleep_dur);
|
||
|
}
|
||
|
printf("OK\r\n");
|
||
|
break;
|
||
|
case 'F':
|
||
|
{
|
||
|
static uint8_t hour = 0;
|
||
|
static uint8_t minute = 0;
|
||
|
static uint8_t second = 0;
|
||
|
static uint16_t mini_second = 0;
|
||
|
uint8_t gsensor_cmd[] = {0x00, 0xe7, 0x07, 0x09, 0x12, 0x14, 0x36, 0x10, 0x20, 0x00, 0x2c, 0x01};
|
||
|
mini_second += 200;
|
||
|
if (mini_second >= 1000) {
|
||
|
mini_second = 0;
|
||
|
second++;
|
||
|
if (second >= 60) {
|
||
|
second = 0;
|
||
|
minute++;
|
||
|
if (minute >= 60) {
|
||
|
minute = 0;
|
||
|
hour++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
gsensor_cmd[5] = hour;
|
||
|
gsensor_cmd[6] = minute;
|
||
|
gsensor_cmd[7] = second;
|
||
|
gsensor_cmd[8] = mini_second;
|
||
|
gsensor_cmd[9] = mini_second >> 8;
|
||
|
btdm_host_send_vendor_cmd(0x12, sizeof(gsensor_cmd), gsensor_cmd);
|
||
|
}
|
||
|
break;
|
||
|
case 'G':
|
||
|
printf("hello world!\r\n");
|
||
|
break;
|
||
|
case 'H':
|
||
|
printf("VAL: 0x%08x.\r\n", *(volatile uint32_t *)ascii_strn2val((const char *)&data[0], 16, 8));
|
||
|
break;
|
||
|
case 'I':
|
||
|
*(volatile uint32_t *)ascii_strn2val((const char *)&data[0], 16, 8) = ascii_strn2val((const char *)&data[9], 16, 8);
|
||
|
printf("OK\r\n");
|
||
|
break;
|
||
|
case 'J':
|
||
|
printf("OOL VAL: 0x%02x.\r\n", ool_read(ascii_strn2val((const char *)&data[0], 16, 2)));
|
||
|
break;
|
||
|
case 'K':
|
||
|
ool_write(ascii_strn2val((const char *)&data[0], 16, 2), ascii_strn2val((const char *)&data[3], 16, 2));
|
||
|
printf("OK\r\n");
|
||
|
break;
|
||
|
case 'L':
|
||
|
printf("VAL: 0x%02x.\r\n", *(volatile uint8_t *)(ascii_strn2val((const char *)&data[0], 16, 8)));
|
||
|
break;
|
||
|
case 'M':
|
||
|
*(volatile uint8_t *)(ascii_strn2val((const char *)&data[0], 16, 8)) = ascii_strn2val((const char *)&data[9], 16, 2);
|
||
|
printf("OK\r\n");
|
||
|
break;
|
||
|
// case 'P':
|
||
|
// co_printf("VAL: 0x%02x.\r\n", *(uint8_t *)(MODEM_BASE + ascii_strn2val((const char *)&data[0], 16, 2)));
|
||
|
// break;
|
||
|
// case 'Q':
|
||
|
// *(uint8_t *)(MODEM_BASE + ascii_strn2val((const char *)&data[0], 16, 2)) = ascii_strn2val((const char *)&data[3], 16, 2);
|
||
|
// co_printf("OK\r\n");
|
||
|
// break;
|
||
|
// case 'S':
|
||
|
// co_printf("VAL: 0x%02x.\r\n", frspim_rd(FR_SPI_RF_COB_CHAN, ascii_strn2val((const char *)&data[0], 16, 2), 1));
|
||
|
// break;
|
||
|
// case 'T':
|
||
|
// frspim_wr(FR_SPI_RF_COB_CHAN, ascii_strn2val((const char *)&data[0], 16, 2), 1, ascii_strn2val((const char *)&data[3], 16, 2));
|
||
|
// co_printf("OK\r\n");
|
||
|
// break;
|
||
|
case 'U':
|
||
|
{
|
||
|
uint32_t *ptr = (uint32_t *)(ascii_strn2val((const char *)&data[0], 16, 8) & (~3));
|
||
|
uint8_t count = ascii_strn2val((const char *)&data[9], 16, 2);
|
||
|
uint32_t *start = (uint32_t *)((uint32_t)ptr & (~0x0f));
|
||
|
for(uint8_t i=0; i<count;) {
|
||
|
if(((uint32_t)start & 0x0c) == 0) {
|
||
|
printf("0x%08x: ", (uint32_t)start);
|
||
|
}
|
||
|
if(start < ptr) {
|
||
|
printf(" ");
|
||
|
}
|
||
|
else {
|
||
|
i++;
|
||
|
printf("%08x", *start);
|
||
|
}
|
||
|
if(((uint32_t)start & 0x0c) == 0x0c) {
|
||
|
printf("\r\n");
|
||
|
}
|
||
|
else {
|
||
|
printf(" ");
|
||
|
}
|
||
|
start++;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case 'V':
|
||
|
flash_erase(QSPI0, ascii_strn2val((const char *)&data[0], 16, 8), ascii_strn2val((const char *)&data[9], 16, 8));
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void app_at_recv_cmd_B(uint8_t sub_cmd, uint8_t *data)
|
||
|
{
|
||
|
struct gap_ble_addr peer_addr;
|
||
|
BD_ADDR addr;
|
||
|
|
||
|
switch(sub_cmd) {
|
||
|
case 'A':
|
||
|
// AT#BA00
|
||
|
//app_ble_advertising_start(ascii_strn2val((const char *)&data[0], 16, 2));
|
||
|
break;
|
||
|
case 'B':
|
||
|
// AT#BB01
|
||
|
//app_ble_advertising_stop(ascii_strn2val((const char *)&data[0], 16, 2));
|
||
|
break;
|
||
|
case 'C':
|
||
|
//app_ble_scan_start();
|
||
|
break;
|
||
|
case 'D':
|
||
|
//app_ble_scan_stop();
|
||
|
break;
|
||
|
case 'E':
|
||
|
// AT#BE0123456789ab_01
|
||
|
peer_addr.addr.addr[5] = ascii_strn2val((const char *)&data[0], 16, 2);
|
||
|
peer_addr.addr.addr[4] = ascii_strn2val((const char *)&data[2], 16, 2);
|
||
|
peer_addr.addr.addr[3] = ascii_strn2val((const char *)&data[4], 16, 2);
|
||
|
peer_addr.addr.addr[2] = ascii_strn2val((const char *)&data[6], 16, 2);
|
||
|
peer_addr.addr.addr[1] = ascii_strn2val((const char *)&data[8], 16, 2);
|
||
|
peer_addr.addr.addr[0] = ascii_strn2val((const char *)&data[10], 16, 2);
|
||
|
peer_addr.addr_type = ascii_strn2val((const char *)&data[13], 16, 2);
|
||
|
//app_ble_conn_start(&peer_addr);
|
||
|
break;
|
||
|
case 'F':
|
||
|
//app_ble_conn_stop();
|
||
|
break;
|
||
|
case 'H':
|
||
|
ME_Inquiry(BT_IAC_GIAC, 5, 5);
|
||
|
break;
|
||
|
case 'I':
|
||
|
ME_CancelInquiry();
|
||
|
break;
|
||
|
case 'J':
|
||
|
{
|
||
|
BtStatus status;
|
||
|
addr.A[0] = ascii_strn2val((const char*)&data[0],16,2);
|
||
|
addr.A[1] = ascii_strn2val((const char*)&data[2],16,2);
|
||
|
addr.A[2] = ascii_strn2val((const char*)&data[4],16,2);
|
||
|
addr.A[3] = ascii_strn2val((const char*)&data[6],16,2);
|
||
|
addr.A[4] = ascii_strn2val((const char*)&data[8],16,2);
|
||
|
addr.A[5] = ascii_strn2val((const char*)&data[10],16,2);
|
||
|
|
||
|
//status = HFG_CreateServiceLink(&hfg_channel[0], &addr);
|
||
|
|
||
|
if (status == BT_STATUS_PENDING) {
|
||
|
printf("Opening Channel...\r\n");
|
||
|
} else {
|
||
|
printf("Could not open channel, status: %d\r\n", status);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case 'O':
|
||
|
// {
|
||
|
// uint8_t battery_level[15] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
|
||
|
// struct gatt_send_event ntf[6];
|
||
|
// uint8_t i=0;
|
||
|
// for(i=0;i<6;i++){
|
||
|
// ntf[i].conidx = 0;
|
||
|
// ntf[i].svc_id = svc_id;
|
||
|
// ntf[i].att_idx = 2;
|
||
|
// ntf[i].data_len = 15;
|
||
|
// ntf[i].p_data = &battery_level[0];
|
||
|
// gatt_notification(&ntf[i]);
|
||
|
// }
|
||
|
// }
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
printf("OK\r\n");
|
||
|
}
|
||
|
|
||
|
static void app_at_recv_cmd_D(uint8_t sub_cmd, uint8_t *data)
|
||
|
{
|
||
|
switch(sub_cmd) {
|
||
|
case 'A':
|
||
|
flash_erase(QSPI0, ascii_strn2val((const char*)&data[0],16,8), 0x1000);
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void app_at_cmd_recv_handler(uint8_t *data, uint16_t length)
|
||
|
{
|
||
|
switch(data[0])
|
||
|
{
|
||
|
case 'A':
|
||
|
app_at_recv_cmd_A(data[1], &data[2]);
|
||
|
break;
|
||
|
case 'B':
|
||
|
app_at_recv_cmd_B(data[1], &data[2]);
|
||
|
break;
|
||
|
case 'D':
|
||
|
app_at_recv_cmd_D(data[1], &data[2]);
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void app_at_recv_c(uint8_t c)
|
||
|
{
|
||
|
switch(at_recv_state)
|
||
|
{
|
||
|
case 0:
|
||
|
if(c == 'A')
|
||
|
{
|
||
|
at_recv_state++;
|
||
|
}
|
||
|
break;
|
||
|
case 1:
|
||
|
if(c == 'T')
|
||
|
at_recv_state++;
|
||
|
else
|
||
|
at_recv_state = 0;
|
||
|
break;
|
||
|
case 2:
|
||
|
if(c == '#')
|
||
|
at_recv_state++;
|
||
|
else
|
||
|
at_recv_state = 0;
|
||
|
break;
|
||
|
case 3:
|
||
|
at_recv_buffer[at_recv_index++] = c;
|
||
|
if((c == '\n')
|
||
|
||(at_recv_index >= AT_RECV_MAX_LEN))
|
||
|
{
|
||
|
struct app_task_event *event;
|
||
|
event = app_task_event_alloc(APP_TASK_EVENT_AT_CMD, at_recv_index, false);
|
||
|
if(event) {
|
||
|
memcpy(event->param, at_recv_buffer, at_recv_index);
|
||
|
app_task_event_post(event, false);
|
||
|
}
|
||
|
at_recv_state = 0;
|
||
|
at_recv_index = 0;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void app_at_rx_done(struct __UART_HandleTypeDef *handle)
|
||
|
{
|
||
|
app_at_recv_c(app_at_recv_char);
|
||
|
if (handle) {
|
||
|
uart_receive_IT(handle, &app_at_recv_char, 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void app_at_init(struct __UART_HandleTypeDef *handle)
|
||
|
{
|
||
|
uart_receive_IT(handle, &app_at_recv_char, 1);
|
||
|
}
|