TACHYON
[~
FORGET EGATE.fth
pub EGATE.fth PRINT" RFID Gate Access interface V1.1 150310.1500 - Peter Jakacki" ;
{ MODULE DESCRIPTION
eGATE provides RFID and timer functions to existing gate controllers using a Propeller controller and a Parallax serial RFID card reader.
eGATE P1419 PCB
In this implementation the EGATE uses a hacked P1419 interfaced to a TC-128 gate controller that is operated by wireless remotes but lacks simple features such as timed operations and RFID card access control.
The interface to the TC-128 uses simple switched inputs which switch between 0 and 34VDC and open-collector outputs interfaced opto-inputs which are pulled up to 34V.There are 4 limit switch inputs, a serial input from the card reader, 2 open-collector outputs to operate the open and close, and another LED+Buzzer line to the card reader.
A Bluetooth serial communications module is fitted in place of the USB serial module once it has been installed.
Link to current formatted log file document
NEW: OCT 13, 2014
Added scheduling in place of the simple open/close timer, it is now possible to paste in readable schedules for any day or date or action etc.
TO DO:
Add touch sensors to gate ends - reverses action, delays, tries again after 1 minute - for 3 attempts
}
( I/O DEFINITIONS )
--- The gate controller has two limit switches per motor but these signals switch between 0 to +34V
--- 100K resistors are used to limit the current into the port inputs.
--- optional pulldown/dividers may be added to the Prop side, with values from 10K to 100K suggested.
#P0 == closed2
#P1 == opened2
#P2 == closed1
#P3 == opened1
--- We have a CE0814 PIO with 4 darlington OC outputs plus shared 10K resistor inputs
--- the resistors have been removed except for the serial input from the card reader
#P9 == LED --- setting this high will turn on the card reader white LED (+Piezo buzzer)
#P10 == open --- setting this high will activate the open input on the gate controller
#P11 == close --- activate the close input on the gatby e controller
#P12 == serinp --- #2400 baud serial input from card reader PCB
( Limit switch sensing )
{
GATE LIMIT SWITCH TRUTH TABLE
3 2 1 0 = INPUTS
------------------
0 1 0 1 = OPEN
1 1 1 1 = OPENING/CLOSING
1 0 1 0 = CLOSED
0 = closed2
1 = opened2
2 = closed1
3 = opened1
}
DECIMAL
pub LIMITS@ ( --- inputs ) --- pulldown inputs before reading and masking
$0F OUTCLR #10 us $0F INPUTS P@ %1111 AND
;
pub OPEN? ( -- flg )
LIMITS@ %0101 =
;
pub CLOSED? ( -- flg )
LIMITS@ %1010 =
;
( hardcoded master card number )
--- NOTE, could change this so that if the card file is blank then the first card read becomes the master.
#6201860 == mastercard
--- RFID SERIAL CARD READER 125kHz
--- FORMAT: 2400 BAUD : LF+360073E043+CR
--- 5100-18C3FC 0001623036
pub FLASH ( ms -- ) LED PINSET ms LED PINCLR ;
pub FLASHES ( n -- ) FOR #30 FLASH #150 ms NEXT ;
DOUBLE cardbuf --- assemble card id here and transfer to "card" when complete
DOUBLE card --- updated with latest valid number, app can clear this afterwards rather than using a flag.
BYTE cardcnt
#10 LONGS stk2 --- private data stack area for serial task
pub CardChar ( ch -- )
DUP >DIGIT --- try to convert it to a hex digit
IF ( ch val ) --- this character is a digit
NIP cardcnt C++
cardbuf @ 16 UM* ( val newval.l newval.h )
cardbuf 4 + @ 4 SHL + ( val newval.l newval2.h ) --- add in overflow into top 32-bits of double
cardbuf 4 + ! + cardbuf ! --- store double
ELSE ( ch ) --- not a digit
$0D = cardcnt C@ #10 = AND
IF
cardbuf card 8 CMOVE --- move completed number to "card"
cardcnt C@ card 7 + C!
#100 FLASH
THEN
cardbuf ~ --- clear cardbuf
cardcnt C~
THEN
;
--- Receive and process card data at 2400 baud, move from "cardbuf" to "card" when complete
pub SERIN.TASK
!SP stk2 SP! --- setup stack for this task
cardbuf ~ cardcnt C~
#2400 SERBAUD --- RFID card reader baud rate
BEGIN
!SP
LED PINCLR serinp SERIN LED PINSET --- get a character from the card reader & bleep
?DUP IF CardChar THEN
AGAIN
;
( TIME STAMPING )
pub MINUTES@ ( -- mins ) --- read hour and minutes of the day as minutes
TIME@ #100 U/ #100 U/MOD #60 * +
;
\ 1 month time stamp - 5 bits of day of month and 11 bits of minutes
pub STAMP@ ( -- dmmm ) --- read day date and hours and minutes and encode as 16-bits
DATE@ #100 MOD #11 SHL MINUTES@ +
;
{ FILE STRUCTURES
Card records are held in EEPROM. All card numbers are 5 bytes long but are converted to a byte index (1-255, 0=invalid) CARD FILE - EEPROM $9000-$97FF+4 8 bytes/record - 2kB = 255 records + dummy CARD(5) ATR(1) Attributes SPARE(2) TIMERS FILE - EEPROM $9810 weekdays(8b) minutes(11b),code(8b) CARD LOG - EEPROM $8000-$8FFF 4 bytes/record - 4kB = 1,023 records + eof marker STAMP(2) CARD INDEX(1) CODE(1) CARD NAMES (OPTIONAL) 32 byte records indexed by card index = 8kB NAME(32) |
}
( EEPROM FILE AREAS )
$8000 == LOGS --- logs are maintained in 2nd 32k section of EEPROM
$1000 == logsz --- size of log file where records are 4 bytes long
LOGS logsz + == CARDS
$800 == cardsz
( CARD FILE )
--- CARD RECORDS = CARD(5),ATR(1),SPARE(2)
--- this will add the current card to the valid card file
pub +CARD ( -- )
CARDS 8 + BEGIN DUP E@ 1+ WHILE 8 + REPEAT --- scan for a blank entry ( ~ 500us/entry)
( addr )
card @ OVER E! card 4 + @ SWAP 4 + E!
;
BYTE index --- a saved copy of the index of the last card processed (for logging)
--- lookup the current card in the card file and return with it's index else zero = false
pub CARD? ( -- index )
card @ DUP 0EXIT
CARDS cardsz + E!
CARDS 8 + BEGIN DUP E@ card @ <> WHILE 8 + REPEAT
CARDS - 8 U/ $FF AND
DUP index C! --- maintain a copy of the current index for logging purposes
;
pub .CARD ( index --- )
?DUP
IF
8 * CARDS + E@ $080A .NUM
ELSE
\ "*" 8 EMITS
THEN
;
pub LC --- list card file
pub lc --- list card file
pub .CARDS
." List cards "
CARDS 8 +
BEGIN
DUP E@ 1+
IF
CR ." #" DUP CARDS - 3 SHR $30A .NUM SPACE
DUP E@ $80A .NUM
THEN
8 + --- jump to next record 8 bytes away
DUP CARDS - cardsz =
UNTIL
DROP --- discard the pointer - chuck out the garbage as we mess it up
;
pub ERASE-CARDS CARDS cardsz ADO -1 I E! 4 +LOOP ;
pub FIX-CARDS
CARDS cardsz ADO
I E@ #1,000,000 U< IF -1 I E! -1 I 4 + E! THEN
8 +LOOP
;
pub AKEY ( -- ch ) --- always wait for a key from any device, that is, ignore nulls
BEGIN KEY ?DUP UNTIL DUP EMIT
;
pri GETDEC ( -- n )
0 BEGIN
AKEY
DUP "0" "9" WITHIN
WHILE
"0" - SWAP #10 * +
REPEAT
DROP
;
pub ADD-CARDS
BEGIN
AKEY
DUP "#" = IF GETDEC 3 SHL CARDS + GETDEC SWAP E! THEN
$1B =
UNTIL
;
--- RECORD: STAMP(2) INDEX(1) CODE(1)
LONG logptr --- write address of entry into log file
LONG logptr2
--- add the latest card to the log file, record the card index, the time stamp, and the action taken
--- if this code is the same as the last then don't create a new log entry, just overwrite the last
pub +LOG? ( code -- )
logptr2 @ 3 + LOGS + EC@ OVER = IF logptr2 @ logptr ! THEN
pub +LOG ( code -- )
#24 SHL STAMP@
index C@ 16 SHL + + --- create a 32-bit number from stamp(16),card(8),code(8)
logptr @ LOGS + E! --- store in EEPROM
logptr @ logptr2 ! --- update previous pointer with current
logptr @ 4 + logsz 1- AND DUP logptr ! --- update write pointer as wraparound
-1 SWAP LOGS + E! --- write a null to indicate end of log file
index C~
;
BYTE reset
--- init logging - find the location where we were writing to last, it should be a -1
pub SETLOG
LOGS BEGIN DUP E@ -1 <> WHILE 4 + REPEAT LOGS - logptr !
reset C++
reset C@ DUP index C! reset EC! --- log index as current reset number plus back it up.
"R" +LOG --- log this reboot
;
{ REPORTING LOGS
LL 17-03:06 OPEN #003 01563569 17-02:29 OPEN #007 01567269 17-03:53 RESET #002 01608827 17-03:56 RESET #002 01608827 17-03:59 RESET #002 01608827 17-08:44 RESET #002 01608827 17-08:40 RESET #002 01608827 17-09:12 RESET #002 01608827 17-09:13 OPEN #009 94967295 17-09:14 OPEN #009 94967295 17-09:14 OPEN #009 94967295 17-09:26 OPEN #008 06201860 17-09:27 OPEN #006 01598675 17-09:50 CLOSE #006 01598675 ok |
}
--- 0101 == inside closed - outside closed
--- 1101 == inside opening - outside closed
--- 1111 == inside opening - outside opening
--- 1011 == inside opened - outside opening
--- 1010 == inside opened - outside opening
\ 12345678123456781234567812345678
pub .CINDEX ( code -- index )
16 SHR >B DUP DUP IF ." #" $30A .NUM SPACE ELSE DROP ." * AUTO * " THEN --- display the index value
;
pub ATYPE ADO I C@ DUP BL <> IF EMIT ELSE DROP THEN LOOP ;
" fault opened closed swinging" 0 STRING gate$
pub .GATECODE ( code -- )
16 SHR >B
pub .GATES ( state -- )
." ["
DUP $0C AND 2* gate$ + 8 ATYPE
SPACE
3 AND 2* 2* 2* gate$ + 8 ATYPE
." ]"
;
--- Convert the single character code to a verbose label
pri .CODE ( code ch -- )
SWITCH
"O" CASE PRINT" OPENING GATE " .CINDEX .CARD BREAK
"C" CASE PRINT" CLOSING GATE " .CINDEX .CARD BREAK
"R" CASE PRINT" REBOOTING " .CINDEX DROP BREAK
"M" CASE PRINT" MASTER MODE " .CINDEX .CARD BREAK
"+" CASE PRINT" ADDING CARD " .CINDEX .CARD BREAK
"G" CASE PRINT" GATES MOVING " .GATECODE BREAK
"H" CASE PRINT" GATES CHECK " .GATECODE BREAK
2 SPACES SWITCH@ EMIT 3 SPACES --- or just the code plus spaces
;
pub .LOG ( addr -- ) --- print the log entry at this address
E@ DUP 1+ 0= IF DROP EXIT THEN
CR DUP #11 SHR $1F AND $20A .NUM ." -"
DUP $7FF AND #60 U/MOD $20A .NUM ." :" $20A .NUM
DUP #24 SHR SPACE .CODE --- display the log code
;
pub LL --- list log file (shortcut for bluetooth use)
pub ll --- list log file (shortcut for bluetooth use)
pub .LOGS
." List logs @" .DT
logptr @ 4 + logsz ADO I logsz 1- AND LOGS + .LOG 4 +LOOP
;
--- console commands to clear the files
pub ERASE-LOGS LOGS logsz ADO -1 I E! 4 +LOOP ;
pub INVALID card 8 ERASE ;
TIMER master --- just a timer/flag to indicate master mode is set
pub HEADER CR .DT SPACE ;
pub MASTER --- enter master mode with timeout
"M" +LOG
HEADER PRINT" YES MASTER "
#600,000 master TIMEOUT --- set master timer to 10 minutes (in ms)
#10 FLASHES card ~
;
\ This card didn't register but check to see if it's the master card
pub CHECK-MASTER
card @ mastercard = --- is this card the mastercard?
IF MASTER ELSE INVALID THEN
;
pub ADDING.CARD
HEADER PRINT" Adding card "
+CARD 5 FLASHES --- add a card into the file and acknowledge with 5 flashes
CARD? DROP --- generate an index for this new card
"+" +LOG
card ~
#600,000 master TIMEOUT --- retrigger master timeout while we are still adding cards
;
--- card is INVALID but check to see if master mode is enabled so we can make this card valid
pub CHECK-INVALID
master @
IF
card 4 + C@ --- and there is a proper card (5th byte is set)
IF ADDING.CARD ELSE INVALID THEN
ELSE
CHECK-MASTER
THEN
;
TIMER operation --- timing open/close operation, allows immediate abort if active
TIMER delay --- delay until open/close operation
TIMER autotmr --- autoclose timer - triggered on opening
WORD action
BYTE op,autoclose?
LONG autotime
pub MINUTES 60 *
pub SECONDS 1,000 * ;
{HELP AUTOCLOSE ( ms -- )
Change the time that the gate will automatically closed after non-timed opening during closing hours
Usage: 15 AUTOCLOSE
}
pub AUTOCLOSE ( minutes -- )
60,000 *
DUP autotime !
autotime E!
;
--- check for any delayed actions
pub CHECK-DELAYED
delay TIMEOUT? IF action W@ ?DUP IF CALL action W~ THEN THEN
;
#10 == exitdelay --- default exit delay in seconds
pub EXIT-DELAY
operation TIMEOUT?
IF
exitdelay #1000 * delay TIMEOUT
LED APIN 1 HZ --- automatic 1 flash/second (until muted)
THEN
;
pub C
pub c
pub CLOSE-NOW
MUTE
LED PINSET
#10,000 operation TIMEOUT
"C" op C!
close PINSET #500 ms close PINCLR
"C" +LOG
PRINT" -- gate now closing"
#500 FLASH
;
pub CLOSE
autotime @ IF 1 autoclose? C! THEN --- remember to autoclose from now on until reset
pub CLOSE2
PRINT" Closing gate "
EXIT-DELAY
' CLOSE-NOW action W!
;
pub O
pub o
pub OPEN-NOW
MUTE --- stop the automatic flashing
LED PINSET --- light up the card LED indicator ( 1 second total)
#10,000 operation TIMEOUT
"O" op C!
open PINSET #500 ms open PINCLR --- pulse the open signal to the TC-128 "open pin"
"O" +LOG --- log that we are now opening the gate
PRINT" -- gate now opening"
#500 FLASH
autoclose? C@
IF autotime @ autotmr TIMEOUT 2 autoclose? C! THEN --- close again after delay if autoclose set
;
pub OPEN
autoclose? C~ --- clear autoclose if this is a scheduled opening
pub OPEN2
PRINT" Opening gate "
EXIT-DELAY
' OPEN-NOW action W!
;
{ Terminal output for valid card
2014/04/21 16:45:40 01560448 #0003 Closing gate |
}
--- since the card was valid we either want to open or close the gate
pub VALID
delay @ --- if this is a valid card presented during a delay then treat it as an abort
IF
PRINT" -- aborting "
action W~ MUTE
ELSE
operation TIMEOUT? --- if it's in the middle of an operation then limit switches are invalid.
IF
OPEN? IF CLOSE2 ELSE OPEN2 THEN
ELSE --- can't rely on limit switches to tell us what to do so just reverse last op immediately
op C@ "C" = IF OPEN-NOW ELSE CLOSE-NOW THEN
THEN
1 second --- debounce, don't read same card too quickly
THEN
card ~ --- clear the card number (accepted)
;
--- using the "card" number scan the card file for a valid entry
pub CHECK-CARDS
card @ --- is there a new card? (otherwise zero)
IF --- we have a card number but is it valid?
HEADER card @ $080A .NUM SPACE
PRINT" #" CARD? DUP IF DUP .DEC ELSE PRINT" INVALID" THEN --- print the card index (0=not valid!!!)
mastercard card @ = master @ 0= AND NOT AND --- oh, and a master is a master first, access operation second
IF
VALID --- card has been validated so now check to see if we need to open or close
ELSE
CHECK-INVALID
THEN
THEN
;
BYTE limits --- change of state latch for gate limit switches
pub CHECK-GATES
LIMITS@ limits C@ <>
IF
LIMITS@
DUP CR ." GATE CHANGE = " $402 .NUM
DUP limits C! index C! "G" +LOG
#100 ms --- debounce
THEN
;
( SCHEDULING )
// define days of the week and their constants
// The month is 0 so that the date is interpreted as a day of week mask
pub MON ( -- day month ) 0 MASK 0 ;
pub TUE 1 MASK 0 ;
pub WED 2 MASK 0 ;
pub THU 3 MASK 0 ;
pub FRI 4 MASK 0 ;
pub SAT 5 MASK 0 ;
pub SUN 6 MASK 0 ;
pub WEEKDAYS %0011111 0 ;
pub WEEKENDS %1100000 0 ;
pub DAILY %1111111 0 ;
{
0 |< == MON
1 |< == TUE
2 |< == WED
3 |< == THU
4 |< == FRI
5 |< == SAT
6 |< == SUN
%0011111 == WEEKDAY
%1100000 == WEEKEND
7 MASKS == DAILY
}
1 == JAN
2 == FEB
3 == MAR
4 == APR
5 == MAY
6 == JUN
7 == JUL
8 == AUG
9 == SEP
#10 == OCT
#11 == NOV
#12 == DEC
pub AM ;
pub PM DUP #1200 < IF #1200 + THEN ;
{ TIMERS
Each long in the schedules array packs an action, a date or day mask, and the minute of the day
A ACTION[10] --- vector index for code to execute
Y DAY[1] --- if set then interpret MMDD as week day mask (0-6 = MON-SUN)
M MM[4] 1-12
D DD[5] 1-31
T minutes[12] --- time encoded as minutes of the day
If MM is 0 then DD = day of week mask (8 bits)
3322222222 2 2111 11111 110000000000
1098765432 1 0987 65432 109876543210
AAAAAAAAAA Y MMMM DDDDD TTTTTTTTTTTT
}
#64 == entries
#64 AVAR schedules
entries 3 * ALLOT
pub @SCH ( index -- addr ) 2* 2* schedules + ;
pub SAVESCH schedules DUP entries 2* 2* ESAVE ;
--- fetch the date for this schedule and a flag to indicate if it's a specific date or a day mask
pub SCH.DATE@ ( index -- MMDD or days.mask+$800 )
@SCH @ #12 SHR DUP 9 MASK AND
IF >B $800 +
ELSE DUP $1F AND SWAP 5 SHR >N #100 * +
THEN
;
--- fetch the time for this schedule - in minutes
pub SCH.TIME@ ( index -- time )
@SCH @ $0FFF AND
;
--- fetch the action for this schedule
pub SCH.JOB@ ( index -- cfa )
@SCH @ #22 SHR 2* XCALLS + W@
;
pub .SCHDAY
$7F AND SWITCH
$7F CASE PRINT" DAILY " BREAK
$1F CASE PRINT" WEEKDAY" BREAK
$60 CASE PRINT" WEEKEND" BREAK
7 0 DO I MASK SWITCH@ AND IF I 3 * " MONTUEWEDTHUFRISATSUN" + 3 CTYPE SPACE THEN LOOP
;
pub .SCHDATE
DUP $800 AND IF .SCHDAY
ELSE #100 U/MOD SWAP PRINT SPACE 1- 3 * " JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC" + 3 CTYPE SPACE
THEN
;
pub .SCH
I @SCH @ IF
CR I $20A .NUM PRINT" : "
" AM"
I SCH.TIME@ #60 U/MOD DUP #12 > IF #12 - ROT DROP " PM" ROT ROT THEN
SWAP <# # # DROP "." HOLD # # #> PRINT$ SPACE PRINT$ SPACE
I SCH.DATE@ .SCHDATE PRINT" WILL "
I SCH.JOB@ PFA>NFA PRINT$
THEN
;
pub LIST
DECIMAL
entries 0 DO
.SCH
LOOP
CR 4 SPACES autotime @ ?DUP IF 60,000 / PRINT ELSE PRINT" NO" THEN PRINT" AUTOCLOSE "
;
pub MINUTES@ ( -- minutes ) TIME@ #100 / #100 U/MOD #60 * + ;
WORD now
pub MINUTE? ( -- flg ) MINUTES@ now W@ OVER now W! <> ;
pub NOW? ( index -- flg ) SCH.TIME@ now W@ = ;
pub TODAY? ( index -- flg ) SCH.DATE@ DUP $800 AND IF DAY@ 1- MASK AND ELSE DATE@ #100 / = THEN ;
pub CHECK-SCHEDULE
MINUTE? --- every minute
IF
entries 1 DO --- scan through all the timers
I NOW? --- is there a match here?
I TODAY? AND
IF CR .DT SPACE .SCH
I SCH.JOB@ ?DUP IF CALL THEN --- perform the job request
THEN
LOOP
THEN
;
{HELP SCHEDULE
Start a new schedule by wiping the working copy in RAM
and clearing errors etc.
}
pub SCHEDULE
!SP errors W~
schedules entries 4 * ERASE --- clear all the timers - but backup is still in EEPROM for now
DECIMAL
;
{HELP DONE
Check for errors and finalize schedule by backing up to eeprom if there were no errors
}
pub DONE
DEPTH errors W@ OR IF CR ." Schedule has not been backed up due to errors "
ELSE CR ." Backing up settings" SAVESCH
THEN
;
pub +SCH ( long --- )
0 #64 1 DO I @SCH @ 0= IF I OR LEAVE THEN LOOP
?DUP IF @SCH ! THEN
;
{
Y DAY[1] --- if set then interpret MMDD as week day mask
M MM[4] 1-12
D DD[5] 1-31
3322222222 2 2111 11111 110000000000
1098765432 1 0987 65432 109876543210
AAAAAAAAAA Y MMMM DDDDD TTTTTTTTTTTT
}
pub WILL ( time day month <action> -- ) IMMEDIATE
[NFA'] NFA>CFA >VEC XCALLS - 2/ #22 SHL --- form the action code in the high bits of the long
[COMPILE] GRAB ( vec time day month ) --- grab the time day month
?DUP IF ( time date month ) --- process a specific date (if month is non-zero)
#17 SHL SWAP #12 SHL + --- form MMMM DDDDD
ELSE ( vec time day-mask ) --- handle field as a day of week mask (month = 0)
$200 + #12 SHL --- Set day of week bit
THEN
( vec time day ) SWAP #100 U/MOD #60 * + ( vec day minutes )
+ +
+SCH
;
TIMER checktimer
pub CHECK-TIMERS
--- if gate has had a non-scheduled opening then check to see if we are ready to close it again
autoclose? C@ 2 = IF autotmr TIMEOUT? CLOSED? NOT AND IF CLOSE THEN THEN
--- log regular checkup
checktimer TIMEOUT? IF #300,000 checktimer TIMEOUT LIMITS@ index C! "H" +LOG? THEN
;
pub CHECK-EEPROM
0 E@ CLKFREQ <> IF REBOOT THEN
;
\ generate a heartbeat by blinking the led and beeping very briefly every second or so
\ do this by reading the system counter
pub HEARTBEAT
delay @ NOT IF CNT@ $3FC.0000 AND $3FC.0000 = LED PIN! THEN --- heartbeat click and flash
;
--- main loop to check the cards and timers etc
pub EGATE.POLL
HEARTBEAT --- short blinks to indicate we're still alive
CHECK-CARDS --- check for any cards
CHECK-TIMERS --- check timers
CHECK-SCHEDULE
CHECK-GATES
CHECK-DELAYED
CHECK-EEPROM
#30,000 WATCHDOG --- kick it back into life if it somehow gets lost
;
--- main entry for EGATE, init tasks and timers etc
pub EGATE
CR EGATE.fth --- announce the application is up and running
CR .DT CR --- report the date and time
--- set a default date and time if it's not right
DATE@ #10,000 U/ #14 < IF PRINT" Warning!, time and date not set ! " #000101 DATE! #120000 TIME! THEN
card ~ --- init card variable
SETLOG --- find where we were writing to last and set the pointer
' SERIN.TASK 6 RUN --- run the serial input processing from the card in it's own task (actually 1 of 8 CPU cores)
' EGATE.POLL keypoll W! --- allow the console to continue running while we check cards etc in the background
0 checktimer TIMEOUT
0 delay TIMEOUT
0 operation TIMEOUT
0 autotmr TIMEOUT
#30,000 master TIMEOUT --- force master mode for 32 seconds after power-up
;
{ TERMINAL OUTPUT
NAMES: $59AA...7422 for 6776 (0054 bytes added) CODE: $0000...3ABA for 8258 (0028 bytes added) CALLS: 0396 vectors free RAM: 7920 bytes free
MODULES LOADED: 348E: EGATE.fth RFID Gate Access interface V1.0 140414.1200 - Peter Jakacki & Jack Stubbs 337A: MCP79410-RTC.fth MCP79410 I2C RTC DRIVER - 130529.1330 1880: EXTEND.fth Primary extensions to TACHYON kernel - 140402-14OO BOOT: EXTEND.boot BOOT: MAIN
RFID Gate Access interface V1.0 140414.1200 - Peter Jakacki & Jack Stubbs 2014/04/23 16:25:06 |
}
{ 10 second BCA analysis - sorted
64 : W@ 1202513
2B : 1 - 961997
CE : (IF) 721843
EB : (REG) 721567
16 : ?DUP 721507
17 : DUP 481349
21 : SWAP 481025
CD : (UNTIL) 240809
89 : 0 240799
0F : EXIT 240576
C2 : XCALL 240573
1A : OVER 240541
57 : = 240533
13 : 2DROP 240493
29 : + 608
62 : C@ 339
59 : 0= 330
5F : C@++ 314
04 : XOP 307
87 : 3 301
7E : (BYTE) 62
6A : C! 35
3A : AND 32
5C : > 24
2C : 1+ 22
28 : - 13
81 : BL 10
14 : DROP 6
6E : W! 6
7D : (WORD) 6
85 : 4 6
C9 : (AGAIN) 6
0D : 0EXIT 5
3E : OR 5
55 : >B 5
33 : U/MOD 4
84 : 1 4
E6 : >R 4
E9 : R> 4
36 : NIP 3
40 : XOR 3
6C : W+! 3
86 : 2 3
1C : 3RD 1
77 : CLR 1
88 : ON 1
BC : CALL 1
BF : VCALL 1
}
]~
END
--- Example of a schedule file that can be pasted in via the console - comments allowed
SCHEDULE - local trading hours 8.30 AM to 9.00 PM
07.30 AM DAILY WILL OPEN --- default opening time
09.30 PM DAILY WILL CLOSE
07.30 AM SUN WILL CLOSE --- don't open early on Sunday
09.30 AM SUN WILL OPEN --- open later on a Sunday
06.30 PM SUN WILL CLOSE --- early close on Sundays
05.30 PM SAT WILL CLOSE --- early close on Saturdays
05.30 PM TUE WILL OPEN
05.30 PM WED WILL OPEN
05.30 PM THU WILL OPEN
07.30 AM 8 JUN WILL CLOSE --- don't bother opening (overrides any previous schedule opening)
07.30 AM 25 DEC WILL CLOSE
07.30 AM 1 JAN WILL CLOSE --- always closed (need to improve and say "1 JAN CLOSED")
5 AUTOCLOSE --- will close automatically 5 mins after remotely opened
DONE
--- If CLOSE is selected then 15 min AUTOCLOSE stays in operation until a timed OPEN operation
AUTORUN EGATE
DATE@ build.date E! TIME@ build.time E!
?BACKUP
REBOOT