program Oko;
{$I DeveloperSpecific.inc} // each developer likes different defines, like {$DEFINE SIMULATOR}
{.$WG} // global Warnings on
{.$ZeroLocVars +} // all local vars are cleared to zero when func/proc is entered (this has cleared FlashTotalPages and FlashPageSize, so we will not use it for now)
{$DEBDELAY} // only used in simulator - shortens mDelays by 90% (no affect on hex file)
{.$DEFINE DEBUG} // show serial debug messages
device = mega128, VCC=3.3;
{.$BOOTRST $07000} // Reset Jump to $07000
import SysTick, SerPort, SerPort2, ADCPort, TWImaster, SPIdriver, SwitchPort1, SwitchPort2, RTClock, UserPort, PWMport1A, PWMport1B, PWMport1C, Watchdog, SysLEDblink;
from System import LongWord, LongInt, Float, Processes, StackChecks, Pipes;
from RTclock import RTCtimer{, RTCalarm};
From SysLEDblink Import FlashOnce; // this is optional
define
ProcClock = 7372800; // Hertz
SysTick = 10, Timer2; // msec
StackSize = 150, iData;
FrameSize = 150, iData;
WatchDog = msec2000; // msec32, msec64, msec125, msec250, msec1000, msec2000
SerPort = 9600, Stop1; // Baud, StopBits|Parity
RxBuffer = 16, iData;
TxBuffer = 16, iData;
SerPort2 = 38400, Stop1, parEven; // change speed to 115200, 230400 or 460800 (for 921600 we would need higher crystal)
RxBuffer2 = 64, iData; // changed from 255 to 64 to improve process freeze
TxBuffer2 = 128, iData; // changed from 255 to 128 to improve process freeze
ADCchans = 8, iData;
ADCpresc = 128;
TWIpresc = TWI_BR400;
SysLedBlink = 50; // SysTicks
SysLedBlink0 = PortC, 0, high; // Buzzer
SysLedBlink1 = PortC, 1, high; // Green LED
SysLedBlink2 = PortC, 2, high; // Red LED
SysLedBlink3 = PortC, 3, high; //
SysLedBlink4 = PortC, 4, high; //
SysLedBlink5 = PortC, 5, high; //
SPIpresc = 0;
SPIOrder = LSB;
SPICPOL = 0;
SPICPHA = 0;
SPI_SS = false; // don't use SS pin as chip select
Scheduler = iData;
SwitchPort1 = PinA; // debouncing input pins: PA.0 .. PA.7
SwitchPMask1 = %11111111; // debounce only these bits
PolarityP1 = %00000000; // active level: false
SwitchPort2 = PinC; // debouncing input pins: PC.6 .. PC.7
SwitchPMask2 = %11000000; // debounce only these bits
PolarityP2 = %00000000; // active level: false
Debounce = 3; // debounce every 3 SysTicks
RTclock = iData, DateTime; // Time or DateTime
RTCtimer = 1; // 1..8 Channels
RTCsource = SysTick{[, adj]}; // SysTick must be >= 1 when selected as RTC source, it must be integer, and (1000 mod SysTick) must be 0.
UserPort = 64; // define Mem expansion size
PWMpresc1 = 256; // prescaler timer1
PWMres1 = 10; // resolution timer1
PWMmode1 = fast, positive; // optional
FlashChkSum = ProgEnd; // generate flash checksum at the end of code
define_usr // user defined global constants visible in whole program (it is better to use included units)
MyGlobalConst = 1;
uses
okoTypes, okoCommon, okoTest, okoTags, okoMuxCom, HcpCom, Common, DriverFlash, DriverRTC, okoRT, okoSysTime, okoJSON, okoInterrupts;
implementation
{$IDATA}
{--------------------------------------------------------------}
{ Type Declarations }
{--------------------------------------------------------------}
{ Const Declarations }
const
{--------------------------------------------------------------}
{ Var Declarations }
{$IDATA}
var
ProcessFreezeCnt: byte;
TotalFreezeCnt: word;
//mydt: TDateTime;
{--------------------------------------------------------------}
{ functions }
procedure Init;
begin
// Init ports
DDRA := %00000000; // All input pins
DDRB := %11110111; // Pin B3 (MISO) - input pin
DDRC := %00111111; // Pin C7,C6 - input pins
DDRD := %11111001; // Pin D2,D1 - input pins
DDRE := %01110001; // Pin E7,E3,E2,E0 - input pins
DDRF := %00000000; // All input pins
DDRG := %00011101; // Pin G1 (CBUS3) - input pins
PORTA := %11000000; // Pin A7:A6 - PullUp if PUD=0
PORTC := %11000000; // Pin C7:C6 - PullUp if PUD=0
PORTG := %00000010; // Pin G1 - PullUp if PUD=0
CS_A := 1; // CS_D must be initially 1 for flash memory chip access
CS_B := 1; //
CS_C := 1; //
CS_D := 1; //
PWMport1A := 0; // PWM-A
PWMport1B := 0; // PWM-B
PWMport1C := 0; // PWM-C
// init interrupt Analog Comparator (AC)
SFIOR := SFIOR and %11110111; // bit 3: connect AIN1(-) input (disable ADC Mux)
ACSR := ACSR and %00111011; // bit 7: 0, AC enabled
// bit 6: 0, Connect AIN0(+)
// bit 5: -, N/A
// bit 4: -, Analog Comparator Interrupt Flag Set/Clear by hardware
// bit 3: -
// bit 2: 0, Analog Comparator Input Capture Disable
// bit 1: -, ACIS1 Comparator Interrupt on Output Edge.
// bit 0: -, ACIS0 (0)Falling/(1)Rising Output Edge.
ACSR := ACSR or %00001011; // bit 7: -
// bit 6: -
// bit 5: -
// bit 4: -
// bit 3: 1, Analog Comparator Interrupt Flag enabled
// bit 2: - // bit 1:
// bit 1: 1, ACIS1 Comparator Interrupt on Output Edge.
// bit 0: 1, ACIS0 (0)Falling/(1)Rising Output Edge.
end Init;
{$IFDEF SIMULATOR}
procedure InitSim;
begin
Runtime.DO[1].Value := true; // MX11
Runtime.DO[2].Value := false; // MX12
Settings.AI[7].Active := false; // MX5107
Settings.AI[8].Active := false; // MX5108
Settings.AO[2].Active := false; // MX5302
Settings.AO[3].Active := true; // MX5303
Settings.General.OverwriteOldEvents := false; // MX5001
Settings.BT.Active := false;
Settings.GPS.Active := false;
Settings.GSM.Active := false;
Settings.InsideTemp[1].Active := false;
Settings.InsideTemp[2].Active := false;
Runtime.General.PowerUp.Moment.Year := 11; // MB101
Runtime.General.PowerUp.Moment.Month := 02; // MB102
Runtime.General.PowerUp.Moment.Day := 12; // MB103
Runtime.General.PowerUp.Moment.Hour := 19; // MB104
Runtime.General.PowerUp.Moment.Minute := 30; // MB105
Runtime.General.PowerUp.Moment.Second := 25; // MB106
Runtime.General.PowerUp.Moment.LeapYear := true; // MX108
Settings.GPS.TimeZone := -7; // MS5001
Runtime.DO[1].Stat.CurrentHour.OnCount := 3210; // MW2001
Settings.General.HcpComm.TimeoutTicks := 59876; // MW5001
Runtime.AO[1].Eng.Value := 1.23; // QF11
Runtime.AO[2].Eng.Value := 2.34; // QF12
Runtime.AO[3].Eng.Value := 3.14; // QF13
Runtime.AO[3].Eng.Stat.CurrentHour.AvgValue := 123.4567; // MF2053
Settings.AO[1].Alarm.Treshold := 987.654321; // MF7041
Battery.EventPages.FirstPage := 2; // must be <> 0 in order for HCP read page command to work in simulator
Battery.EventPages.LastPage := 5;
Battery.BoardStat.TotalSeconds := 1000000; // running days shown in statistics
//DisableInts;
RtcSetYear(13); RtcSetMonth(12); RtcSetDay(31); // 2013.12.31
RtcSetHour(23); RtcSetMinute(59); RtcSetSecond(0); // 23:59:00
RtcSetWeekDay(1); // Tuesday
//EnableInts; // no need to enable interrupts here since Start_Processes called later will do that for us
// Runtime.General.PowerUp.Tick := 1234567890; // MD1
{if StrToDateTime('20141124T185959Z', mydt) then
WriteLn(SerOutHcp, '1: ' + DateTimeToStr(mydt, tzDoNotShowTimeZoneChar));
endif;
if StrToDateTime('20141024T185859', mydt) then
WriteLn(SerOutHcp, '2: ' + DateTimeToStr(mydt, tzShowTimeZoneChar));
endif;}
end InitSim;
{$ENDIF}
procedure CheckFrameAndStack;
const
BAD_RESULT: integer = -1; //$FFFF
var
i: byte;
begin
if CheckStackValid(Main_Proc) = BAD_RESULT then Runtime.General.Processes[IDX_MAIN ].Stack.Valid := false; endif;
if CheckStackValid(HcpComm) = BAD_RESULT then Runtime.General.Processes[IDX_HCP_COMM ].Stack.Valid := false; endif;
if CheckStackValid(MuxComm) = BAD_RESULT then Runtime.General.Processes[IDX_MUX_COMM ].Stack.Valid := false; endif;
if CheckStackValid(RT_Data) = BAD_RESULT then Runtime.General.Processes[IDX_RT_DATA ].Stack.Valid := false; endif;
if CheckStackValid(RT_Second) = BAD_RESULT then Runtime.General.Processes[IDX_RT_SECOND ].Stack.Valid := false; endif;
if CheckStackValid(RT_Hour) = BAD_RESULT then Runtime.General.Processes[IDX_RT_HOUR ].Stack.Valid := false; endif;
if CheckStackValid(RT_Actions) = BAD_RESULT then Runtime.General.Processes[IDX_RT_ACTIONS].Stack.Valid := false; endif;
if CheckFrameValid(Main_Proc) = BAD_RESULT then Runtime.General.Processes[IDX_MAIN ].Frame.Valid := false; endif;
if CheckFrameValid(HcpComm) = BAD_RESULT then Runtime.General.Processes[IDX_HCP_COMM ].Frame.Valid := false; endif;
if CheckFrameValid(MuxComm) = BAD_RESULT then Runtime.General.Processes[IDX_MUX_COMM ].Frame.Valid := false; endif;
if CheckFrameValid(RT_Data) = BAD_RESULT then Runtime.General.Processes[IDX_RT_DATA ].Frame.Valid := false; endif;
if CheckFrameValid(RT_Second) = BAD_RESULT then Runtime.General.Processes[IDX_RT_SECOND ].Frame.Valid := false; endif;
if CheckFrameValid(RT_Hour) = BAD_RESULT then Runtime.General.Processes[IDX_RT_HOUR ].Frame.Valid := false; endif;
if CheckFrameValid(RT_Actions) = BAD_RESULT then Runtime.General.Processes[IDX_RT_ACTIONS].Frame.Valid := false; endif;
for i := 1 to NUMBER_OF_PROCESSES do
Runtime.General.PowerUp.StackFrameCorrupted := Runtime.General.PowerUp.StackFrameCorrupted or (not Runtime.General.Processes[i].Stack.Valid) or (not Runtime.General.Processes[i].Frame.Valid);
endfor;
if Runtime.General.PowerUp.StackFrameCorrupted then // if stack/frame was corrupted at least once since power up
Buzz(1000); // TODO: in production buzzer should not be heard - save event instead
endif;
end;
{--------------------------------------------------------------}
{ Main Program }
...