Skip to content

Commit 321dc25

Browse files
committed
Initial publish of general telem module.
1 parent ebea43d commit 321dc25

File tree

2 files changed

+422
-0
lines changed

2 files changed

+422
-0
lines changed

telem.c

Lines changed: 334 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,334 @@
1+
/*
2+
* Copyright (c) 2010-2014, Regents of the University of California
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are met:
7+
*
8+
* - Redistributions of source code must retain the above copyright notice,
9+
* this list of conditions and the following disclaimer.
10+
* - Redistributions in binary form must reproduce the above copyright notice,
11+
* this list of conditions and the following disclaimer in the documentation
12+
* and/or other materials provided with the distribution.
13+
* - Neither the name of the University of California, Berkeley nor the names
14+
* of its contributors may be used to endorse or promote products derived
15+
* from this software without specific prior written permission.
16+
*
17+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27+
* POSSIBILITY OF SUCH DAMAGE.
28+
*
29+
*
30+
* Generalized interface for telemetry recording and readback.
31+
*
32+
* by Andrew Pullin
33+
*
34+
* v0.1
35+
*
36+
* Revisions:
37+
* Andrew Pullin 2014 Initial publish to imageproc-lib
38+
*
39+
* Usage:
40+
* There are three requed macros to be defined, in settings.h:
41+
* #define TELEM_TYPE myTelemStruct_t
42+
* #define TELEM_INCLUDE "my_telem.h"
43+
* #define TELEMPACKFUNC(x) myTelemGetData(x)
44+
*
45+
* The header file referenced by TELEM_INCLUDE must be defined.
46+
* See https://github.com/biomimetics/roach/blob/master/lib/vr_telem.h for an
47+
* example of how to set up this file.
48+
* Similarly, the matching C file that implements TELEMPACKFUNC(x) must exist.
49+
* See https://github.com/biomimetics/roach/blob/master/lib/vr_telem.c for an
50+
* example implementation matching he header above.
51+
*/
52+
53+
#include "utils.h"
54+
#include "settings.h"
55+
#include "dfmem.h"
56+
#include "telem.h"
57+
#include "radio.h"
58+
#include "at86rf231_driver.h"
59+
#include "sclock.h"
60+
//#include "sys_service.h"
61+
#include "cmd.h" //for CMD codes
62+
#include <string.h> //for memcpy
63+
64+
//This is a terrible hack to avoid bus conflicts.
65+
//TODO: find source of bus problems and fix
66+
#include <timer.h>
67+
68+
//Timer parameters
69+
#define TIMER_FREQUENCY 1000.0 // 1000 Hz
70+
#define TIMER_PERIOD 1/TIMER_FREQUENCY
71+
#define DEFAULT_SKIP_NUM 1
72+
73+
74+
#if defined(__RADIO_HIGH_DATA_RATE)
75+
#define READBACK_DELAY_TIME_MS 3
76+
#else
77+
#define READBACK_DELAY_TIME_MS 4
78+
#endif
79+
80+
telemStruct_t telemBuffer;
81+
unsigned int telemDataSize;
82+
unsigned int telemPacketSize;
83+
84+
#define TELEM_HEADER_SIZE sizeof(telemBuffer.sampleIndex) + sizeof(telemBuffer.timestamp)
85+
86+
//////// Private variables ////////////////
87+
static unsigned long samplesToSave = 0;
88+
//Skip counter for dividing the 300hz timer into lower telemetry rates
89+
static unsigned int telemSkipNum = DEFAULT_SKIP_NUM;
90+
static unsigned int skipcounter = DEFAULT_SKIP_NUM;
91+
static unsigned long sampIdx = 0;
92+
93+
//static unsigned long samplesToStream = 0;
94+
//static char telemStreamingFlag = TELEM_STREAM_OFF;
95+
//static unsigned int streamSkipCounter = 0;
96+
//static unsigned int streamSkipNum = 15;
97+
98+
//Offset for time value when recording samples
99+
static unsigned long telemStartTime = 0;
100+
101+
static DfmemGeometryStruct mem_geo;
102+
103+
///////////// Private functions //////////////
104+
//Function to be installed into T5, and setup function
105+
//static void SetupTimer5(); // Might collide with setup in steering module!
106+
//static void telemServiceRoutine(void); //To be installed with sysService
107+
//The following local functions are called by the service routine:
108+
static void telemISRHandler(void);
109+
110+
///////// Telemtry ISR ////////
111+
//////// Installed to Timer5 @ 300hz ////////
112+
//void __attribute__((interrupt, no_auto_psv)) _T5Interrupt(void) {
113+
114+
//static void telemServiceRoutine(void) {
115+
//This intermediate function is used in case we want to tie other
116+
//sub-taks to the telemtry service routine.
117+
//TODO: Is this neccesary?
118+
119+
// Section for saving telemetry data to flash
120+
// Uses telemSkip as a divisor to T5.
121+
// telemISRHandler();
122+
//}
123+
124+
/*
125+
static void SetupTimer5() {
126+
///// Timer 5 setup, Steering ISR, 300Hz /////
127+
// period value = Fcy/(prescale*Ftimer)
128+
unsigned int T5CON1value, T5PERvalue;
129+
// prescale 1:64
130+
T5CON1value = T5_ON & T5_IDLE_CON & T5_GATE_OFF & T5_PS_1_64 & T5_SOURCE_INT;
131+
// Period is set so that period = 5ms (200Hz), MIPS = 40
132+
//T5PERvalue = 2083; // ~300Hz
133+
T5PERvalue = 625; //1Khz
134+
int retval;
135+
//retval = sysServiceConfigT5(T5CON1value, T5PERvalue, T5_INT_PRIOR_4 & T5_INT_ON);
136+
}
137+
*/
138+
139+
void telemSetup() {
140+
141+
dfmemGetGeometryParams(&mem_geo); // Read memory chip sizing
142+
143+
//Telemetry packet size is set at startupt time.
144+
telemDataSize = sizeof (TELEM_TYPE);
145+
telemPacketSize = sizeof (telemStruct_t);
146+
Nop();
147+
Nop();
148+
149+
//Install telemetry service handler
150+
// Lines removed before to use telemetry module in direct mode, does not
151+
// run its own ISR. (pullin, 10/9/14)
152+
//int retval;
153+
//retval = sysServiceInstallT5(telemServiceRoutine);
154+
//SetupTimer5();
155+
}
156+
157+
void telemSetSamplesToSave(unsigned long n) {
158+
samplesToSave = n;
159+
sampIdx = 0;
160+
}
161+
162+
void telemReadbackSamples(unsigned long numSamples) {
163+
int delaytime_ms = READBACK_DELAY_TIME_MS;
164+
unsigned long i = 0; //will actually be the same as the sampleIndex
165+
166+
telemStruct_t sampleData;
167+
168+
//This is a terrible hack to avoid bus conflicts.
169+
//TODO: find source of bus problems and fix
170+
DisableIntT1;
171+
172+
for (i = 0; i < numSamples; i++) {
173+
//Retireve data from flash
174+
telemGetSample(i, sizeof (sampleData), (unsigned char*) (&sampleData));
175+
//Reliable send, with linear backoff
176+
do {
177+
//debugpins1_set();
178+
telemSendDataDelay(&sampleData, delaytime_ms);
179+
//Linear backoff
180+
delaytime_ms += 0;
181+
//debugpins1_clr();
182+
} while (trxGetLastACKd() == 0);
183+
184+
delaytime_ms = READBACK_DELAY_TIME_MS;
185+
}
186+
187+
//This is a terrible hack to avoid bus conflicts.
188+
//TODO: find source of bus problems and fix
189+
EnableIntT1;
190+
}
191+
192+
void telemSendDataDelay(telemStruct_t* sample, int delaytime_ms) {
193+
radioSendData(RADIO_DST_ADDR, 0, CMD_FLASH_READBACK, telemPacketSize, (unsigned char *)sample, 0);
194+
delay_ms(delaytime_ms); // allow radio transmission time
195+
}
196+
197+
198+
//Saves telemetry data structure into flash memory, in order
199+
//Position in flash memory is maintained by dfmem module
200+
void telemSaveData(telemStruct_t * telemPkt) {
201+
202+
//Write the packet header info to the DFMEM
203+
dfmemSave((unsigned char*) telemPkt, sizeof(telemStruct_t));
204+
samplesToSave--;
205+
206+
//This is done here instead of the ISR because telemSaveData() will only be
207+
//executed if samplesToSave > 0 upon entry.
208+
if (samplesToSave == 0) {
209+
//Done sampling, commit last buffer
210+
dfmemSync();
211+
}
212+
}
213+
214+
void telemErase(unsigned long numSamples) {
215+
//dfmemEraseSectorsForSamples(numSamples, sizeof (telemU));
216+
// TODO (apullin) : Add an explicit check to see if the number of saved
217+
// samples will fit into memory!
218+
219+
//Green LED will be used as progress indicator
220+
221+
//Horibble hack: Disable IMU while erasing flash
222+
_T4IE = 0;
223+
224+
LED_GREEN = 1;
225+
unsigned int firstPageOfSector, i;
226+
227+
//avoid trivial case
228+
if (numSamples == 0) {
229+
return;
230+
}
231+
232+
//Saves to dfmem will NOT overlap page boundaries, so we need to do this level by level:
233+
unsigned int samplesPerPage = mem_geo.bytes_per_page / telemPacketSize; //round DOWN int division
234+
unsigned int numPages = (numSamples + samplesPerPage - 1) / samplesPerPage; //round UP int division
235+
unsigned int numSectors = (numPages + mem_geo.pages_per_sector - 1) / mem_geo.pages_per_sector;
236+
237+
//This is a terrible hack to avoid bus conflicts.
238+
//TODO: find source of bus problems and fix
239+
DisableIntT1;
240+
241+
//At this point, it is impossible for numSectors == 0
242+
//Sector 0a and 0b will be erased together always, for simplicity
243+
//Note that numSectors will be the actual number of sectors to erase,
244+
// even though the sectors themselves are numbered starting at '0'
245+
dfmemEraseSector(0); //Erase Sector 0a
246+
LED_GREEN = ~LED_GREEN;
247+
dfmemEraseSector(8); //Erase Sector 0b
248+
LED_GREEN = ~LED_GREEN;
249+
250+
//Start erasing the rest from Sector 1,
251+
// The (numsectors-1) here is because sectors are numbered from 0, whereas
252+
// numSectors is the actual count of sectors to erase; fencepost error.
253+
for (i = 1; i <= (numSectors-1); i++) {
254+
firstPageOfSector = mem_geo.pages_per_sector * i;
255+
//hold off until dfmem is ready for sector erase command
256+
//LED should blink indicating progress
257+
//Send actual erase command
258+
dfmemEraseSector(firstPageOfSector);
259+
LED_GREEN = ~LED_GREEN;
260+
}
261+
262+
//Leadout flash, should blink faster than above, indicating the last sector
263+
while (!dfmemIsReady()) {
264+
LED_GREEN = ~LED_GREEN;
265+
delay_ms(50);
266+
}
267+
LED_GREEN = 0; //Green LED off
268+
269+
//This is a terrible hack to avoid bus conflicts.
270+
//TODO: find source of bus problems and fix
271+
EnableIntT1;
272+
273+
//Since we've erased, reset our place keeper vars
274+
dfmemZeroIndex();
275+
276+
//Horibble hack: Disable IMU while erasing flash
277+
_T4IE = 1;
278+
}
279+
280+
281+
void telemGetSample(unsigned long sampNum, unsigned int sampLen, unsigned char *data)
282+
{
283+
unsigned int samplesPerPage = mem_geo.bytes_per_page / sampLen; //round DOWN int division
284+
unsigned int pagenum = sampNum / samplesPerPage;
285+
unsigned int byteOffset = (sampNum - pagenum*samplesPerPage)*sampLen;
286+
287+
dfmemRead(pagenum, byteOffset, sampLen, data);
288+
}
289+
290+
//This only exists to allow an exteral module to cause a telemetry save
291+
//immediately. (pullin, 10/9/14)
292+
void telemSaveNow(){
293+
telemISRHandler();
294+
}
295+
296+
//// Private functions
297+
////////////////////////
298+
299+
static void telemISRHandler() {
300+
301+
//skipcounter decrements to 0, triggering a telemetry save, and resets
302+
// value of skicounter
303+
if (skipcounter == 0) {
304+
if (samplesToSave > 0) {
305+
telemBuffer.timestamp = sclockGetTime() - telemStartTime;
306+
telemBuffer.sampleIndex = sampIdx;
307+
//Write telemetry data into packet
308+
//TELEMPACKFUNC((unsigned char*) &(telemBuffer.telemData));
309+
TELEMPACKFUNC( &(telemBuffer.telemData) );
310+
311+
telemSaveData(&telemBuffer);
312+
sampIdx++;
313+
}
314+
//Reset value of skip counter
315+
skipcounter = telemSkipNum;
316+
}
317+
//Always decrement skip counter at every interrupt, at 300Hz
318+
//This way, if telemSkipNum = 1, a sample is saved at every interrupt.
319+
skipcounter--;
320+
321+
}
322+
323+
void telemSetSkip(unsigned int skipnum) {
324+
telemSkipNum = skipnum;
325+
}
326+
327+
//This function is a setter for the telemStartTime variable,
328+
//which is used to offset the recorded times for telemetry, such that
329+
//they start at approx. 0, instead of reflecting the total number of
330+
//sclock ticks.
331+
332+
void telemSetStartTime(void) {
333+
telemStartTime = sclockGetTime();
334+
}

0 commit comments

Comments
 (0)