/**** IR Mrakomer 4 ****/
#define VERSION "4.0"
#define ID "$Id: irmrak4.c 1298 2009-01-16 23:40:59Z kakl $"
#include "irmrak4.h"
#bit CREN = 0x18.4 // USART registers
#bit SPEN = 0x18.7
#bit OERR = 0x18.1
#bit FERR = 0x18.2
#include <string.h>
//!!! #include "bloader.c" // Boot Loader driver
#CASE // Case sensitive compiler
#define MAXHEAT 20 // Number of cycles for heating
#define MAXOPEN 20 // Number of cycles for dome open
#define MEASURE_DELAY 6000 // Delay to a next measurement
#define RESPONSE_DELAY 100 // Reaction time after receiving a command
#define SAFETY_COUNT 90 // Time of one emergency cycle
#define SEND_DELAY 50 // Time between two characters on RS232
#define DOME PIN_B4 // Dome controll port
#define HEATING PIN_B3 // Heating for defrosting
char VER[4]=VERSION; // Buffer for concatenate of a version string
int8 heat; // Status variables
int8 open;
inline void toggle_dome(void) // Wire exercise
{
if (open>0)
{output_toggle(DOME);} // Toggle = Open Dome
else
{output_high(DOME);} // Do not toggle = Close Dome
}
void delay(int16 cycles) // Wire exercise with delay
{
int16 i;
for(i=0; i<cycles; i++) {toggle_dome(); delay_us(100);}
}
void welcome(void) // Welcome message
{
char REV[50]=ID; // Buffer for concatenate of a version string
if (REV[strlen(REV)-1]=='$') REV[strlen(REV)-1]=0;
printf("\n\r# Mrakomer %s (C) 2007 KAKL\n\r",VER); // Welcome message
printf("#%s\n\r",&REV[4]);
printf("# <sequence> <ambient[1/100 C]> <sky[1/100 C]> ");
printf("<heating[s]> <dome[s]> <check>\n\r\n\r");
}
#include "smb.c" // System Management Bus driver
// Read sensor's RAM
// Returns temperature in °K
int16 ReadTemp(int8 addr, int8 select)
{
unsigned char arr[6]; // Buffer for the sent bytes
int8 crc; // Readed CRC
int16 temp; // Readed temperature
addr<<=1;
SMB_STOP_bit(); //If slave send NACK stop comunication
SMB_START_bit(); //Start condition
SMB_TX_byte(addr);
SMB_TX_byte(RAM_Access|select);
SMB_START_bit(); //Repeated Start condition
SMB_TX_byte(addr);
arr[2]=SMB_RX_byte(ACK); //Read low data,master must send ACK
arr[1]=SMB_RX_byte(ACK); //Read high data,master must send ACK
temp=make16(arr[1],arr[2]);
crc=SMB_RX_byte(NACK); //Read PEC byte, master must send NACK
SMB_STOP_bit(); //Stop condition
arr[5]=addr;
arr[4]=RAM_Access|select;
arr[3]=addr;
arr[0]=0;
if (crc != PEC_calculation(arr)) temp=0; // Calculate and check CRC
return temp;
}
/*-------------------------------- MAIN --------------------------------------*/
void real_main()
{
unsigned int16 seq, temp, tempa;
signed int16 ta, to;
int8 safety_counter;
int1 repeat;
output_high(DOME); // Close Dome
output_low(HEATING); // Heating off
delay_ms(1000);
restart_wdt();
seq=0; // Variables initiation
heat=0;
open=0;
repeat=TRUE;
welcome();
tempa=ReadTemp(SA, RAM_Tamb); // Dummy read
temp=ReadTemp(SA, RAM_Tobj1);
delay_ms(1000);
//---WDT
restart_wdt();
while(TRUE) // Main Loop
{
safety_counter=SAFETY_COUNT; // Heating and Dome Count Down
do
{
if (safety_counter<SAFETY_COUNT) safety_counter++;
delay(RESPONSE_DELAY);
if (safety_counter>=SAFETY_COUNT)
{
if (heat>0) heat--;
if (open>0) open--;
if (heat>0) { output_high(HEATING); } else { output_low(HEATING); }
safety_counter=0;
//---WDT
restart_wdt();
}
} while (!kbhit()&&!repeat);
//---WDT
restart_wdt();
{ // Retrieve command
char ch='k';
if(kbhit()) ch=getc();
switch (ch)
{
case 'h':
heat=MAXHEAT; // Need heating
break;
case 'c':
heat=0; // Need colder
break;
case 'o':
open=MAXOPEN; // Open the dome
break;
case 'x':
open=MAXOPEN; // Open the dome
heat=MAXHEAT; // Need heating
break;
case 'l':
open=0; // Lock the dome
break;
case 'i':
if (open==0) welcome(); // Information about version, etc...
break; // Only when dome is closed
case 'r':
repeat=TRUE; // Repeated measure mode
break;
case 's':
repeat=FALSE; // Single measure mode
break;
case 'u':
// load_program(); // Update firmware
}
}
// while(kbhit()) getc(); // Flush USART buffer
CREN=0; CREN=1; // Reinitialise USART
seq++; // Increment the number of measurement
tempa=ReadTemp(SA, RAM_Tamb); // Read temperatures from sensor
temp=ReadTemp(SA, RAM_Tobj1);
ta=tempa*2-27315; // °K -> °C
to=temp*2-27315;
{ // printf
char output[8]; // Output buffer
int8 j; // String pointer
int8 check=0; // Checksum is calculated between '$' and '*'
delay(SEND_DELAY);
putc('$');
delay(SEND_DELAY);
sprintf(output,"M%s ",VER);
j=0; while(output[j]!=0) { delay(SEND_DELAY); putc(output[j]); check^=output[j++]; }
sprintf(output,"%Lu ", seq);
j=0; while(output[j]!=0) { delay(SEND_DELAY); putc(output[j]); check^=output[j++]; }
sprintf(output,"%Ld ", ta);
j=0; while(output[j]!=0) { delay(SEND_DELAY); putc(output[j]); check^=output[j++]; }
sprintf(output,"%Ld ", to);
j=0; while(output[j]!=0) { delay(SEND_DELAY); putc(output[j]); check^=output[j++]; }
sprintf(output,"%u ", heat);
j=0; while(output[j]!=0) { delay(SEND_DELAY); putc(output[j]); check^=output[j++]; }
sprintf(output,"%u ", open);
j=0; while(output[j]!=0) { delay(SEND_DELAY); putc(output[j]); check^=output[j++]; }
sprintf(output,"*%X\n\r\0", check);
j=0; while(output[j]!=0) { delay(SEND_DELAY); putc(output[j++]); }
delay(SEND_DELAY);
}
delay(MEASURE_DELAY); // Delay to a next measurement
//---WDT
restart_wdt();
}
}
/*------------------- BOOT LOADER --------------------------------------------*/
#define LOADER_RESERVED getenv("PROGRAM_MEMORY")-getenv("FLASH_ERASE_SIZE")-800
#define BUFFER_LEN_LOD 46
#ORG LOADER_RESERVED,getenv("PROGRAM_MEMORY")-201 auto=0 default
unsigned int atoi_b16(char *s) { // Convert two hex characters to a int8
unsigned int result = 0;
int i;
for (i=0; i<2; i++,s++) {
if (*s >= 'A')
result = 16*result + (*s) - 'A' + 10;
else
result = 16*result + (*s) - '0';
}
return(result);
}
void assert(int1 Condition, int8 ErrorCode)
{
if(Condition)
{
putchar('E');
putchar(ErrorCode+'1');
reset_cpu();
}
}
void pause()
{
int16 timeout;
for(timeout=0; timeout<65535; timeout++); // Delay cca 300ms
}
boot_loader()
{
int buffidx;
char buffer[BUFFER_LEN_LOD];
int8 checksum, line_type;
int16 l_addr,h_addr=0;
int32 addr;
#if getenv("FLASH_ERASE_SIZE")>2
int32 next_addr;
#endif
//!!! #error ble getenv("FLASH_ERASE_SIZE") getenv("FLASH_WRITE_SIZE")
int8 dataidx, i, count;
union program_data {
int8 i8[16];
int16 i16[8];
} data;
putchar('@');
//!!!nesmaze obsluhu preruseni
for(i=getenv("FLASH_ERASE_SIZE")+1;i<LOADER_RESERVED;i+=getenv("FLASH_ERASE_SIZE"))
erase_program_eeprom(i);
putchar('@');
while(TRUE)
{
//---WDT
//!!! musi fungovat watchdog
while (getc()!=':') restart_wdt(); // Only process data blocks that starts with ':'
buffidx = 0; // Read into the buffer until 'x' is received or buffer is full
do
{
buffer[buffidx] = getc();
} while ( (buffer[buffidx++] != 'x') && (buffidx < BUFFER_LEN_LOD) );
assert(buffidx == BUFFER_LEN_LOD,1); // Overrun buffer?
//---WDT
restart_wdt();
checksum = 0; // Sum the bytes to find the check sum value
for (i=0; i<(buffidx-3); i+=2)
checksum += atoi_b16 (&buffer[i]);
checksum = 0xFF - checksum + 1;
assert(checksum != atoi_b16 (&buffer[buffidx-3]),2); // Bad CheckSum?
count = atoi_b16 (&buffer[0]); // Get the number of bytes from the buffer
// Get the lower 16 bits of address
l_addr = make16(atoi_b16(&buffer[2]),atoi_b16(&buffer[4]));
line_type = atoi_b16 (&buffer[6]);
addr = make32(h_addr,l_addr);
addr /= 2; // PIC16 uses word addresses
// If the line type is 1, then data is done being sent
if (line_type == 1)
{
putchar('#');
reset_cpu();
}
assert (line_type == 4,4);
//!!! pozor, nevypalilo by to obsluhu preruseni
if (addr > 3 || addr < LOADER_RESERVED)
{
if (line_type == 0)
{
for (i=0,next_addr=addr;i<8;i++)
data.i16[i]=read_program_eeprom(next_addr++);
// Loops through all of the data and stores it in data
// The last 2 bytes are the check sum, hence buffidx-3
for (i=8,dataidx=0; i < buffidx-3; i += 2)
data.i8[dataidx++]=atoi_b16(&buffer[i]);
write_program_memory(addr, data.i8, count);
}
putchar('*');
}
}
}
#ORG default
#ORG getenv("PROGRAM_MEMORY")-200,getenv("PROGRAM_MEMORY")-1
void main()
{
int8 timeout;
disable_interrupts(GLOBAL);
setup_wdt(WDT_2304MS); // Setup Watch Dog
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_oscillator(OSC_8MHZ|OSC_INTRC);
/*
for(timeout=0; timeout<(3*20); timeout++) //cca 20s
if (kbhit())
{
if (getc()=='u') if (getc()=='f') boot_loader(); // Update Firmware starter
pause();
CREN=0; CREN=1;
restart_wdt();
};
*/
real_main();
}
#include "dbloader.c"