?? hoarder.c
字號(hào):
while ((cf_task_file_read(7)&0xC0)!=0x40);
cf_task_file_write(2, 1);
cf_task_file_write(3, sector[0]);
cf_task_file_write(4, sector[1]);
cf_task_file_write(5, sector[2]);
cf_task_file_write(6, 0xE0 | (sector[3]&0x0F));
cf_task_file_write(7, 0x20); // read sector command
while ((cf_read()&0x88)!=0x08);
cf_set_addr(0);
}
// start writing CF sector
// global var sector contains sector number
// after calling this function use cf_write()
// to write 512 bytes to sector
void cf_start_sector_write()
{
while ((cf_task_file_read(7)&0xC0)!=0x40);
cf_task_file_write(2, 1);
cf_task_file_write(3, sector[0]);
cf_task_file_write(4, sector[1]);
cf_task_file_write(5, sector[2]);
cf_task_file_write(6, 0xE0 | (sector[3]&0x0F));
cf_task_file_write(7, 0x30); // write sector command
while ((cf_read()&0x88)!=0x08);
cf_set_addr(0);
}
// put CF to sleep mode (see CF specs)
#separate
void cf_sleep()
// put the card into sleep mode
{
while ((cf_task_file_read(7)&0xC0)!=0x40);
cf_task_file_write(6, 0xE0);
cf_task_file_write(7, 0x99); // sleep command
}
// put CF to standby mode (see CF specs)
#separate
void cf_standby()
// put the card into stadby mode
{
while ((cf_task_file_read(7)&0xC0)!=0x40);
cf_task_file_write(6, 0xE0);
cf_task_file_write(7, 0x94); // standby immediate command
}
// put CF to idle mode (see CF specs)
#separate
void cf_idle(int delay)
// put the card into idle mode, sets a delay for auto power-down
{
while ((cf_task_file_read(7)&0xC0)!=0x40);
cf_task_file_write(2, delay);
cf_task_file_write(6, 0xE0);
cf_task_file_write(7, 0x97); // idle command
}
void print_prompt()
{
putc('>');
}
void led_off()
{
OUTPUT_LOW(CF_LED0);
OUTPUT_LOW(CF_LED1);
}
void led_green()
{
OUTPUT_LOW(CF_LED1);
OUTPUT_HIGH(CF_LED0);
}
void led_red()
{
OUTPUT_LOW(CF_LED0);
OUTPUT_HIGH(CF_LED1);
}
// getc() after taking care of possible overflow error
char loadc()
{
while (!input(RCIF))
{
if (input(OERR))
{
output_low(CREN);
output_high(CREN);
}
}
return getc();
}
// Yep! It's nope. Used for short delays.
#inline
void nop()
{
#asm
nop
#endasm
}
// RTC functions
// see RTC chip specs http://pdfserv.maxim-ic.com/arpdf/DS1302.pdf (if still there)
// for data format etc
// IMPORTANT
// RTC READ/WRITE DOES NOT WORK IF CF CARD IS PLUGGED IN AND POWERED DOWN
// This is because of sharing port D pins
// So make sure CF is either out or powered up before using RTC
// Read time from RTC chip into time[]
// 8-byte burst operation
// Note: nop() are important to get proper timing at 20MHz
void rtc_read_time()
{
static byte i, j, result;
set_tris_d(TRIS_D_RTC_OUT);
output_high(RTC_RST);
output_high(RTC_IO);
for (i=0; i<6; i++) {
output_high(RTC_CLK);
nop();
output_low(RTC_CLK);
}
output_low(RTC_IO);
output_high(RTC_CLK);
nop();
output_low(RTC_CLK);
output_high(RTC_IO);
output_high(RTC_CLK);
nop();
set_tris_d(TRIS_D_RTC_IN);
for (j=0; j<8; j++) {
for (i=0; i<8; i++) {
output_low(RTC_CLK);
nop();
shift_right(&result, 1, input(RTC_IO));
output_high(RTC_CLK);
}
time[j]=result;
}
output_low(RTC_CLK);
output_low(RTC_IO);
output_low(RTC_RST);
SET_TRIS_D(TRIS_D_IN);
}
// Read and return one byte from RTC chip at addr
int rtc_read(int addr)
{
int i;
set_tris_d(TRIS_D_RTC_OUT);
output_high(RTC_RST);
output_high(RTC_IO);
output_high(RTC_CLK);
nop();
output_low(RTC_CLK);
for (i=0; i<6; i++) {
output_bit(RTC_IO, bit_test(addr, 0));
output_high(RTC_CLK);
addr>>=1;
output_low(RTC_CLK);
}
output_high(RTC_IO);
output_high(RTC_CLK);
set_tris_d(TRIS_D_RTC_IN);
for (i=0; i<8; i++) {
output_low(RTC_CLK);
nop();
shift_right(&_return_, 1, input(RTC_IO));
output_high(RTC_CLK);
}
output_low(RTC_CLK);
output_low(RTC_IO);
output_low(RTC_RST);
SET_TRIS_D(TRIS_D_IN);
}
// Write data to RTC chip at addr
void rtc_write(int addr, int data)
{
int i;
set_tris_d(TRIS_D_RTC_OUT);
output_high(RTC_RST);
output_low(RTC_IO);
output_high(RTC_CLK);
nop();
output_low(RTC_CLK);
for (i=0; i<6; i++) {
output_bit(RTC_IO, addr&1);
output_high(RTC_CLK);
addr>>=1;
output_low(RTC_CLK);
}
output_high(RTC_IO);
output_high(RTC_CLK);
nop();
output_low(RTC_CLK);
for (i=0; i<8; i++) {
output_bit(RTC_IO, data&1);
output_high(RTC_CLK);
data>>=1;
output_low(RTC_CLK);
}
output_low(RTC_IO);
output_low(RTC_RST);
set_tris_d(TRIS_D_IN);
}
// Write time to RTC chip
// 8-byte burst operation
void rtc_set_time()
{
int i, j, data;
set_tris_d(TRIS_D_RTC_OUT);
output_high(RTC_RST);
output_low(RTC_IO);
output_high(RTC_CLK);
nop();
output_low(RTC_CLK);
output_high(RTC_IO);
for (i=0; i<5; i++) {
output_high(RTC_CLK);
output_low(RTC_CLK);
}
output_low(RTC_IO);
output_high(RTC_CLK);
nop();
output_low(RTC_CLK);
output_high(RTC_IO);
output_high(RTC_CLK);
nop();
output_low(RTC_CLK);
for (j=0; j<8; j++)
{
data=time[j];
for (i=0; i<8; i++) {
output_bit(RTC_IO, data&1);
output_high(RTC_CLK);
data>>=1;
output_low(RTC_CLK);
}
}
output_low(RTC_IO);
output_low(RTC_RST);
set_tris_d(TRIS_D_IN);
}
// Use this function to skip previous records in data file and prevent
// accidental loss of previously recorded data when Hoarder restarts.
// Skips to first "unused" sector of data file.
// - "unused" sector has either invalid signature or timestamp lower than previous sector
// - sectors written by Hoarder have "ESL" signature and 6-byte time stamp in the beginning
//
// Function returns TRUE if data file is valid and not full
// FALSE if data file is not valid or no space left
// If function returns TRUE sector points to first "unused" sector of data file and
// sector_counter indicates number of free sectors
#separate
boolean init_file_write() {
int i, t[6];
if (cf_out || !(disk_valid && file_valid)) return FALSE;
move32(sector, data_start);
move32(sector_counter, data_file_size);
for (i=0; i<6; i++) time[i]=0;
while (!is_zero32(sector_counter)) {
for (i=0; i<6; i++) t[i]=time[i];
cf_start_sector_read();
if ((cf_read()!='E')||(cf_read()!='S')||(cf_read()!='L')) return TRUE;
for (i=0; i<6; i++) time[i]=cf_read();
i=6;
while (--i!=0xFF) if (time[i]<t[i]) return TRUE; else if (time[i]>t[i]) i=0;
inc32(sector);
dec32(sector_counter);
}
cf_idle(100);
return FALSE;
}
// Call cf_start_sector_write() for next sector in data file
// return FALSE if no free sectors left
// uses global vars sector and sector_counter
#separate
boolean next_file_sector_write() {
if (cf_out) return FALSE;
if (is_zero32(sector_counter)) {
cf_idle(100);
return FALSE;
}
cf_start_sector_write();
inc32(sector);
dec32(sector_counter);
return TRUE;
}
#separate
void save_audio()
{
char tag1[4], tag2[4];
long tagtime, tag1time, tag2time;
int tagphase;
if (cf_out || !(disk_valid && file_valid)) return;
// Start at beginning of data file
move32(sector, data_start);
move32(sector_counter, data_file_size);
tag1time=0xFFFF;
tag2time=0xFFFF;
tagphase=0;
// Set timer interrupt to 8kHz to sample audio
setup_timer_2(T2_DIV_BY_1, 125, 5); // 8 kHz
write_pos=0;
// Set flags for timer interrupt data sampling
audio=TRUE;
ad_on=TRUE;
// loop until something received thru serial port
// and full sector is written
while ((!input(RCIF))||(write_pos!=512)) {
// if sector ended start a new one
if (write_pos>=512) {
write_pos=0;
}
else if (write_pos==0) {
// exit if no space left in data file
if (!next_file_sector_write()) return;
// blink
SET_TRIS_C(TRIS_C);
led_red();
// write sector signature ESL
cf_write('E');
cf_write('S');
cf_write('L');
// write time stamp
rtc_read_time();
cf_write(time[0]);
cf_write(time[1]);
cf_write(time[2]);
cf_write(time[3]);
cf_write(time[4]);
cf_write(time[6]);
write_pos+=9;
led_off();
}
// save accelerometer data 3 times in each sector
else if ((write_pos==170)||(write_pos==335)||(write_pos==500)) {
putI2C(0xB0, 2);
I2C_start();
I2C_write(0xB0 | I2CREAD);
cf_write(i2c_read());
cf_write(i2c_read());
cf_write(i2c_read());
cf_write(i2c_read());
i2c_read(0);
I2C_stop();
write_pos+=4;
// write tag reader data once per sector
if (write_pos==504) {
if ((tagphase&0x1F)==0) {
putI2C(0xA0, 2);
I2C_start();
I2C_write(0xA0 | I2CREAD);
tag1[0]=i2c_read();
tag1[1]=i2c_read();
tag1[2]=i2c_read();
tag1[3]=i2c_read();
tagtime=i2c_read();
tagtime=tagtime<<8|i2c_read();
i2c_read(0);
I2C_stop();
if (tagtime>=tag1time) zero32(tag1);
tag1time=tagtime;
putI2C(0xA0, 3);
I2C_start();
I2C_write(0xA0 | I2CREAD);
tag2[0]=i2c_read();
tag2[1]=i2c_read();
tag2[2]=i2c_read();
tag2[3]=i2c_read();
tagtime=i2c_read();
tagtime=tagtime<<8|i2c_read();
i2c_read(0);
I2C_stop();
if (tagtime>=tag2time) zero32(tag2);
tag2time=tagtime;
}
tagphase++;
cf_write(tag1[0]);
cf_write(tag1[1]);
cf_write(tag1[2]);
cf_write(tag1[3]);
cf_write(tag2[0]);
cf_write(tag2[1]);
cf_write(tag2[2]);
cf_write(tag2[3]);
write_pos+=8;
}
} else if (write_pos<512) {
// save buffered audio samples
// sampling happens in timer interrupt
while (buf_count==0);
cf_write(buffer[buf_head]>>2);
write_pos++;
disable_interrupts(GLOBAL);
buf_head=(buf_head+1)%buf_size;
buf_count--;
enable_interrupts(GLOBAL);
}
}
// stop sampling, restore 1000Hz timer frequency
ad_on=FALSE;
audio=FALSE;
purge_adc_buffer();
setup_timer_2(T2_DIV_BY_4, 250, 5); // 1mS interval @ 20 MHz
}
#separate
void save_data()
{
if (!disk_valid) return;
write_pos=0;
move32(sector, data_start);
ad_on=TRUE;
while ((!input(RCIF))||(write_pos!=512)) {
if (write_pos>=512) {
write_pos=0;
inc32(sector);
}
if (write_pos==0) {
led_red();
cf_start_sector_write();
cf_write('E');
cf_write('S');
rtc_read_time();
cf_write(time[0]);
cf_write(time[1]);
cf_write(time[2]);
cf_write(time[3]);
cf_write(time[4]);
cf_write(time[6]);
write_pos+=8;
led_off();
}
while (buf_count==0);
cf_write(buffer[buf_head]);
cf_write(buffer[buf_head]>>8);
write_pos+=2;
disable_interrupts(GLOBAL);
buf_head=(buf_head+1)%buf_size;
buf_count--;
enable_interrupts(GLOBAL);
}
ad_on=FALSE;
purge_adc_buffer();
inc32(sector);
cf_start_sector_write();
for (write_pos=0; write_pos<512; write_pos++) cf_write(0);
}
#separate
void send_data()
{
unsigned int temp;
long int id;
ad_on=TRUE;
while (!input(RCIF)) {
//for (temp=0; temp<19; temp++) putc(0xF0);
putc(0x5A);
for (temp=0; temp<4; temp++) {
while (buf_count==0);
if (temp==3)
{
putc(buffer[buf_head]);
if (id>0) putc((buffer[buf_head]>>8)|((id-1) << 2)|0xA8);
else putc(buffer[buf_head]>>8);
}
if (temp==2)
{
if (buffer[buf_head]>768) id=0; else if (buffer[buf_head]<256) id=1; else id=2;
}
disable_interrupts(GLOBAL);
buf_head=(buf_head+1)%buf_size;
buf_count--;
enable_interrupts(GLOBAL);
}
}
ad_on=FALSE;
purge_adc_buffer();
}
// Calculates standard 16-bit CRC
// uses global var crc16
// Note: crc16 should be set to 0 before each series of CRC calculations
void crc (unsigned int data)
{
int i, j;
for (i=0; i<8; i++) {
j=(data^crc16)&1;
crc16>>=1;
if (j) crc16^=0xA001;
data>>=1;
}
}
// send data and update CRC
void put_crc(unsigned int data)
{
putc(data);
crc(data);
}
#separate
void send_data_bim()
{
unsigned int temp;
unsigned int bits;
unsigned long order;
unsigned int i;
if (!init_file_write()) return;
ad_on=TRUE;
order=0;
output_low(BIM_TX);
while (!input(RCIF) && next_file_sector_write()) {
led_red();
cf_write('E');
cf_write('S');
cf_write('L');
rtc_read_time();
cf_write(time[0]);
cf_write(time[1]);
cf_write(time[2]);
cf_write(time[3]);
cf_write(time[4]);
cf_write(time[6]);
led_off();
for (i=0; i<100; i++) {
for (temp=0; temp<5; temp++) putc(0x0F<<(temp%5)); //total packet length 22
crc16=0;
put_crc(0xA5);
put_crc(order);
put_crc(order>>8);
for (temp=0; temp<4; temp++) {
while (buf_count==0);
put_crc(buffer[buf_head]);
cf_write(buffer[buf_head]);
bits=(bits<<2)|((buffer[buf_head]>>8)&0x03);
disable_interrupts(GLOBAL);
buf_head=(buf_head+1)%buf_size;
buf_count--;
enable_interrupts(GLOBAL);
}
put_crc(bits);
cf_write(bits);
putc(crc16);
putc(crc16>>8);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -