Eric Allen 13 years ago
parent
commit
796fb2f585
  1. 14
      TODO
  2. 163
      contrib/plot_accel.py
  3. 2
      driver/display.h
  4. 1
      ezchronos.c
  5. 2
      logic/menu.c
  6. 94
      logic/phase_clock.c
  7. 14
      logic/phase_clock.h
  8. 27
      logic/rfsimpliciti.c
  9. 10
      logic/rfsimpliciti.h
  10. 9
      logic/temperature.c
  11. 3
      logic/test.c
  12. 42
      simpliciti/Applications/application/End_Device/main_ED_BM.c

14
TODO

@ -1,11 +1,21 @@
* modularise more code
* try to free more space
* autosync before/after flash
* use bulk transfer in sleep clock mode
* make buttons lock while sleep mode active
* better compilition depending on config file. someone with more make knowledge please ;-)
* fix warnings in simplicti code
* use RTC of the msp430 instead of the interrupt code
* fix the eggtimer. it runs to slow (like 2 seconds per second...)
* merge eggtimer into stopwatch. to much shared code that blow the firmware
== OPEN BUG ==
* very hard to debug: when the battery is quite low, the sleep init mode fails. only way currently working
is to set "bug 1" in the sleep settings and skip the init phase (very bad).
== IN WORKS ==
* autosync before/after flash
== MAYBE ==
* use bulk transfer in sleep clock mode. There is now a multistep init phase that works quite well
=== DONE ===

163
contrib/plot_accel.py

@ -0,0 +1,163 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (C) 2010 Marc Poulhiès
#
# 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, either version 3 of the License, or
# (at your option) any later version.
#
# 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, see <http://www.gnu.org/licenses/>.
#
# Author: Marc Poulhiès
import time
import sys
import pygame
import os
import optparse
from datetime import datetime
import math
import serial
import array
def startAccessPoint():
return array.array('B', [0xFF, 0x07, 0x03]).tostring()
def accDataRequest():
return array.array('B', [0xFF, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00]).tostring()
class Graph:
fontheight = 20
# These four values sould go into the configuration file
winheight = 800 # Window height at startup
width = 700 # Window width at startup
bgcolor = (255,255,255) # Background color for the window
color = [(255,0,0), (0,255,0), (0,0,255)]
txtcolor = (255,0,0)
t = 0
prev_display_debug = None
def __init__(self, size):
pygame.init()
self.previous_points = [0]*size
self.font = pygame.font.Font(None, self.fontheight)
self.screen = pygame.display.set_mode( (self.width, self.winheight), pygame.RESIZABLE )
pygame.display.set_caption( "Plotter" )
self.screen.fill( self.bgcolor )
pygame.display.flip()
def display_debug(self, dtext):
text = self.font.render(dtext, 1, self.txtcolor)
pos = text.get_rect(left=0, top=self.winheight -self.fontheight - 5)
if self.prev_display_debug:
self.screen.fill(self.bgcolor, self.prev_display_debug)
self.screen.blit(text, pos)
if self.prev_display_debug:
pygame.display.update(self.prev_display_debug)
else:
pygame.display.update(pos)
self.prev_display_debug = pos
def plot_values(self, values):
self.t += 1
yoff = 0
each_y = self.winheight/len(values)
norms = [a * (each_y-5)/each_y for a in values]
for i in xrange(len(values)):
pygame.draw.aaline(self.screen,
self.color[i%3],
(self.t-1,
self.previous_points[i]+yoff),
(self.t,
norms[i]+yoff),
1)
yoff += each_y
rect = pygame.Rect(self.t-1, 0, 40, self.winheight)
pygame.display.update(rect)
if self.t >= 700:
self.t = 0
self.screen.fill( self.bgcolor )
self.previous_points = norms
def conv(c):
if c > 127:
return c - 256
else:
return c
def main():
parser = optparse.OptionParser(
usage='Usage: %prog [options]',
description="Plotter !")
parser.add_option("-f", "--freq",
help="Sampling frequency in ms (defaults: 10ms)",
default=10, type="int",
metavar="sampling_freq")
parser.add_option("-v", "--verbose",
help="Be verbose and display lots of garbage",
action="store_true", default=False,
metavar="verbose")
(options, args) = parser.parse_args(sys.argv[1:])
sampling_freq = options.freq
ser = serial.Serial('/dev/ttyACM0',115200,timeout=1)
ser.write(startAccessPoint())
g = None
while True:
ser.write(accDataRequest())
accel = ser.read(7)
if len(accel) < 3:
continue
if ord(accel[0]) != 0 and ord(accel[1]) != 0 and ord(accel[2]) != 0:
l = [conv(ord(accel[0]))+128, conv(ord(accel[1]))+128,conv(ord(accel[2]))+128]
print l
print "***"
else:
continue
if g == None:
g = Graph(len(l))
g.plot_values(l)
pygame.time.wait(sampling_freq)
if __name__ == '__main__':
sys.exit(main())

2
driver/display.h

@ -293,7 +293,7 @@ extern volatile s_display_flags display;
#define LCD_UNIT_L1_K_MASK (BIT6)
#define LCD_UNIT_L1_M_MASK (BIT1)
#define LCD_UNIT_L1_I_MASK (BIT0)
#define LCD_UNIT_L1_PER_S_MASK (BIT3)
#define LCD_UNIT_L1_PER_S_MASK (BIT7)
#define LCD_UNIT_L1_PER_H_MASK (BIT2)
#define LCD_UNIT_L1_DEGREE_MASK (BIT1)
#define LCD_UNIT_L2_KCAL_MASK (BIT4)

1
ezchronos.c

@ -320,6 +320,7 @@ void init_global_variables(void)
// ptrMenu_L2 = &menu_L2_Distance;
// ptrMenu_L2 = &menu_L2_Calories;
// ptrMenu_L2 = &menu_L2_Battery;
// ptrMenu_L2 = &menu_L2_Phase;
// Assign LINE1 and LINE2 display functions
fptr_lcd_function_line1 = ptrMenu_L1->display_function;

2
logic/menu.c

@ -253,7 +253,7 @@ const struct menu menu_L2_Battery =
const struct menu menu_L2_Phase =
{
FUNCTION(sx_phase), // direct function
FUNCTION(dummy), // sub menu function
FUNCTION(mx_phase), // sub menu function
FUNCTION(display_phase_clock), // display function
FUNCTION(update_time), // new display data
&menu_L2_Rf,

94
logic/phase_clock.c

@ -64,6 +64,7 @@
#include "temperature.h"
#include "vti_ps.h"
#include "altitude.h"
#include "user.h"
// *************************************************************************************************
@ -116,22 +117,6 @@ unsigned char phase_clock_reply_count;
extern void (*fptr_lcd_function_line1)(u8 line, u8 update);
// *************************************************************************************************
// @fn reset_rf
// @brief Reset SimpliciTI data.
// @param none
// @return none
// *************************************************************************************************
void reset_sleep(void)
{
// No connection
sPhase.mode = SLEEP_OFF;
// reset rf
reset_rf();
}
// *************************************************************************************************
// @fn sx_sleep
// @brief Start Sleep mode. Button DOWN connects/disconnects to access point.
@ -152,10 +137,71 @@ void sx_phase(u8 line)
if (is_bluerobin()) return;
#endif
// Start SimpliciTI in tx only mode
start_simpliciti_tx_only(SIMPLICITI_PHASE_CLOCK_START);
if(sPhase.bug)
start_simpliciti_tx_only(SIMPLICITI_PHASE_CLOCK);
else
start_simpliciti_tx_only(SIMPLICITI_PHASE_CLOCK_START);
//start_simpliciti_tx_only(SIMPLICITI_PHASE_CLOCK);
}
// *************************************************************************************************
// @fn mx_phase
// @brief Set program number to use
// @param u8 line LINE2
// @return none
// *************************************************************************************************
void mx_phase(u8 line){
s32 prog, bug;
u8 mode = 0;
prog = (s32)sPhase.program;
bug = (s32)sPhase.bug;
// Loop values until all are set or user breaks set
while(1)
{
// Idle timeout: exit without saving
if (sys.flag.idle_timeout) break;
// M2 (short): save, then exit
if (button.flag.num)
{
// Store local variables in global Eggtimer default
//sAlarm.hour = hours;
//sAlarm.minute = minutes;
sPhase.program = (u8)prog;
sPhase.bug = (u8)bug;
display.flag.line2_full_update = 1;
break;
}
if (button.flag.star)
mode = (mode+1)%2;
switch (mode) {
case 0:
//set_value(&prog, 2, 0, 0, 99, SETVALUE_ROLLOVER_VALUE + SETVALUE_DISPLAY_VALUE + SETVALUE_NEXT_VALUE, LCD_SEG_L2_1_0, display_value1);
display_chars(LCD_SEG_L2_5_0, (u8 *)" PR ", SEG_ON);
set_value(&prog, 2, 0, 0, 99, SETVALUE_ROLLOVER_VALUE + SETVALUE_DISPLAY_VALUE + SETVALUE_NEXT_VALUE, LCD_SEG_L2_1_0, display_value1);
break;
case 1:
display_chars(LCD_SEG_L2_5_0, (u8 *)" BUG", SEG_ON);
set_value(&bug, 2, 0, 0, 1, SETVALUE_ROLLOVER_VALUE + SETVALUE_DISPLAY_VALUE + SETVALUE_NEXT_VALUE, LCD_SEG_L2_1_0, display_value1);
break;
}
}
// Clear button flag
button.all_flags = 0;
display_phase_clock(line, DISPLAY_LINE_UPDATE_FULL);
}
u8 diff(u8 x1, u8 x2) {
// *************************************************************************************************
// @fn diff
// @brief calculates the smallest difference between two numbers
// @param none
// @return none
// *************************************************************************************************
static u8 diff(u8 x1, u8 x2) {
u8 b1 = x1 - x2;
if(b1 > 127)
b1 = x2 - x1;
@ -165,7 +211,6 @@ u8 diff(u8 x1, u8 x2) {
return b1;
}
// *************************************************************************************************
// @fn phase_clock_calcpoint
// @brief calculate one data point for the out buffer
@ -208,15 +253,6 @@ void display_phase_clock(u8 line, u8 update)
display_chars(LCD_SEG_L2_5_0, (u8 *)" SLEEP", SEG_ON);
}
}
// *************************************************************************************************
// @fn is_sleep
// @brief Returns TRUE if SimpliciTI receiver is connected.
// @param none
// @return u8
// *************************************************************************************************
u8 is_sleep(void)
{
return (sPhase.mode != SLEEP_OFF);
}
#endif /*CONFIG_PHASE_CLOCK*/

14
logic/phase_clock.h

@ -55,15 +55,7 @@ extern void send_data(void);
extern void display_phase_clock(u8 line, u8 update);
extern void sx_phase(u8 line);
/*extern void sx_rf(u8 line);
extern void sx_ppt(u8 line);
extern void sx_sync(u8 line);
extern void display_rf(u8 line, u8 update);
extern void display_ppt(u8 line, u8 update);
extern void display_sync(u8 line, u8 update);
extern void send_smpl_data(u16 data);
extern u8 is_rf(void);
*/
extern void mx_phase(u8 line);
extern void phase_clock_calcpoint();
@ -116,9 +108,7 @@ typedef enum
// Global Variable section
struct SPhase
{
// SIMPLICITI_OFF, SIMPLICITI_ACCELERATION, SIMPLICITI_BUTTONS
simpliciti_mode_t mode;
u8 bug;
// current session id
u8 session;
// sleep program to start

27
logic/rfsimpliciti.c

@ -75,7 +75,7 @@
void simpliciti_get_data_callback(void);
void start_simpliciti_tx_only(simpliciti_mode_t mode);
void start_simpliciti_sync(void);
int simpliciti_get_rvc_callback(u8 len) __attribute__((noinline));
// *************************************************************************************************
// Defines section
@ -223,10 +223,10 @@ void start_simpliciti_tx_only(simpliciti_mode_t mode)
start_as = 1;
}
#ifdef CONFIG_PHASE_CLOCK
else if (mode == SIMPLICITI_PHASE_CLOCK_START)
else if (mode == SIMPLICITI_PHASE_CLOCK_START || mode == SIMPLICITI_PHASE_CLOCK)
{
simpliciti_data[0] = SIMPLICITI_PHASE_CLOCK_START_EVENTS;
start_as = 1;
if(mode == SIMPLICITI_PHASE_CLOCK)
start_as = 1;
display_symbol(LCD_ICON_RECORD, SEG_ON_BLINK_ON);
}
#endif
@ -414,6 +414,8 @@ WDTCTL = WDTPW + WDTHOLD;
{
/* Initialisation phase. Get a Session id and send the
program wanted */
//display_chars(LCD_SEG_L1_3_2, itoa(packet_counter, 2, ' '), SEG_ON);
if(packet_counter == 30) {
simpliciti_flag |= SIMPLICITI_TRIGGER_STOP;
packet_counter = 0;
@ -424,19 +426,20 @@ WDTCTL = WDTPW + WDTHOLD;
// 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
// put 2 bytes of watch id into the package
WATCH_ID(simpliciti_data, 1);
// 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);
// Wait for next sample
display_symbol(LCD_ICON_RECORD, SEG_ON);
Timer0_A4_Delay(CONV_MS_TO_TICKS(20));
Timer0_A4_Delay(CONV_MS_TO_TICKS(60));
// 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))
{
@ -487,8 +490,13 @@ WDTCTL = WDTPW + WDTHOLD;
display_symbol(LCD_ICON_BEEPER2, SEG_ON_BLINK_ON);
display_symbol(LCD_ICON_BEEPER3, SEG_ON_BLINK_ON);
open_radio();
simpliciti_flag |= SIMPLICITI_TRIGGER_SEND_DATA;
}
} else if (sPhase.out_nr == 0) {
// shutoff radio. no need to let it run for so long
close_radio();
}
sRFsmpl.timeout = SIMPLICITI_TIMEOUT;
@ -556,6 +564,7 @@ int simpliciti_get_rvc_callback(u8 len)
simpliciti_data[0] = 0x00;
simpliciti_data[1] = 0x00;
simpliciti_data[2] = 0x00;
as_start();
return 1;
#endif
}

10
logic/rfsimpliciti.h

@ -82,6 +82,15 @@ typedef enum
#define SIMPLICITI_PHASE_CLOCK_EVENTS (0x03)
#define SIMPLICITI_PHASE_CLOCK_START_EVENTS (0x04)
// notify the ap that sync mode started
#define SIMPLICITI_SYNC_STARTED_EVENTS (0x10)
#define WATCH_ID(dst,offset) \
dst[offset] = simpliciti_ed_address[0] ^ simpliciti_ed_address[1];\
dst[offset+1] = simpliciti_ed_address[2] ^ simpliciti_ed_address[3];
#define SIMPLICITI_PHASE_CLOCK_START_RESPONSE (0x54)
@ -103,6 +112,7 @@ extern unsigned char simpliciti_flag;
// Extern section
extern void start_simpliciti_tx_only(simpliciti_mode_t mode);
extern int simpliciti_get_rvc_callback(u8 len) __attribute__((noinline));
#endif /*RFSIMPLICITI_H_*/

9
logic/temperature.c

@ -56,9 +56,11 @@
// *************************************************************************************************
// Prototypes section
u8 is_temp_measurement(void);
#ifndef CONFIG_METRIC_ONLY
s16 convert_C_to_F(s16 value);
s16 convert_F_to_C(s16 value);
#endif
// *************************************************************************************************
// Defines section
@ -225,6 +227,9 @@ void mx_temperature(u8 line)
if (button.flag.star)
{
// For English units, convert set °F to °C
#ifdef CONFIG_METRIC_ONLY
temperature1 = temperature;
#else
if (!sys.flag.use_metric_units)
{
temperature1 = convert_F_to_C(temperature);
@ -233,7 +238,7 @@ void mx_temperature(u8 line)
{
temperature1 = temperature;
}
#endif
// New offset is difference between old and new value
offset = temperature1 - temperature0;
sTemp.offset += offset;

3
logic/test.c

@ -35,7 +35,6 @@
// Test functions.
// *************************************************************************************************
#ifdef CONFIG_TEST
// *************************************************************************************************
// Include section
@ -43,6 +42,8 @@
// system
#include "project.h"
#ifdef CONFIG_TEST
// driver
#include "display.h"
#include "vti_as.h"

42
simpliciti/Applications/application/End_Device/main_ED_BM.c

@ -36,6 +36,7 @@
#include "bsp_buttons.h"
#include "simpliciti.h"
#include "driver/display.h"
#include "rfsimpliciti.h"
// *************************************************************************************************
@ -60,8 +61,9 @@ extern uint8_t sInit_done;
extern void Timer0_A4_Delay(u16 ticks);
extern unsigned char simpliciti_payload_length;
//extern txOpt_t simpliciti_options;
extern int simpliciti_get_rvc_callback(uint8_t len);
//extern int simpliciti_get_rvc_callback(uint8_t len);
// *************************************************************************************************
// Global Variable section
@ -231,10 +233,11 @@ void simpliciti_main_tx_only(void)
// 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);
SMPL_SendOpt(sLinkID1, simpliciti_data, simpliciti_payload_length, SMPL_TXOPTION_NONE);
//SMPL_SendOpt(sLinkID1, simpliciti_data, simpliciti_payload_length, simpliciti_options);
// reset options to default
//simpliciti_options = SMPL_TXOPTION_NONE;
clearFlag(simpliciti_flag, SIMPLICITI_TRIGGER_SEND_DATA);
}
// Receive data when flag bit SIMPLICITI_TRIGGER_RECEIVE_DATA is set
@ -251,8 +254,8 @@ void simpliciti_main_tx_only(void)
// 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++) {
@ -275,8 +278,8 @@ void simpliciti_main_tx_only(void)
break;
}
}
Timer0_A4_Delay(CONV_MS_TO_TICKS(50));
}
Timer0_A4_Delay(CONV_MS_TO_TICKS(500));
}
}
@ -304,18 +307,30 @@ void simpliciti_main_tx_only(void)
// *************************************************************************************************
void simpliciti_main_sync(void)
{
uint8_t len, i;
uint8_t ed_data[2];
uint8_t len, i, contacted;
uint8_t ed_data[4];
contacted = 0;
while(1)
{
// send a notification that we are in sync mode
if (!contacted) {
SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_AWAKE, 0);
ed_data[0] = SIMPLICITI_SYNC_STARTED_EVENTS;
WATCH_ID(ed_data, 1);
ed_data[3] = 0x00;
SMPL_SendOpt(sLinkID1, ed_data, 4, SMPL_TXOPTION_NONE);
SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SLEEP, 0);
}
// Sleep 0.5sec between ready-to-receive packets
// SimpliciTI has no low power delay function, so we have to use ours
Timer0_A4_Delay(CONV_MS_TO_TICKS(500));
// Get radio ready. Radio wakes up in IDLE state.
SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_AWAKE, 0);
SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_AWAKE, 0);
// Send 2 byte long ready-to-receive packet to stimulate host reply
ed_data[0] = SYNC_ED_TYPE_R2R;
ed_data[1] = 0xCB;
@ -324,11 +339,12 @@ void simpliciti_main_sync(void)
// Wait shortly for host reply
SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_RXON, 0);
NWK_DELAY(10);
// Check if a command packet was received
while (SMPL_Receive(sLinkID1, simpliciti_data, &len) == SMPL_SUCCESS)
{
// Decode received data
// Decode received data
contacted = 1;
if (len > 0)
{
// Use callback function in application to decode data and react

Loading…
Cancel
Save