I had the same need for my Logomatic, where I have a GPS and six axes of inertial measurements, and need to record both.
Here is my heavily modified main.c. It expects the GPS to be in 8N1 SIRF binary, attached to UART1 (not 0), baud rate specified as before in LOGCON.TXT, and it records everything in SIRF binary, including the ADCs. I made up two packets to describe the ADCs and one to describe the Logomatic processor load and timing.
ADC Columns
0xA0A2 - packet start
0x00XX - packet length, 1byte+(2 bytes*number of ADCs active)
0x2A - packet type
For each ADC
-
1 byte pin number as labeled on the Logomatic board ( 1-8 )
-
1 byte pin number as seen by the LPC2148 (1.3 etc) ADC ‘side’ 1.X is in high 4 bits, ADC ‘channel’ X.3 is in the low 4 bits, so 1.3 is 0x13
0xXXXX - checksum, same algorithm as SIRF
0xB0B3 - packet end
ADC readout
0xA0A2 - packet start
0x00XX - packet length, 9bytes+(2 bytes*number of ADCs active)
0x2C - packet type
4 byte timestamp before reading ADCs (60MHz counter, resets to 0 each second, not synced with GPS)
For each ADC
- 2 byte ADC reading, 0-1023
4 byte timestamp after reading ADCs
0xXXXX - checksum, same algorithm as SIRF
0xB0B3 - packet end
Logomatic time and load - 1 per second
0xA0A2 - packet start
0x00XX - packet length, 16 bytes
0x15 - Packet type
2 byte year
1 byte month
1 byte day of month
1 byte hour
1 byte minute
1 byte second (above calendar set to 0000/00/00 00:00:00 at reset)
4 byte time under load in last second (divide by 60M for percentage)
0xXXXX - checksum
0xB0B3 - message end
Software can send SIRF binary commands to GPS, see ‘message’ variable. The software puts on the header, calculates the checksum, and puts on the footer, all automatically. Just encode the payload. It also records all commands sent to the GPS in the log, again as a packet, which is ok since command and received packets’ message IDs don’t overlap. You may even be able to send NMEA commands with this, since if the receiver is in NMEA mode, the SIRF header and footer will just be interpreted as line noise. However, this program expects the data received from the GPS to be in SIRF mode, and probably won’t handle NMEA properly.
This program works with UART1, not 0! It was more convenient on my board to use, since I had a row of headers already soldered to it.
This saves all the data on the card, as we have come to expect. However, since it is all in SIRF binary, a special program is needed in order to interpret it. I have one written in Java, which this margin is too narrow to contain.
To compile this, get the Logomatic V2 firmware packet from Sparkfun, make sure you can compile it according to the instructions, then replace the given main/main.c with the code below and recompile Follow the remaining instructions to install the firmware. I do it by USB bootloader.
The Logomatic hardware is pretty flexible, as the Sparkfun guys say. It’s a full blown computer, not just a logger. If this code doesn’t do what you need, hopefully you can modify it. After all, we all love to tinker, right?
I have successfully run this with my GPS at 57600baud and ADC readout of around ~100Hz.
This is posted with no guarantees that it will do anything, helpful or harmful. It will probably work (it does for me) but if it makes your GPS explode and burns down your house, it’s not my fault.
The code was originally the Logomatic V2 firmware, but I think I have changed it enough to call my own. Anyone may use and/or modify it for any purpose, including commercial purposes.
/*********************************************************************************
* Logomatic Version Kwan Firmware
* Sparkfun Electronics 2008
* Kwan Systems 2009
* ******************************************************************************/
/*******************************************************
* Header Files
******************************************************/
#include <stdio.h>
#include <string.h>
#include "LPC21xx.h"
#include "serial.h"
//Needed for main function calls
#include "main_msc.h"
#include "fat16.h"
#include "armVIC.h"
#include "itoa.h"
#include "rootdir.h"
#include "sd_raw.h"
/*******************************************************
* Global Variables
******************************************************/
#define ON 1
#define OFF 0
#define stringSize 512
char RX_array1[stringSize];
char RX_array2[stringSize];
char log_array1 = 0;
char log_array2 = 0;
short RX_in = 0;
char get_frame = 0;
struct fat16_file_struct* handle;
struct fat16_file_struct * fd;
char stringBuf[256];
int nChannels = 0;
// Default Settings
static int baudcode = 4;
static int freq = 100;
char channelActive[8];
static char fn[]="LOK9_XXX.bin";
/*******************************************************
* Function Declarations
******************************************************/
void setupPins(void);
void setup_uart0(int newbaud, char want_ints);
void setup_uart1(int newbaud, char want_ints);
void startRecordUART(void);
void startRecordADC(void);
void setup(void);
void loop(void);
void blinklock(void);
void readLogCon(void);
void stat(int statnum, int onoff);
//void feed(void);
static void UART0ISR(void); //__attribute__ ((interrupt("IRQ")));
static void UART1ISR(void); //__attribute__ ((interrupt("IRQ")));
static void timerISR(void); //__attribute__ ((interrupt("IRQ")));
void FIQ_Routine(void) __attribute__ ((interrupt("FIQ")));
void SWI_Routine(void) __attribute__ ((interrupt("SWI")));
void UNDEF_Routine(void) __attribute__ ((interrupt("UNDEF")));
void fat_initialize(void);
void delay_ms(int count);
/*******************************************************
* MAIN
* Arduino-style structure here
******************************************************/
int main (void) {
setup();
for(;;) loop();
}
void setup() {
int i;
int count = 0;
//Turn on timer 1, 60MHz by default
T1TCR=0x01;
//Turn on the clock, using the 32kHz clock crystal
CCR=0x13;
YEAR=0;
MONTH=0;
DOM=0;
DOW=0;
DOY=0;
HOUR=0;
MIN=0;
SEC=0;
CCR=0x11;
enableFIQ();
setupPins();
fat_initialize();
// Flash Status Lights
for(i = 0; i < 5; i++) {
stat(0,ON);
delay_ms(50);
stat(0,OFF);
stat(1,ON);
delay_ms(50);
stat(1,OFF);
}
count=0;
do {
if(count >=99) {
blinklock();
}
fn[5]=count/100+'0';
fn[6]=(count%100)/10+'0';
fn[7]=(count%10)+'0';
count++;
} while(root_file_exists(fn));
handle = root_open_new(fn);
sd_raw_sync();
readLogCon();
startRecordUART();
//Only set up the ADC if some channels are to be recorded
if(nChannels>0) startRecordADC();
}
/*******************************************************
* Initialize
******************************************************/
#define PLOCK 0x400
void setupPins(void) {
// C F 3 5 1 5 0 5
// 1100 1111 0011 0101 0001 0101 0000 0101
// F E D C B A 9 8 7 6 5 4 3 2 1 0
// Pin 0.00 - 01 - TxD0
// Pin 0.01 - 01 - RxD0
// Pin 0.02 - 00 - GPIO 0.02
// Pin 0.03 - 00 - GPIO 0.03
// Pin 0.04 - 01 - SCK0
// Pin 0.05 - 01 - MISO0
// Pin 0.06 - 01 - MOSI0
// Pin 0.07 - 00 - GPIO 0.07
// Pin 0.08 - 01 - TxD1
// Pin 0.09 - 01 - RxD1
// Pin 0.10 - 11 - AD1.2
// Pin 0.11 - 00 - GPIO 0.11
// Pin 0.12 - 11 - AD1.3
// Pin 0.13 - 11 - AD1.4
// Pin 0.14 - 00 - GPIO 0.14
// Pin 0.15 - 11 - AD1.5
PINSEL0 = 0xCF351505;
// 1 5 4 4 1 8 0 1
// 0001 0101 0100 0100 0001 1000 0000 0001
// F E D C B A 9 8 7 6 5 4 3 2 1 0
// Pin 0.16 0 - 01 - EINT0
// Pin 0.17 1 - 00 - GPIO 0.17
// Pin 0.18 2 - 00 - GPIO 0.18
// Pin 0.19 3 - 00 - GPIO 0.19
// Pin 0.20 4 - 00 - GPIO 0.20
// Pin 0.21 5 - 10 - AD1.6
// Pin 0.22 6 - 01 - AD1.7
// Pin 0.23 7 - 00 - GPIO 0.23
// Pin 0.24 8 - 00 - Reserved
// Pin 0.25 9 - 01 - GPIO 0.25
// Pin 0.26 A - 00 - Reserved
// Pin 0.27 B - 01 - Reserved
// Pin 0.28 C - 01 - AD0.1
// Pin 0.29 D - 01 - AD0.2
// Pin 0.30 E - 01 - AD0.3
// Pin 0.31 F - 00 - GPO only
PINSEL1 = 0x15441801;
// Pin 2,7,11 set to out
IODIR0 |= 0x00000884;
IOSET0 = 0x00000080;
S0SPCR = 0x08; // SPI clk to be pclk/8
S0SPCR = 0x30; // master, msb, first clk edge, active high, no ints
}
void writeRX(char in) {
if(RX_in < 512) {
RX_array1[RX_in] = in;
RX_in++;
if(RX_in == 512) log_array1 = 1;
} else if(RX_in >= 512) {
RX_array2[RX_in-512] = in;
RX_in++;
if(RX_in == 1024) {
log_array2 = 1;
RX_in = 0;
}
}
}
void writeRXHex(char in) {
char bit1=(in>>4) & 0x0F;
if(bit1<10) {
bit1+=48;
} else {
bit1+=55;
}
writeRX(bit1);
bit1=(in & 0x0F);
if(bit1<10) {
bit1+=48;
} else {
bit1+=55;
}
writeRX(bit1);
}
static char sirfIn[256];
static int sirfInPtr=0;
static int GPSLight=0;
static int lockOn=0;
static int loops=0;
static void parseSirf() {
if(sirfIn[4]==0x29) {
//Check if we have a position
lockOn=((sirfIn[6]==0) & (sirfIn[5]==0));
if(lockOn) GPSLight=1;
} else if(!lockOn && sirfIn[4]==4) {
//Check if we have at least one sat
if(sirfIn[12]>0) {
GPSLight=1-GPSLight;
} else {
GPSLight=0;
}
}
stat(0,GPSLight);
}
static void addSirf(char temp) {
sirfIn[sirfInPtr]=temp;
sirfInPtr++;
if((sirfInPtr>0 && sirfIn[sirfInPtr-1]==0xB3 && sirfIn[sirfInPtr-2]==0xB0) || sirfInPtr>=256) {
for(int i=0;i<sirfInPtr;i++) writeRX(sirfIn[i]);
parseSirf();
sirfInPtr=0;
}
}
static int sendRX(char out, int checksum) {
writeRX(out);
checksum+=out;
checksum &= 0x7FFF;
return checksum;
}
static int sendcmd(char out, int checksum) {
putc_serial1(out);
return sendRX(out,checksum);
}
static void UART0ISR(void) {
char temp=U0RBR;
addSirf(temp);
temp = U0IIR; // Have to read this to clear the interrupt
VICVectAddr = 0;
}
static void UART1ISR(void) {
char temp=U1RBR;
addSirf(temp);
temp = U1IIR; // Have to read this to clear the interrupt
VICVectAddr = 0;
}
static char adcSide[]={0,0,0,0,1,1,1,1};
static char adcChan[]={3,2,1,4,7,6,2,3};
static volatile char timeForADC=0;
static void timerISR(void) {
T0IR = 1; // reset TMR0 interrupt
timeForADC=1;
VICVectAddr= 0;
}
void readADC() {
int temp = 0, adcValue = 0, ind = 0;
int j;
timeForADC=0;
char q[50];
unsigned int tsc0=T1TC;
tsc0 %= 60000000;
for(j = 0; j < 50; j++) {
q[j] = 0;
}
for(j=0;j<8;j++) {
temp=0x0020FF00 | (1 << adcChan[j]);
if(channelActive[j]) {
if(adcSide[j]==0) {
AD0CR=temp; //Set up ADC and select channel
AD0CR|= 0x01000000; // start conversion
do {
temp = AD0DR;
} while((temp & 0x80000000) == 0);
AD0CR = 0x00000000;
} else {
AD1CR=temp; //Set up ADC and select channel
temp=0;
AD1CR|= 0x01000000; // start conversion
do {
temp = AD1DR;
} while((temp & 0x80000000) == 0);
AD1CR = 0x00000000;
}
adcValue = (temp & 0xFFC0) >> 6;
q[ind]=adcValue>>8;
ind++;
q[ind]=adcValue & 0xFF;
ind++;
}
}
unsigned int tsc1=T1TC;
tsc1 %= 60000000;
writeRX(0xA0);
writeRX(0xA2);
writeRX(0x00);
writeRX(ind+9); //length
int checksum=sendRX(0x2C,0);//Steal an unused output message slot;
checksum=sendRX((tsc0 >>24) & 0xFF,checksum);
checksum=sendRX((tsc0 >>16) & 0xFF,checksum);
checksum=sendRX((tsc0 >> 8) & 0xFF,checksum);
checksum=sendRX((tsc0 >> 0) & 0xFF,checksum);
for(j = 0; j < ind; j++) checksum=sendRX(q[j],checksum);
checksum=sendRX((tsc1 >>24) & 0xFF,checksum);
checksum=sendRX((tsc1 >>16) & 0xFF,checksum);
checksum=sendRX((tsc1 >> 8) & 0xFF,checksum);
checksum=sendRX((tsc1 >> 0) & 0xFF,checksum);
writeRX(checksum>>8);
writeRX(checksum & 0xFF);
writeRX(0xB0);
writeRX(0xB3);
}
void FIQ_Routine(void) {
char a;
int j;
stat(0,ON);
for(j = 0; j < 5000000; j++);
stat(0,OFF);
a = U0RBR;
a = U0IIR; // have to read this to clear the interrupt
}
void SWI_Routine(void) {
while(1);
}
void UNDEF_Routine(void) {
stat(0,ON);
}
//0 1 2 3 4 5 6 7 8
//X 1200 2400 4800 9600 19200 38400 57600 115200
static int baudDL[]={0xFFFF,0x0C00,0x0600,0x0300,0x0180,0x00C0,0x0060,0x0040,0x0020};
void setup_uart0(int newbaudcode, char want_ints) {
baudcode = newbaudcode;
U0LCR = 0x83; // 8 bits, no parity, 1 stop bit, DLAB = 1
//DLAB - Divisor Latch Access bit. When set, a certain memory address
// maps to the divisor latches, which control the baud rate. When
// cleared, those same addresses correspond to the processor end
// of the FIFOs. In other words, set the DLAB to change the baud
// rate, and clear it to use the FIFOs.
U0DLM=baudDL[baudcode] >> 8;
U0DLL=baudDL[baudcode] & 0xFF;
U0FCR = 0x01; //Enable both FIFOs
U0LCR = 0x03; //Turn of DLAB - FIFOs accessable
// U0TER = 0x80; //Enable transmitter
if(want_ints == 1) {
enableIRQ();
VICIntSelect &= ~0x00000040; //Not an FIQ interrupt
VICIntEnable |= 0x00000040; //Enabled
VICVectCntl1 = 0x26; //VIC slot 1 enabled, IRQ6 (UART0)
VICVectAddr1 = (unsigned int)UART0ISR;
U0IER = 0x01; //Enable UART0 interrupts on Rx data available
} else {
VICIntEnClr = 0x00000040;
U0IER = 0x00;
}
}
void setup_uart1(int newbaudcode, char want_ints) {
baudcode = newbaudcode;
U1LCR = 0x83; // 8 bits, no parity, 1 stop bit, DLAB = 1
//DLAB - Divisor Latch Access bit. When set, a certain memory address
// maps to the divisor latches, which control the baud rate. When
// cleared, those same addresses correspond to the processor end
// of the FIFOs. In other words, set the DLAB to change the baud
// rate, and clear it to use the FIFOs.
U1DLM=baudDL[baudcode] >> 8;
U1DLL=baudDL[baudcode] & 0xFF;
U1FCR = 0x01; //Enable both FIFOs
U1LCR = 0x03; //Turn of DLAB - FIFOs accessable
// U1TER = 0x80; //Enable transmitter
if(want_ints == 1) {
enableIRQ();
VICIntSelect &= ~0x00000080; //Make this a normal interrupt instead of FIQ
VICIntEnable |= 0x00000080; //Enable the interrupt
VICVectCntl1 = 0x27; //VIC slot 1 enabled, IRQ6 (UART0)
VICVectAddr1 = (unsigned int)UART1ISR;
U1IER = 0x01; //UART throws interrupts
} else {
VICIntEnClr = 0x00000080;
U1IER = 0x00;
}
}
void stat(int statnum, int onoff) {
if(statnum) {
// Stat 1
if(onoff){ IOCLR0 = 0x00000800; } // On
else { IOSET0 = 0x00000800; } // Off
} else {
// Stat 0
if(onoff){ IOCLR0 = 0x00000004; } // On
else { IOSET0 = 0x00000004; } // Off
}
}
void readLogCon(void) {
int x, mark = 0, ind = 0, s;
char temp;
if(root_file_exists("LOGCON.txt")) {
fd = root_open("LOGCON.txt");
s = fat16_read_file(fd, (unsigned char *)stringBuf, 512);
stringBuf[s] = '\0';
fat16_close_file(fd);
} else {
fd = root_open_new("LOGCON.txt");
if(fd == NULL) {
blinklock();
}
strcpy(stringBuf, ";MODE = 0\r\n"
";ASCII = N\r\n"
"Baud = 7\r\n"
"Frequency = 100\r\n"
";Trigger Character = $\r\n"
";Text Frame = 100\r\n"
"AD1 = N\r\n"
"AD2 = N\r\n"
"AD3 = N\r\n"
"AD4 = N\r\n"
"AD5 = N\r\n"
"AD6 = N\r\n"
"AD7 = N\r\n"
"AD8 = N\r\n"
";Saftey On = Y\r\n");
s = strlen(stringBuf);
fat16_write_file(fd, (unsigned char*)stringBuf, s);
sd_raw_sync();
}
for(x = 0; x < stringSize; x++) {
temp = stringBuf[x];
if(temp == 10) {
mark = x;
ind++;
if(ind == 3) {
baudcode=stringBuf[mark-2]-'0';
} else if(ind == 4) {
freq = (stringBuf[mark-2]-48) + (stringBuf[mark-3]-48) * 10;
if((stringBuf[mark-4] >= 48) && (stringBuf[mark-4] < 58)) {
freq+= (stringBuf[mark-4]-48) * 100;
if((stringBuf[mark-5] >= 48) && (stringBuf[mark-5] < 58)){ freq += (stringBuf[mark-5]-48)*1000; }
}
} else if(ind == 7) {
channelActive[0] = (stringBuf[mark-2]=='Y');
if(channelActive[0]){ nChannels++; }
} else if(ind == 8) {
channelActive[1] = (stringBuf[mark-2]=='Y');
if(channelActive[1]){ nChannels++; }
} else if(ind == 9) {
channelActive[2] = (stringBuf[mark-2]=='Y');
if(channelActive[2]){ nChannels++; }
} else if(ind == 10) {
channelActive[3] = (stringBuf[mark-2]=='Y');
if(channelActive[3]){ nChannels++; }
} else if(ind == 11) {
channelActive[4] = (stringBuf[mark-2]=='Y');
if(channelActive[4]){ nChannels++; }
} else if(ind == 12) {
channelActive[5] = (stringBuf[mark-2]=='Y');
if(channelActive[5]){ nChannels++; }
} else if(ind == 13) {
channelActive[6] = (stringBuf[mark-2]=='Y');
if(channelActive[6]){ nChannels++; }
} else if(ind == 14) {
channelActive[7] = (stringBuf[mark-2]=='Y');
if(channelActive[7]){ nChannels++; }
}
}
}
writeRX(0xA0);
writeRX(0xA2);
writeRX(0x00);
writeRX(nChannels*2+1); //length
int checksum=sendRX(0x2A,0); //Steal an unused output message slot;
for(x = 0; x < nChannels; x++) {
if(channelActive[x]) {
checksum=sendRX(x+1,checksum);
checksum=sendRX(adcSide[x]<<4 | adcChan[x],checksum);
}
}
writeRX(checksum>>8);
writeRX(checksum & 0xFF);
writeRX(0xB0);
writeRX(0xB3);
}
void startRecordUART(void) {
// setup_uart0(baud,1);
setup_uart1(baudcode,1);
}
void startRecordADC(void) {
enableIRQ();
// Timer0 interrupt is an IRQ interrupt
VICIntSelect &= ~0x00000010;
// Enable Timer0 interrupt
VICIntEnable |= 0x00000010;
// Use slot 3 for Timer0 interrupt
VICVectCntl3 = 0x24;
// Set the address of ISR for slot 3
VICVectAddr3 = (unsigned int)timerISR;
T0TCR = 0x00000002; // Reset counter and prescaler
T0MCR = 0x00000003; // On match reset the counter and generate interrupt
T0MR0 = 58982400 / freq;
T0PR = 0x00000000;
T0TCR = 0x00000001; // enable timer
}
void blinklock() {
for(;;) {
stat(0,ON);
delay_ms(50);
stat(0,OFF);
stat(1,ON);
delay_ms(50);
stat(1,OFF);
}
}
static int limit[]={1,2};
static int fired[]={0,0};
static char messages[]={25, //payload length
0x80, //Init Data Source
0x00,0x00,0x00,0x00, //ECF X (ignored)
0x00,0x00,0x00,0x00, //ECF Y (ignored)
0x00,0x00,0x00,0x00, //ECF Z (ignored)
0x00,0x00,0x00,0x00, //Clock drift (ignored)
0x00,0x00,0x00,0x00, //GPSTOW (ignored)
0x00,0x00, //GPS Week (ignored)
0x0C, //Channel count (ignored)
0x10, //Hot init, Firehose on! Raw track, nav lib, 50bps, RTCM, clock, DR
2, //payload length
0x84, //Poll Software Version
0x00 //Not used
};
void writeMsgs() {
for(int j=0;j<2;j++) {
if((!fired[j]) && (loops>=limit[j])) {
fired[j]=1;
char* ptr=messages;
char len=*ptr;
ptr++;
for(int k=0;k<j;k++) {
ptr+=len;
len=*ptr;
ptr++;
}
sendcmd(0xA0,0);
sendcmd(0xA2,0);
sendcmd(0x00,0);
sendcmd(len,0);
int checksum=0;
for(int k=0;k<len;k++) {
checksum=sendcmd(*ptr,checksum);
ptr++;
}
sendcmd(checksum >> 8,0);
sendcmd(checksum & 0xFF,0);
sendcmd(0xB0,0);
sendcmd(0xB3,0);
}
}
}
void writeTimeUsed(int lasttoc, int thistoc, int time) {
writeRX(0xA0);
writeRX(0xA2);
writeRX(0x00);
writeRX(12); //length
int checksum=sendRX(0x15,0); //Steal an unused output message slot;
checksum=sendRX((YEAR >> 8) & 0xFF,checksum);
checksum=sendRX((YEAR >> 0) & 0xFF,checksum);
checksum=sendRX((MONTH >> 0) & 0xFF,checksum);
checksum=sendRX((DOM >> 0) & 0xFF,checksum);
checksum=sendRX((HOUR >> 0) & 0xFF,checksum);
checksum=sendRX((MIN >> 0) & 0xFF,checksum);
checksum=sendRX((SEC >> 0) & 0xFF,checksum);
checksum=sendRX((time >>24) & 0xFF,checksum);
checksum=sendRX((time >>16) & 0xFF,checksum);
checksum=sendRX((time >> 8) & 0xFF,checksum);
checksum=sendRX((time >> 0) & 0xFF,checksum);
writeRX(checksum>>8);
writeRX(checksum & 0xFF);
writeRX(0xB0);
writeRX(0xB3);
}
static int lasttoc=-1;
static int timeused=0;
static int redlight=0;
void loop(void) {
int idle=1;
if(timeForADC) {
stat(1,ON);
readADC();
idle=0;
}
if(log_array1 == 1) {
stat(1,ON);
if(fat16_write_file(handle,(unsigned char *)RX_array1, stringSize) < 0) blinklock();
sd_raw_sync();
log_array1 = 0;
loops++;
writeMsgs();
idle=0;
}
if(log_array2 == 1) {
stat(1,ON);
if(fat16_write_file(handle,(unsigned char *)RX_array2, stringSize) < 0) blinklock();
sd_raw_sync();
log_array2 = 0;
idle=0;
}
// if button pushed, log file & quit
if((IOPIN0 & 0x00000008) == 0) {
VICIntEnClr = 0xFFFFFFFF; //Turn off interrupts
//Write out the last bit of buffer
if(RX_in < 512) {
fat16_write_file(handle, (unsigned char *)RX_array1, RX_in);
sd_raw_sync();
} else if(RX_in >= 512) {
fat16_write_file(handle, (unsigned char *)RX_array2, RX_in - 512);
sd_raw_sync();
}
//quit
blinklock();
}
int thistoc=T1TC % 60000000;
//Handle the last little bit of each timer cycle
// if(T1TC>4260000000) {
// T1TC-=426000000;
// }
if(lasttoc>0) {
if(thistoc<lasttoc) {
//Get the last little bit of time around the corner
if(!idle) timeused+=60000000-lasttoc;
writeTimeUsed(lasttoc,thistoc,timeused);
//This resets the counter
if(!idle) {
timeused=thistoc;
} else {
timeused=0;
}
} else if(!idle) {
timeused+=(thistoc-lasttoc);
}
}
lasttoc=thistoc;
stat(1,OFF);
}
void fat_initialize(void) {
if(!sd_raw_init()) {
blinklock();
}
if(openroot()) {
blinklock();
}
}
void delay_ms(int count) {
int i;
count *= 10000;
for(i = 0; i < count; i++) asm volatile ("nop");
}