380 lines
8.9 KiB
C
380 lines
8.9 KiB
C
|
/***************************************************************
|
||
|
*
|
||
|
* OpenBeacon.org - main file for OpenBeacon USB II Bluetooth
|
||
|
*
|
||
|
* Copyright 2010 Milosch Meriac <meriac@openbeacon.de>
|
||
|
*
|
||
|
***************************************************************
|
||
|
|
||
|
This program is free software; you can redistribute it and/or modify
|
||
|
it under the terms of the GNU General Public License as published by
|
||
|
the Free Software Foundation; version 2.
|
||
|
|
||
|
This program is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License along
|
||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||
|
|
||
|
*/
|
||
|
#include <openbeacon.h>
|
||
|
#include "pin.h"
|
||
|
#include "hid.h"
|
||
|
#include "spi.h"
|
||
|
#include "iap.h"
|
||
|
#include "pmu.h"
|
||
|
#include "crc16.h"
|
||
|
#include "xxtea.h"
|
||
|
#include "bluetooth.h"
|
||
|
#include "storage.h"
|
||
|
#include "nRF_API.h"
|
||
|
#include "nRF_CMD.h"
|
||
|
#include "openbeacon-proto.h"
|
||
|
|
||
|
/* OpenBeacon packet */
|
||
|
static TBeaconEnvelope g_Beacon;
|
||
|
|
||
|
/* Default TEA encryption key of the tag - MUST CHANGE ! */
|
||
|
static const uint32_t xxtea_key[4] =
|
||
|
{ 0x00112233, 0x44556677, 0x8899AABB, 0xCCDDEEFF };
|
||
|
|
||
|
/* set nRF24L01 broadcast mac */
|
||
|
static const unsigned char broadcast_mac[NRF_MAX_MAC_SIZE] =
|
||
|
{ 1, 2, 3, 2, 1 };
|
||
|
|
||
|
/* device UUID */
|
||
|
static uint16_t tag_id;
|
||
|
static TDeviceUID device_uuid;
|
||
|
|
||
|
#if (USB_HID_IN_REPORT_SIZE>0)||(USB_HID_OUT_REPORT_SIZE>0)
|
||
|
static uint8_t hid_buffer[USB_HID_IN_REPORT_SIZE];
|
||
|
|
||
|
void
|
||
|
GetInReport (uint8_t * src, uint32_t length)
|
||
|
{
|
||
|
(void) src;
|
||
|
(void) length;
|
||
|
|
||
|
if (length > USB_HID_IN_REPORT_SIZE)
|
||
|
length = USB_HID_IN_REPORT_SIZE;
|
||
|
|
||
|
memcpy (src, hid_buffer, length);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
SetOutReport (uint8_t * dst, uint32_t length)
|
||
|
{
|
||
|
(void) dst;
|
||
|
(void) length;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
static void show_version(void)
|
||
|
{
|
||
|
debug_printf(" * Tag ID: %i\n", (uint16_t) device_uuid[3]);
|
||
|
debug_printf(" * Device UID: %08X:%08X:%08X:%08X\n", device_uuid[0],
|
||
|
device_uuid[1], device_uuid[2], device_uuid[3]);
|
||
|
debug_printf(" * free heap memory: %i bytes\n",xPortGetFreeHeapSize());
|
||
|
}
|
||
|
|
||
|
void main_menue(uint8_t cmd)
|
||
|
{
|
||
|
/* ignore non-printable characters */
|
||
|
if (cmd <= ' ')
|
||
|
return;
|
||
|
/* show key pressed */
|
||
|
debug_printf("%c\n", cmd);
|
||
|
/* map lower case to upper case */
|
||
|
if (cmd > 'a' && cmd < 'z')
|
||
|
cmd -= ('a' - 'A');
|
||
|
|
||
|
switch (cmd)
|
||
|
{
|
||
|
case '?':
|
||
|
case 'H':
|
||
|
debug_printf("\n"
|
||
|
" *****************************************************\n"
|
||
|
" * OpenBeacon USB II - Bluetooth Console *\n"
|
||
|
" * (C) 2010 Milosch Meriac <meriac@openbeacon.de> *\n"
|
||
|
" *****************************************************\n"
|
||
|
" * H,? - this help screen\n"
|
||
|
#ifdef MENUE_ALLOW_ISP_REBOOT
|
||
|
" * P - invoke ISP programming mode\n"
|
||
|
#endif
|
||
|
" * S - show device status\n"
|
||
|
" * R - OpenBeacon nRF24L01 register dump\n"
|
||
|
" *****************************************************\n"
|
||
|
"\n");
|
||
|
break;
|
||
|
#ifdef MENUE_ALLOW_ISP_REBOOT
|
||
|
case 'P':
|
||
|
debug_printf ("\nRebooting...");
|
||
|
iap_invoke_isp ();
|
||
|
break;
|
||
|
#endif
|
||
|
case 'R':
|
||
|
nRFCMD_RegisterDump();
|
||
|
break;
|
||
|
case 'S':
|
||
|
debug_printf("\n"
|
||
|
" *****************************************************\n"
|
||
|
" * OpenBeacon Status Information *\n"
|
||
|
" *****************************************************\n");
|
||
|
show_version();
|
||
|
spi_status();
|
||
|
nRFCMD_Status();
|
||
|
// pmu_status ();
|
||
|
#if (DISK_SIZE>0)
|
||
|
storage_status();
|
||
|
#endif
|
||
|
nRFCMD_Status();
|
||
|
debug_printf(" *****************************************************\n"
|
||
|
"\n");
|
||
|
break;
|
||
|
default:
|
||
|
debug_printf("Unknown command '%c' - please press 'H' for help \n", cmd);
|
||
|
}
|
||
|
debug_printf("\n# ");
|
||
|
}
|
||
|
|
||
|
static
|
||
|
void nRF_tx(uint8_t power)
|
||
|
{
|
||
|
/* update crc */
|
||
|
g_Beacon.pkt.crc = htons(crc16(g_Beacon.byte, sizeof(g_Beacon)
|
||
|
- sizeof(uint16_t)));
|
||
|
/* encrypt data */
|
||
|
xxtea_encode(g_Beacon.block, XXTEA_BLOCK_COUNT, xxtea_key);
|
||
|
|
||
|
pin_led(GPIO_LED0);
|
||
|
|
||
|
/* update power pin */
|
||
|
nRFCMD_Power(power & 0x4);
|
||
|
|
||
|
/* disable RX mode */
|
||
|
nRFCMD_CE(0);
|
||
|
vTaskDelay(5 / portTICK_RATE_MS);
|
||
|
|
||
|
/* switch to TX mode */
|
||
|
nRFAPI_SetRxMode(0);
|
||
|
|
||
|
/* set TX power */
|
||
|
nRFAPI_SetTxPower(power & 0x3);
|
||
|
|
||
|
/* upload data to nRF24L01 */
|
||
|
nRFAPI_TX(g_Beacon.byte, sizeof(g_Beacon));
|
||
|
|
||
|
/* transmit data */
|
||
|
nRFCMD_CE(1);
|
||
|
|
||
|
/* wait until packet is transmitted */
|
||
|
vTaskDelay(2 / portTICK_RATE_MS);
|
||
|
|
||
|
/* switch to RX mode again */
|
||
|
nRFAPI_SetRxMode(1);
|
||
|
|
||
|
pin_led(GPIO_LEDS_OFF);
|
||
|
|
||
|
if (power & 0x4)
|
||
|
nRFCMD_Power(0);
|
||
|
}
|
||
|
|
||
|
static
|
||
|
void nRF_Task(void *pvParameters)
|
||
|
{
|
||
|
int t, active;
|
||
|
uint8_t strength, status;
|
||
|
uint16_t crc;
|
||
|
uint32_t seq, oid;
|
||
|
portTickType LastUpdateTicks, Ticks;
|
||
|
|
||
|
(void) pvParameters;
|
||
|
|
||
|
/* Initialize OpenBeacon nRF24L01 interface */
|
||
|
if (!nRFAPI_Init(81, broadcast_mac, sizeof(broadcast_mac), 0))
|
||
|
/* bail out if can't initialize */
|
||
|
// for (;;)
|
||
|
{
|
||
|
pin_led(GPIO_LED0 | GPIO_LED1);
|
||
|
vTaskDelay(500 / portTICK_RATE_MS);
|
||
|
|
||
|
pin_led(GPIO_LEDS_OFF);
|
||
|
vTaskDelay(500 / portTICK_RATE_MS);
|
||
|
}
|
||
|
|
||
|
/* blink as a sign of boot to detect crashes */
|
||
|
for (t = 0; t < 20; t++)
|
||
|
{
|
||
|
pin_led(GPIO_LED0);
|
||
|
vTaskDelay(50 / portTICK_RATE_MS);
|
||
|
|
||
|
pin_led(GPIO_LEDS_OFF);
|
||
|
vTaskDelay(50 / portTICK_RATE_MS);
|
||
|
}
|
||
|
|
||
|
nRFAPI_SetRxMode(1);
|
||
|
nRFCMD_CE(1);
|
||
|
|
||
|
LastUpdateTicks = xTaskGetTickCount();
|
||
|
|
||
|
/* main loop */
|
||
|
active = 0;
|
||
|
seq = t = 0;
|
||
|
UARTCount = 0;
|
||
|
while (1)
|
||
|
{
|
||
|
/* turn off after button press */
|
||
|
if (!pin_button0())
|
||
|
{
|
||
|
pin_mode_pmu(0);
|
||
|
pmu_off(0);
|
||
|
}
|
||
|
|
||
|
if (nRFCMD_WaitRx(10 / portTICK_RATE_MS))
|
||
|
do
|
||
|
{
|
||
|
// read packet from nRF chip
|
||
|
nRFCMD_RegReadBuf(RD_RX_PLOAD, g_Beacon.byte, sizeof(g_Beacon));
|
||
|
|
||
|
// adjust byte order and decode
|
||
|
xxtea_decode(g_Beacon.block, XXTEA_BLOCK_COUNT, xxtea_key);
|
||
|
|
||
|
// verify the CRC checksum
|
||
|
crc = crc16(g_Beacon.byte, sizeof(g_Beacon) - sizeof(uint16_t));
|
||
|
|
||
|
if (ntohs (g_Beacon.pkt.crc) == crc)
|
||
|
{
|
||
|
pin_led(GPIO_LED1);
|
||
|
|
||
|
oid = ntohs (g_Beacon.pkt.oid);
|
||
|
if (((g_Beacon.pkt.flags & RFBFLAGS_SENSOR) > 0) && active)
|
||
|
debug_printf("BUTTON: %i\n", oid);
|
||
|
|
||
|
switch (g_Beacon.pkt.proto)
|
||
|
{
|
||
|
case RFBPROTO_READER_ANNOUNCE:
|
||
|
strength = g_Beacon.pkt.p.reader_announce.strength;
|
||
|
break;
|
||
|
|
||
|
case RFBPROTO_BEACONTRACKER:
|
||
|
strength = g_Beacon.pkt.p.tracker.strength;
|
||
|
if (active)
|
||
|
debug_printf(" R: %04i={%i,0x%08X}\n", (int) oid,
|
||
|
(int) strength,
|
||
|
ntohl (g_Beacon.pkt.p.tracker.seq));
|
||
|
break;
|
||
|
|
||
|
case RFBPROTO_PROXREPORT:
|
||
|
strength = 3;
|
||
|
if (active)
|
||
|
debug_printf(" P: %04i={%i,0x%04X}\n", (int) oid,
|
||
|
(int) strength,
|
||
|
(int) ntohs (g_Beacon.pkt.p.prox.seq));
|
||
|
for (t = 0; t < PROX_MAX; t++)
|
||
|
{
|
||
|
crc = (ntohs (g_Beacon.pkt.p.prox.oid_prox[t]));
|
||
|
if (crc && active)
|
||
|
debug_printf("PX: %04i={%04i,%i,%i}\n",
|
||
|
(int) oid, (int) ((crc >> 0) & 0x7FF),
|
||
|
(int) ((crc >> 14) & 0x3), (int) ((crc
|
||
|
>> 11) & 0x7));
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
strength = 0xFF;
|
||
|
if (active)
|
||
|
debug_printf("Unknown Protocol: %i\n",
|
||
|
(int) g_Beacon.pkt.proto);
|
||
|
}
|
||
|
|
||
|
if (strength < 0xFF)
|
||
|
{
|
||
|
/* do something with the data */
|
||
|
}
|
||
|
pin_led(GPIO_LEDS_OFF);
|
||
|
}
|
||
|
status = nRFAPI_GetFifoStatus();
|
||
|
} while ((status & FIFO_RX_EMPTY) == 0);
|
||
|
|
||
|
nRFAPI_ClearIRQ(MASK_IRQ_FLAGS);
|
||
|
|
||
|
// update regularly
|
||
|
if (((Ticks = xTaskGetTickCount()) - LastUpdateTicks)
|
||
|
> UPDATE_INTERVAL_MS)
|
||
|
{
|
||
|
LastUpdateTicks = Ticks;
|
||
|
|
||
|
/* setup tracking packet */
|
||
|
bzero(&g_Beacon, sizeof(g_Beacon));
|
||
|
g_Beacon.pkt.oid = ntohs ((uint16_t)device_uuid[3]);
|
||
|
g_Beacon.pkt.proto = RFBPROTO_BEACONTRACKER;
|
||
|
g_Beacon.pkt.p.tracker.strength = seq % 8;
|
||
|
g_Beacon.pkt.p.tracker.seq = htonl(seq++);
|
||
|
|
||
|
/* send away packet */
|
||
|
nRF_tx(g_Beacon.pkt.p.tracker.strength);
|
||
|
}
|
||
|
|
||
|
if (UARTCount)
|
||
|
{
|
||
|
/* blink LED1 upon Bluetooth command */
|
||
|
pin_led(GPIO_LED1);
|
||
|
|
||
|
/* show help screen upon Bluetooth connect */
|
||
|
if (!active)
|
||
|
{
|
||
|
active = 1;
|
||
|
debug_printf("press 'H' for help...\n# ");
|
||
|
}
|
||
|
else
|
||
|
/* execute menu command with last character received */
|
||
|
main_menue(UARTBuffer[UARTCount - 1]);
|
||
|
|
||
|
/* LED1 off again */
|
||
|
pin_led(GPIO_LEDS_OFF);
|
||
|
|
||
|
/* clear UART buffer */
|
||
|
UARTCount = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int main(void)
|
||
|
{
|
||
|
volatile int i;
|
||
|
/* wait on boot - debounce */
|
||
|
for (i = 0; i < 2000000; i++)
|
||
|
;
|
||
|
/* initialize pins */
|
||
|
pin_init();
|
||
|
/* Init SPI */
|
||
|
spi_init();
|
||
|
/* Init Storage */
|
||
|
#ifdef USB_DISK_SUPPORT
|
||
|
storage_init();
|
||
|
#endif
|
||
|
/* Init USB HID interface */
|
||
|
#if (USB_HID_IN_REPORT_SIZE>0)||(USB_HID_OUT_REPORT_SIZE>0)
|
||
|
hid_init ();
|
||
|
#error hid
|
||
|
#endif
|
||
|
/* power management init */
|
||
|
pmu_init();
|
||
|
/* read device UUID */
|
||
|
bzero(&device_uuid, sizeof(device_uuid));
|
||
|
iap_read_uid(&device_uuid);
|
||
|
tag_id = crc16((uint8_t*) &device_uuid, sizeof(device_uuid));
|
||
|
|
||
|
xTaskCreate(nRF_Task, (const signed char*) "nRF", TASK_NRF_STACK_SIZE,
|
||
|
NULL, TASK_NRF_PRIORITY, NULL);
|
||
|
|
||
|
/* Start the tasks running. */
|
||
|
vTaskStartScheduler();
|
||
|
|
||
|
return 0;
|
||
|
}
|