large update to sleep clock code and simplicti

* implemented a nice send and receive framework.
  Code in simplic_tx_only loop can request receive window.
  In this window the recv of rf will be active and a R2R
  (ready to receive) package is sent. By then the AP should
  have filled outgoing buffer and a received handler is called.

* made the sleep clock use initialisation.
  When starting the sleep clock, a new session id is requested that is
  sent with every package (3 bits), together with the couter (5 bits).
  When initialized a hash of the hardware address is sent so the clock
  can detect which watch is running. Also a currently unused program id
  can be sent to select the watch program later on.
fertito
Daniel Poelzleithner 13 years ago
parent 1bfa252567
commit fd3ff268c8

@ -76,6 +76,10 @@
#ifdef CONFIG_EGGTIMER
#include "eggtimer.h"
#endif
#ifdef CONFIG_PHASE_CLOCK
#include "phase_clock.h"
#endif
// *************************************************************************************************
@ -134,8 +138,6 @@ extern u8 ps_write_register(u8 address, u8 data);
// *************************************************************************************************
int main(void)
{
volatile u8 ps;
// Init MCU
init_application();
@ -374,6 +376,11 @@ void init_global_variables(void)
reset_eggtimer();
#endif
#ifdef CONFIG_PHASE_CLOCK
// default program
sPhase.program = 0;
#endif
// Reset SimpliciTI stack
reset_rf();

@ -143,12 +143,16 @@ void sx_phase(u8 line)
// Exit if battery voltage is too low for radio operation
if (sys.flag.low_battery) return;
sPhase.session = 0;
sPhase.out_nr = 0;
sPhase.data_nr = 0;
// Exit if BlueRobin stack is active
#ifndef ELIMINATE_BLUEROBIN
if (is_bluerobin()) return;
#endif
// Start SimpliciTI in tx only mode
start_simpliciti_tx_only(SIMPLICITI_PHASE_CLOCK);
start_simpliciti_tx_only(SIMPLICITI_PHASE_CLOCK_START);
}
u8 diff(u8 x1, u8 x2) {
@ -169,31 +173,23 @@ u8 diff(u8 x1, u8 x2) {
// @return none
// *************************************************************************************************
void phase_clock_calcpoint() {
u16 x,y,z,res = 0;
// char *str;
u8 i = 0;
for(i=1;i<SLEEP_BUFFER;i++) {
x += diff(sPhase.data[i-1][0], sPhase.data[i][0]);
y += diff(sPhase.data[i-1][1], sPhase.data[i][1]);
z += diff(sPhase.data[i-1][2], sPhase.data[i][2]);
}
// can't overflow when SLEEP_BUFFER is not larger then 171
res = x + y + z;
// Convert day to string
// str = itoa(x, 2, 0);
// display_chars(LCD_SEG_L2_5_0, str, SEG_ON);
//display_chars(LCD_SEG_L2_5_0, (u8 *)" SLEEP", SEG_ON);
sPhase.out[sPhase.out_nr] = res;
sPhase.out_nr++;
//sPhase.out[1] = res & 0xFF;
//sPhase.out[0] = (res >> 8) & 0xFF;
//memcpy(&sPhase.out + sPhase.out_nr, &res, sizeof(u16));
// reset stack index
//sPhase.out_nr += 2;
sPhase.data_nr = 0;
u16 x,y,z,res;
x = y = z = res = 0;
u8 i = 0;
for(i=1;i<SLEEP_DATA_BUFFER;i++) {
x += diff(sPhase.data[i-1][0], sPhase.data[i][0]);
y += diff(sPhase.data[i-1][1], sPhase.data[i][1]);
z += diff(sPhase.data[i-1][2], sPhase.data[i][2]);
}
// can't overflow when SLEEP_BUFFER is not larger then 171
res = x + y + z;
// set the result into the out buffer
sPhase.out[sPhase.out_nr] = res;
sPhase.out_nr++;
sPhase.data_nr = 0;
}

@ -81,7 +81,13 @@ typedef enum
// collect n samples of data before tranmitting (saves energy)
#define SLEEP_BUFFER 30
// n bits in the couter byte which mark the session
#define SLEEP_RF_ID_BIT_LENGHT 3
// 5 bits + 1 so counter%SLEEP_MAX_PACKET_COUNTER does not overflow
#define SLEEP_MAX_PACKET_COUNTER 32
#define SLEEP_DATA_BUFFER 30
#define SLEEP_OUT_BUFFER 10
// how often should a the clock be searched again
@ -113,14 +119,13 @@ struct SPhase
// SIMPLICITI_OFF, SIMPLICITI_ACCELERATION, SIMPLICITI_BUTTONS
simpliciti_mode_t mode;
// clock to which the watch is paired
u16 clock_id;
// Timeout until clock will be searched again
u16 timeout;
// current session id
u8 session;
// sleep program to start
u8 program;
// collected data
//
u8 data[SLEEP_BUFFER][3];
u8 data[SLEEP_DATA_BUFFER][3];
u8 data_nr;
//u8 out[PHASE_CLOCK_BUFFER];
u16 out[SLEEP_OUT_BUFFER];

@ -223,12 +223,11 @@ void start_simpliciti_tx_only(simpliciti_mode_t mode)
start_as = 1;
}
#ifdef CONFIG_PHASE_CLOCK
else if (mode == SIMPLICITI_PHASE_CLOCK)
else if (mode == SIMPLICITI_PHASE_CLOCK_START)
{
simpliciti_data[0] = SIMPLICITI_PHASE_CLOCK_EVENTS;
simpliciti_data[0] = SIMPLICITI_PHASE_CLOCK_START_EVENTS;
start_as = 1;
display_symbol(LCD_ICON_RECORD, SEG_ON_BLINK_ON);
}
#endif
else
@ -290,7 +289,7 @@ void start_simpliciti_tx_only(simpliciti_mode_t mode)
display_symbol(LCD_ICON_BEEPER3, SEG_OFF_BLINK_OFF);
#ifdef CONFIG_PHASE_CLOCK
if (mode == SIMPLICITI_PHASE_CLOCK)
if (mode == SIMPLICITI_PHASE_CLOCK || mode == SIMPLICITI_PHASE_CLOCK_START)
{
display_symbol(LCD_ICON_RECORD, SEG_OFF_BLINK_OFF);
@ -380,8 +379,7 @@ void simpliciti_get_ed_data_callback(void)
static u8 packet_counter = 0;
u8 i;
u16 res;
char *str;
WDTCTL = WDTPW + WDTHOLD;
if (sRFsmpl.mode == SIMPLICITI_ACCELERATION)
{
// Wait for next sample
@ -412,11 +410,32 @@ void simpliciti_get_ed_data_callback(void)
}
}
#ifdef CONFIG_PHASE_CLOCK
} else if (sRFsmpl.mode == SIMPLICITI_PHASE_CLOCK)
} else if (sRFsmpl.mode == SIMPLICITI_PHASE_CLOCK_START)
{
/* Initialisation phase. Get a Session id and send the
program wanted */
if(packet_counter == 30) {
simpliciti_flag |= SIMPLICITI_TRIGGER_STOP;
packet_counter = 0;
return;
}
display_symbol(LCD_ICON_BEEPER1, SEG_ON_BLINK_ON);
display_symbol(LCD_ICON_BEEPER2, SEG_ON_BLINK_ON);
// send hw address so he recognices us and we will get a session id
simpliciti_data[0] = SIMPLICITI_PHASE_CLOCK_START_EVENTS;
simpliciti_data[1] = simpliciti_ed_address[0] ^ simpliciti_ed_address[1];
simpliciti_data[2] = simpliciti_ed_address[2] ^ simpliciti_ed_address[3];
// FIXME: TODO set program
simpliciti_data[3] = sPhase.program;
simpliciti_flag |= SIMPLICITI_TRIGGER_SEND_DATA | SIMPLICITI_TRIGGER_RECEIVE_DATA;
packet_counter ++;
}
else if (sRFsmpl.mode == SIMPLICITI_PHASE_CLOCK)
{
//display_symbol(LCD_ICON_BEEPER1, SEG_ON_BLINK_ON);
//display_symbol(LCD_ICON_BEEPER1, SEG_ON_BLINK_ON);
// Wait for next sample
display_symbol(LCD_ICON_RECORD, SEG_ON);
display_symbol(LCD_ICON_RECORD, SEG_ON);
Timer0_A4_Delay(CONV_MS_TO_TICKS(20));
// Read from sensor if DRDY pin indicates new data (set in PORT2 ISR)
if (request.flag.acceleration_measurement && ((AS_INT_IN & AS_INT_PIN) == AS_INT_PIN))
@ -428,66 +447,47 @@ void simpliciti_get_ed_data_callback(void)
as_get_data(sAccel.xyz);
// push messured data onto the stack
if (sPhase.data_nr > SLEEP_BUFFER-1) {
phase_clock_calcpoint();
display_symbol(LCD_ICON_BEEPER1, SEG_OFF);
display_symbol(LCD_ICON_BEEPER2, SEG_OFF);
display_symbol(LCD_ICON_BEEPER3, SEG_OFF);
/*simpliciti_data[1] = sPhase.out[0];
simpliciti_data[2] = sPhase.out[1];
simpliciti_data[3] = packet_counter++; //8>>sPhase.out[1]&&0xFF;
simpliciti_payload_length = 4;
simpliciti_flag |= SIMPLICITI_TRIGGER_SEND_DATA;
*/
} else {
// copy current value onto the stack
//memcpy(&sPhase.data[sPhase.data_nr][0], &sAccel.xyz, sizeof(u8)*3);
sPhase.data[sPhase.data_nr][0] = sAccel.xyz[0];
if (sPhase.data_nr > SLEEP_DATA_BUFFER-1) {
phase_clock_calcpoint();
display_symbol(LCD_ICON_BEEPER1, SEG_OFF);
display_symbol(LCD_ICON_BEEPER2, SEG_OFF);
display_symbol(LCD_ICON_BEEPER3, SEG_OFF);
} else {
// copy current value onto the stack
//memcpy(&sPhase.data[sPhase.data_nr][0], &sAccel.xyz, sizeof(u8)*3);
sPhase.data[sPhase.data_nr][0] = sAccel.xyz[0];
sPhase.data[sPhase.data_nr][1] = sAccel.xyz[1];
sPhase.data[sPhase.data_nr][2] = sAccel.xyz[2];
sPhase.data[sPhase.data_nr][2] = sAccel.xyz[2];
//simpliciti_data[3] = sAccel.xyz[2];
sPhase.data_nr++;
}
sPhase.data_nr++;
}
//str = itoa(accel_data, 3, 0);
if (sPhase.out_nr > SLEEP_OUT_BUFFER-1)
if ((sPhase.out_nr > SLEEP_OUT_BUFFER-1))
{
// Reset counter
sPhase.out_nr = 0;
// copy out buffer into the simplicti out buffer skip prefix
//memcpy(&simpliciti_data+sizeof(u8), &sPhase.out, PHASE_CLOCK_SEND_LENGTH);
for(i=0; i < SLEEP_OUT_BUFFER; i++) {
//if (((2**17)-1)
// FIXME: overflow detection ?
res += sPhase.out[i];
}
simpliciti_data[3] = packet_counter++;
simpliciti_data[2] = res & 0xFF;
simpliciti_data[1] = (res >> 8) & 0xFF;
simpliciti_payload_length = 4;
//simpliciti_data[0] = SIMPLICITI_PHASE_CLOCK_EVENTS;
// Trigger packet sending
// str = itoa(simpliciti_data[2], 2, 0);
// clear_line(LINE1);
// display_chars(LCD_SEG_L2_5_0, str, SEG_ON);
// Force full display update
//display.flag.full_update = 1;
//str = itoa(simpliciti_data[1], 2, 0);
// display_chars(LCD_SEG_L2_5_2, str, SEG_ON);
//display_chars(LCD_SEG_L1_3_0, str, SEG_ON);
//str = itoa(simpliciti_data[2], 2, 0);
//display_chars(LCD_SEG_L1_1_0, str, SEG_ON);
//display_symbol(LCD_ICON_RECORD, SEG_ON);
simpliciti_flag |= SIMPLICITI_TRIGGER_SEND_DATA;
display_symbol(LCD_ICON_BEEPER1, SEG_ON);
display_symbol(LCD_ICON_BEEPER2, SEG_ON);
display_symbol(LCD_ICON_BEEPER3, SEG_ON);
res = 0;
for(i=0; i < SLEEP_OUT_BUFFER; i++) {
//if (((2**17)-1))
// FIXME: overflow detection ?
res += sPhase.out[i];
}
packet_counter = (packet_counter+1)%SLEEP_MAX_PACKET_COUNTER;
simpliciti_data[3] = (sPhase.session << (8-SLEEP_RF_ID_BIT_LENGHT)) | packet_counter;
simpliciti_data[2] = res & 0xFF;
simpliciti_data[1] = (res >> 8) & 0xFF;
simpliciti_data[0] = SIMPLICITI_PHASE_CLOCK_EVENTS;
simpliciti_payload_length = 4;
display_symbol(LCD_ICON_BEEPER1, SEG_ON_BLINK_ON);
display_symbol(LCD_ICON_BEEPER2, SEG_ON_BLINK_ON);
display_symbol(LCD_ICON_BEEPER3, SEG_ON_BLINK_ON);
simpliciti_flag |= SIMPLICITI_TRIGGER_SEND_DATA;
}
@ -538,6 +538,27 @@ void simpliciti_get_ed_data_callback(void)
}
}
// *************************************************************************************************
// @fn simpliciti_get_rvc_callback
// @brief Callback when data wher received
// @param u8 lenght
// @return none
// *************************************************************************************************
int simpliciti_get_rvc_callback(u8 len)
{
switch (simpliciti_data[0])
{
case SIMPLICITI_PHASE_CLOCK_START_RESPONSE: // Send watch parameters
sPhase.session = simpliciti_data[1];
sRFsmpl.mode = SIMPLICITI_PHASE_CLOCK;
simpliciti_data[0] = 0x00;
simpliciti_data[1] = 0x00;
simpliciti_data[2] = 0x00;
return 1;
}
return 0;
}
// *************************************************************************************************
// @fn start_simpliciti_sync

@ -52,7 +52,6 @@ extern void display_sync(u8 line, u8 update);
extern void send_smpl_data(u16 data);
extern u8 is_rf(void);
// *************************************************************************************************
// Defines section
@ -64,6 +63,7 @@ typedef enum
SIMPLICITI_BUTTONS, // Transmitting button events
SIMPLICITI_SYNC, // Syncing
#ifdef CONFIG_PHASE_CLOCK
SIMPLICITI_PHASE_CLOCK_START, // Start new phase
SIMPLICITI_PHASE_CLOCK, // Phase Clock is running
#endif
} simpliciti_mode_t;
@ -77,9 +77,13 @@ typedef enum
#define SIMPLICITI_BUTTON_UP (0x30)
// SimpliciTI mode flag
#define SIMPLICITI_MOUSE_EVENTS (0x01)
#define SIMPLICITI_KEY_EVENTS (0x02)
#define SIMPLICITI_PHASE_CLOCK_EVENTS (0x03)
#define SIMPLICITI_MOUSE_EVENTS (0x01)
#define SIMPLICITI_KEY_EVENTS (0x02)
#define SIMPLICITI_PHASE_CLOCK_EVENTS (0x03)
#define SIMPLICITI_PHASE_CLOCK_START_EVENTS (0x04)
#define SIMPLICITI_PHASE_CLOCK_START_RESPONSE (0x54)
// *************************************************************************************************
// Global Variable section
@ -98,4 +102,7 @@ extern unsigned char simpliciti_flag;
// *************************************************************************************************
// Extern section
extern void start_simpliciti_tx_only(simpliciti_mode_t mode);
#endif /*RFSIMPLICITI_H_*/

@ -35,6 +35,7 @@
#include "bsp_leds.h"
#include "bsp_buttons.h"
#include "simpliciti.h"
#include "driver/display.h"
// *************************************************************************************************
@ -45,7 +46,7 @@
#define CONV_MS_TO_TICKS(msec) (((msec) * 32768) / 1000)
// U16
typedef unsigned short u16;
//typedef unsigned short u16;
// *************************************************************************************************
// Prototypes section
@ -60,6 +61,8 @@ extern void Timer0_A4_Delay(u16 ticks);
extern unsigned char simpliciti_payload_length;
extern int simpliciti_get_rvc_callback(uint8_t len);
// *************************************************************************************************
// Global Variable section
static linkID_t sLinkID1;
@ -211,34 +214,83 @@ unsigned char simpliciti_link(void)
// *************************************************************************************************
void simpliciti_main_tx_only(void)
{
while(1)
{
// Get end device data from callback function
simpliciti_get_ed_data_callback();
// Send data when flag bit SIMPLICITI_TRIGGER_SEND_DATA is set
if (getFlag(simpliciti_flag, SIMPLICITI_TRIGGER_SEND_DATA))
{
// Get radio ready. Wakes up in IDLE state.
SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_AWAKE, 0);
// Acceleration / button events packets are 4 bytes long
SMPL_SendOpt(sLinkID1, simpliciti_data, simpliciti_payload_length, SMPL_TXOPTION_NONE);
// Put radio back to SLEEP state
SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SLEEP, 0);
clearFlag(simpliciti_flag, SIMPLICITI_TRIGGER_SEND_DATA);
}
// Exit when flag bit SIMPLICITI_TRIGGER_STOP is set
if (getFlag(simpliciti_flag, SIMPLICITI_TRIGGER_STOP))
{
// Clean up SimpliciTI stack to enable restarting
sInit_done = 0;
break;
uint8_t len, i;
uint8_t ed_data[2];
while(1)
{
// Get end device data from callback function
simpliciti_get_ed_data_callback();
// Get radio ready. Wakes up in IDLE state.
if(getFlag(simpliciti_flag, SIMPLICITI_TRIGGER_SEND_DATA) ||
getFlag(simpliciti_flag, SIMPLICITI_TRIGGER_RECEIVED_DATA)) {
SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_AWAKE, 0);
// Send data when flag bit SIMPLICITI_TRIGGER_SEND_DATA is set
if (getFlag(simpliciti_flag, SIMPLICITI_TRIGGER_SEND_DATA))
{
SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_AWAKE, 0);
// Acceleration / button events packets are 4 bytes long
SMPL_SendOpt(sLinkID1, simpliciti_data, simpliciti_payload_length, SMPL_TXOPTION_NONE);
clearFlag(simpliciti_flag, SIMPLICITI_TRIGGER_SEND_DATA);
}
// Receive data when flag bit SIMPLICITI_TRIGGER_RECEIVE_DATA is set
if (getFlag(simpliciti_flag, SIMPLICITI_TRIGGER_RECEIVE_DATA)) {
// Send 2 byte long ready-to-receive packet to stimulate host reply
clearFlag(simpliciti_flag, SIMPLICITI_TRIGGER_RECEIVE_DATA);
// clean up tha buffer first
simpliciti_data[0] = 0x00;
simpliciti_data[1] = 0x00;
simpliciti_data[3] = 0x00;
simpliciti_data[4] = 0x00;
// generate a ready to receive packet
ed_data[0] = SYNC_ED_TYPE_R2R;
ed_data[1] = 0xCB;
SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_RXON, 0);
NWK_DELAY(10);
// we try to receive 9 times by sending a R2R packet
for (i = 0; i < 10; i++) {
SMPL_SendOpt(sLinkID1, ed_data, 2, SMPL_TXOPTION_NONE);
//WDTCTL = WDTPW + WDTHOLD;
// Wait shortly for host reply
NWK_DELAY(10);
while (SMPL_Receive(sLinkID1, simpliciti_data, &len) == SMPL_SUCCESS)
{
if (len > 0)
{
// Decode received data
if(simpliciti_get_rvc_callback(len))
{
// stop retry loop
i = 10;
break;
}
}
Timer0_A4_Delay(CONV_MS_TO_TICKS(50));
}
}
}
// Put radio back to SLEEP state
SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SLEEP, 0);
}
// Exit when flag bit SIMPLICITI_TRIGGER_STOP is set
if (getFlag(simpliciti_flag, SIMPLICITI_TRIGGER_STOP))
{
// Clean up SimpliciTI stack to enable restarting
sInit_done = 0;
break;
}
}
}
}

@ -106,6 +106,7 @@ extern unsigned char simpliciti_flag;
#define SIMPLICITI_TRIGGER_SEND_DATA (BIT3)
#define SIMPLICITI_TRIGGER_RECEIVED_DATA (BIT4)
#define SIMPLICITI_TRIGGER_STOP (BIT5)
#define SIMPLICITI_TRIGGER_RECEIVE_DATA (BIT6)
// Radio frequency offset read from calibration memory
// Compensates crystal deviation from 26MHz nominal value

Loading…
Cancel
Save