;************************************************************************ ; ; Miniature Realtime Controller V2.0 ; ws 25 July 1994 ; 1st modified 3 December 1995 ; for a miniature 89C2051 SCM ; 2KB code memory ; specifications: ; 89c2051 @3.579545MHz + MAX232C + 74LS07 ; programmed via serial port using on-chip data memory for saving timing ; control code. ;************************************************************************ ; ; CPU "8051.TBL" HOF "INT8" ; ; ;MCS-51 INTERNAL REGISTERS ; B: EQU 0F0H ;B REGISTER ACC: EQU 0E0H ;ACCUMULATOR PSW: EQU 0D0H ;PROGRAM STATUS WORD IPC: EQU 0B8H ;INTERRUPT PRIORITY P3: EQU 0B0H ;PORT 3 IEC: EQU 0A8H ;INTERRUPT ENABLE P2: EQU 0A0H ;PORT 2 SBUF: EQU 99H ;SEND BUFFER SCON: EQU 98H ;SERIAL CONTROL P1: EQU 90H ;PORT 1 TH1: EQU 8DH ;TIMER 1 HIGH TH0: EQU 8CH ;TIMER 0 HIGH TL1: EQU 8BH ;TIMER 1 LOW TL0: EQU 8AH ;TIMER 0 LOW TMOD: EQU 89H ;TIMER MODE TCON: EQU 88H ;TIMER CONTROL PCON: EQU 87H ;POWER CONTROL REGISTER DPH: EQU 83H ;DATA POINTER HIGH DPL: EQU 82H ;DATA POINTER LOW SP: EQU 81H ;STACK POINTER P0: EQU 80H ;PORT 0 ; ;MCS-51 INTERNAL BIT ADDRESSES ; CY: EQU 0D7H ;CARRY FLAG AC: EQU 0D6H ;AUXILIARY-CARRY FLAG F0: EQU 0D5H ;USER FLAG 0 RS1: EQU 0D4H ;REGISTER SELECT MSB RS0: EQU 0D3H ;REGISTER SELECT LSB OV: EQU 0D2H ;OVERFLOW FLAG P: EQU 0D0H ;PARITY FLAG PS: EQU 0BCH ;PRIORITY SERIAL PORT PT1: EQU 0BBH ;PRIORITY TIMER 1 PX1: EQU 0BAH ;PRIORITY EXTERNAL 1 PT0: EQU 0B9H ;PRIORITY TIMER 0 PX0: EQU 0B8H ;PRIORITY EXTERNAL 0 EA: EQU 0AFH ;ENABLE ALL INTERRUPT ES: EQU 0ACH ;ENABLE SERIAL INTERRUPT ET1: EQU 0ABH ;ENABLE TIMER 1 INTERRUPT EX1: EQU 0AAH ;ENABLE EXTERNAL 1 INTERR ET0: EQU 0A9H ;ENABLE TIMER 0 INTERRUPT EX0: EQU 0A8H ;ENABLE EXTERNAL 0 INTERR SM0: EQU 09FH ;SERIAL MODE 0 SM1: EQU 09EH ;SERIAL MODE 1 SM2: EQU 09DH ;SERIAL MODE 2 REN: EQU 09CH ;SERIAL RECEPTION ENABLE TB8: EQU 09BH ;TRANSMITT BIT 8 RB8: EQU 09AH ;RECEIVE BIT 8 TI: EQU 099H ;TRANSMIT INTERRUPT FLAG RI: EQU 098H ;RECEIVE INTERRUPT FLAG TF1: EQU 08FH ;TIMER 1 OVERFLOW FLAG TR1: EQU 08EH ;TIMER 1 RUN CONTROL BIT TF0: EQU 08DH ;TIMER 0 OVERFLOW FLAG TR0: EQU 08CH ;TIMER 0 RUN CONTROL BIT IE1: EQU 08BH ;EXT INTERR. 1 EDGE FLAG IT1: EQU 08AH ;EXT INTERR. 1 TYPE FLAG IE0: EQU 089H ;EXT INTERR. 0 EDGE FLAG IT0: EQU 088H ;EXT INTERR. 0 TYPE FLAG ; PORT 1 BIT ADDRESS P1.0: EQU 090H ; START COMMAND P1.1: EQU 091H ; select A-B only or A-B-C-D P1.2: EQU 092H ; P1.3: EQU 093H ; P1.4: EQU 094H ; output soleniod #4 option P1.5: EQU 095H ; output solenoid #3 option P1.6: EQU 096H ; output solenoid #2 ---> A-C P1.7: EQU 097H ; output solenoid #1 ---> A-B p2.0: equ 0a0h ; time base indicator p2.1: equ 0a1h ; clock out 50.000 Hz for calibration ! p2.2: equ 0a2h ; tone output p3.0: equ 0b0h p3.1: equ 0b1h p3.2: equ 0b2h p3.3: equ 0b3h p3.4: equ 0b4h p3.5: equ 0b5h p3.6: equ 0b6h p3.7: equ 0b7h SAVE_L: EQU 048H ; SAVE POINTER USE IN INTERRUPT SERVICE SAVE_H: EQU 049H ; ROUTINE STATE: EQU 038H ; STATE BYTE 1 = TIME ; 2 = PROGRAM ; RAM BIT ADDRESS serial: equ 18h ; on/off send data sim: equ 19h ; simulate mode (speed-up test) blink: equ 1Ah output: equ 21h ; 16 bit output cuntrol 21h 22h KEY: EQU 0BH LED: EQU 08H ; INTERRUPT BLINK XOFF_FLAG:EQU 0AH ZEROING: EQU 0DH VALVE: EQU 0EH CYCLE_COUNT: EQU 0FH ;current time storage sec100: equ 25h sec: equ 26h min: equ 27h hour: equ 28h day: equ 29h MONTH: EQU 2AH YEAR: EQU 2BH warm_code: equ 2Eh light: equ 2dh econo: equ 2ch tl0adj: equ 2fh pgm_buffer: equ 30h ; start from 30h RECEIVE_BUFFER: EQU 4AH TOP_FIFO: EQU 1000H ; TOP OF FIFO BUFFER CR: EQU 0DH LF: EQU 0AH EOS: EQU 10H BELL: EQU 07H ;****************************************************** ; ORG 000H LJMP MAIN_TIMER org 003h ljmp service_int0 ; for airconditioner start manually ORG 00BH LJMP SERVICE_T0 ; TIMER COUNTER 0 INTERRUPT ORG 0100H ;INIT_RS232C INITIALIZED 89C2051 SERIAL PORT ; BAUD RATE: 9600 ; DATA LENGTH: 8 BIT ; STOP BIT: 1 BIT ; PARITY: NO ; X-TAL: 3.579545 MHz INIT: MOV TMOD,#00100001B MOV SCON,#01010010B MOV PCON,#10000000B ; smod = 1 MOV TH1,#0FEH ;TIMER1 LOAD VALUE SETB TR1 ;START TIMER1 RET ;SEND SEND A TO SERIAL PORT ; CHECK TRANSMITTER BUFFER BEFORE SEND ; ; ENTRY: A ; EXIT: NO ; SEND: JNB TI,SEND CLR TI MOV SBUF,A ;OK BUFFER EMPTY SEND OUT... RET ; ;RECIVES RECIVE BYTE FROM SERIAL PORT WITH TIME-OUT FUNCTION ; ENTRY: NO ; EXIT: A = ASCII NUMBER OR STRING COMMAND ; A = FF TIME-OUT RECIVES: MOV R7,#05H AGAIN: MOV R6,#00H ; TIME-OUT DELAY GET_RI: JB RI,READY DJNZ R6,GET_RI DJNZ R7,AGAIN MOV A,#0FFH ; TIME-OUT NO DATA RECEPTED RET READY: CLR RI MOV A,SBUF RET ;RECIVE RECIVE BYTE PUT TO A FROM SERIAL PORT ; WAIT UNTIL RECIVER BUFFER READY ; ENTRY: NO ; EXIT: A RECIVE: JNB RI,RECIVE CLR RI MOV A,SBUF ; GET IT LCALL SEND ; ECHO TO TERMINAL RET ;SEND_PROMPT SEND_PROMPT: LCALL CR_LF MOV DPTR,#PROMPT LCALL SEND_STRING RET ;CR_SEND SEND CR TO RS232 ; ENTRY: NO ; EXIT: NO ; CR_LF: MOV A,#CR LCALL SEND MOV A,#LF LCALL SEND RET XOFF: EQU 13H XON: EQU 11H BREAK: EQU 00H EOF: equ 0FH ;SEND_XOFF SEND XOFF TO RS232 ; ENTRY: NO ; EXIT: NO ; SEND_XOFF: MOV A,#XOFF ;GET XOFF CHARACTER LCALL SEND RET ;SEND_XON ; ; ; SEND_XON: MOV A,#XON LCALL SEND RET ;SPACE SPACE: MOV A,#20H LCALL SEND RET ;ASCII_BIN CONVERTS SINGLE ASCII CHARACTER TO SINGLE NIBBLE ; BINARY ; ENTRY: A ( 30-39 for 0-9, 41-46 for A-F, 61-66 for a-f) ; EXIT: A ; ignor lower case clr bit 5 before ASCII_BIN: CLR C MOV R6,A SUBB A,#41H JNC ASCII_AF MOV A,R6 CLR C SUBB A,#30H RET ASCII_AF: CLR C MOV A,R6 SUBB A,#37H RET ;COMBINE DATA 2 BYTE TO SINGLE BYTE ; ENTRY: R4= LOW NIBBLE ; R5= HIGH NIBBLE ; EXIT: A ; COMBINE: MOV A,R5 SWAP A ADD A,R4 RET ;GET_BYTE GET DATA FROM SERIAL PORT TWO BYTE SAVE TO ; R5 AS A HIGH NIBBLE AND R4 AS A LOW NIBBLE ; ENTRY: NO, serial port must be initialzed before calling ; EXIT: A ; ; GET_BYTE: LCALL RECIVE ; FIRST READING MUST GO TO R5 !! LCALL ASCII_BIN MOV R5,A LCALL RECIVE LCALL ASCII_BIN MOV R4,A LCALL COMBINE RET ;BIN_ASCII CONVERT BIN TO ASCII CODE ; ENTRY: A ; EXIT : A BIN_ASCII: ANL A,#0FH MOV R2,A CLR C SUBB A,#0AH JNC ASCII_AF2 MOV A,R2 ADD A,#30H RET ASCII_AF2: MOV A,R2 ADD A,#37H RET ;BYTE_ASCII CONVERT A TO ASCII IN R4, R5 BYTE_ASCII: MOV B,A LCALL BIN_ASCII MOV R4,A MOV A,B SWAP A LCALL BIN_ASCII MOV R5,A RET ;SEND_ASCII SEND ASCII IN R5(HI) R4(LO) BYTE TO MONITOR ; INPUT : A ; OUTPUT : NONE SEND_ASCII: LCALL BYTE_ASCII MOV A,R5 LCALL SEND MOV A,R4 LCALL SEND RET ;NIBBLE_SHIFT SHIFT FOUR DIGIT BCD NUMBER LEFT A NIBBLE ; ENTRY : R0 POINTED TO LSD ; EXIT : NO NIBBLE_SHIFT: INC R0 MOV A,@R0 SWAP A ANL A,#0F0H MOV R1,A DEC R0 MOV A,@R0 SWAP A MOV R2,A ANL A,#0FH ADD A,R1 INC R0 MOV @R0,A MOV A,R2 ANL A,#0F0H DEC R0 MOV @R0,A RET ;SHIFT_16BIT SHIFT LEFT 1 BIT ADDRESS $3D,$3E ; $3D LO BYTE ; $3E HI BYTE ; ENTRY: NO ; EXIT: Carry Flag SHIFT_16BIT: CLR C ; {($3E,$3D)} X 2 MOV A,3DH ADD A,3DH MOV 3DH,A MOV A,3EH ADDC A,3EH MOV 3EH,A RET ; CARRY GONE ;BIN_BCD CONVERT 16 BIT BINARY TO BCD ; SHIFT LEFT 1 BIT FROM MOST SIGNIFICANT BIT TO LEAST SIGNIFICANT ; BIT , IF CARRY = 1 THEN BCD= (2^N + BCD) ; ; ENTRY: 16 BIT DATA ; $3D = LO BYTE ; $3E = HI BYTE ; EXIT: 6 DIGIT BCD ; $36L = 0 ; $36H = 10 ; $37L = 100 ; $37H = 1000 ; $38L = 10000 ; $38H = 100000 BIN_BCD: MOV 36H,#00 ; CLEAR BCD BEFORE MOV 37H,#00 MOV 38H,#00 MOV R1,#00H MOV R7,#16D BIN_1: LCALL SHIFT_16BIT JNC NEXT_BIT ; OK CARRY = 1 ADD BCD TO 2^N CONSTANT IN TABLE2 MOV DPTR,#TABLE2 CLR C MOV R0,#36H MOV R6,#03H BIN_2: MOV A,R1 MOVC A,@A+DPTR ADDC A,@R0 DAA MOV @R0,A INC DPTR INC R0 DJNZ R6,BIN_2 NEXT_BIT: INC R1 INC R1 INC R1 DJNZ R7,BIN_1 RET TABLE2: DFB 68H,27H,03H DFB 84H,63H,01H DFB 92H,81H,00H DFB 96H,40H,00H DFB 48H,20H,00H DFB 24H,10H,00H DFB 12H,05H,00H DFB 56H,02H,00H DFB 28H,01H,00H DFB 64H,00H,00H DFB 32H,00H,00H DFB 16H,00H,00H DFB 08H,00H,00H DFB 04H,00H,00H DFB 02H,00H,00H DFB 01H,00H,00H ;######################################################################## ; TIMER 0 INTERRUPT SERVICE ROUTINE # ; enter to this routine every 1/10 Hz # ; update current time and date # ; check current day and time every 1 sec # ; if current time = set time the activates 8 output bit # ; # ;######################################################################## SERVICE_T0: PUSH PSW PUSH ACC PUSH B PUSH DPL PUSH DPH MOV PSW,#00001000B ; SELECT REGISTER BANK 1 ; TIMER 0 SERVICE BODY ; cpl p3.5 ; check time base should be 10/2 Hz MOV TH0,#COUNT_H MOV TL0,tl0adj ; get low byte adjustable lcall light_on inc sec100 ; mov a,sec100 cjne a,#0AH,CHECK_SEC ; update second every 10 counts inc econo mov a,econo cjne a,#05h,skip_econo mov econo,#00h setb blink clr p3.7 ; turn on light every 5 second ; since inc sec100 as binary skip_econo: lcall io_out jnb serial,no_send LCALL SEND_TIME no_send: mov sec100,#00h mov a,sec add a,#01d daa mov sec,a CHECK_SEC: mov a,sec cjne a,#60H,CHECK_MIN jnb sim,min_send lcall send_time min_send: mov sec,#00d mov a,min add a,#01d daa mov min,a CHECK_MIN: mov a,min cjne a,#60H,CHECK_HOUR mov min,#00d mov a,hour add a,#01d daa mov hour,a CHECK_HOUR: mov a,hour cjne a,#24h,check_day mov hour,#00d mov a,day add a,#01d daa mov day,a check_day: lcall get_month_day mov a,day cjne a,b,check_month mov day,#01d mov a,month add a,#01d daa mov month,a check_month: mov a,month cjne a,#13h,check_year mov month,#01d mov a,year add a,#01d daa mov year,a check_year: POP DPH POP DPL POP B POP ACC POP PSW RETI ;send_output send output (display) to terminal for simulate test send_outputs: lcall space lcall space mov r6,#01d ; tiny timer 8 bit I/O $21 mov dptr,#output_prompt lcall send_string mov r0,#output outer: mov r7,#08d mov a,@r0 cpl a ; sink current drive circuit MOV P1,A ; send current output to port 1 cpl a mov b,a inner: mov a,b rlc a mov b,a jc on_contact mov a,#"-" lcall send lcall space sjmp next_bits on_contact: mov a,#"O" lcall send lcall space next_bits: djnz r7,inner inc r0 djnz r6,outer ret ;light_on blink led shows time base is run light_on: jnb blink,led_on ; if blink not set do not count down mov a,light inc a mov light,a cjne a,#01h,led_on mov light,#00h setb p3.7 ; off light clr blink ; finished blink led_on: ret ;send_tone send tone like beep beep to p2.2 send_tone: mov r7,#00h tone0: clr p2.2 mov r6,#50h tone1: djnz r6,tone1 setb p2.2 mov r6,#50h tone2: djnz r6,tone2 djnz r7,tone0 ret ;BCD_ASCII CONVERT BCD NUMBER TO ASCII CODE ; ENTRY: A {LOW NIBBLE ONLY} ; EXIT: A BCD_ASCII: ANL A,#0FH ;GET ONLY LOW NIBBLE ADD A,#30H ;CONVERT TO ASCII CODE RET ;send current time send_time: LCALL CR_LF MOV A,DAY LCALL SEND_ASCII MOV A,#"-" LCALL SEND MOV A,MONTH LCALL SEND_ASCII MOV A,#"-" LCALL SEND MOV A,#25H LCALL SEND_ASCII MOV A,YEAR LCALL SEND_ASCII LCALL SPACE MOV A,HOUR LCALL SEND_ASCII MOV A,#":" LCALL SEND MOV A,MIN LCALL SEND_ASCII MOV A,#":" LCALL SEND MOV A,SEC LCALL SEND_ASCII lcall send_outputs RET ;io_out send output o1-o8 when current time = setting time ; scan setting time and compare current time ; if current time = set time then activate i/o ; els next set time till eof found io_out: mov r0,#pgm_buffer io0: mov a,@r0 cjne a,#eof,io1 ret io1: jb p3.5,skip_day ; if p3.7 = 0 then skip day checking cjne a,day,io4 ; check day skip_day: inc r0 mov a,@r0 cjne a,hour,io2 ; check hour inc r0 mov a,@r0 cjne a,min,io3 ; check min inc r0 ; current time = set time mov a,@r0 ; get output mov output,a ; put to output byte cpl a ; i.e., sink current is used for driving LED mov p1,a ; activate port 1 also ret io4: inc r0 io2: inc r0 io3: inc r0 inc r0 sjmp io0 ;GET_MONTH_DAY get day-end of each month, e.g. Jan=31, Feb=28, Mar=31,.. ; ,etc. ; entry: current month 01,02,03,...,12 ; exit: B = day-end ; get_month_day: mov a,month ; get current month clr c subb a,#10h jc bcd_is_binary mov a,month clr c subb a,#06h sjmp convert_to_binary bcd_is_binary: mov a,month convert_to_binary: dec a mov dptr,#day_end_table movc a,@a+dptr mov b,a inc b ; to compensate increment day before ret day_end_table: dfb 31h ; Jan dfb 28h ; Feb dfb 31h ; Mar dfb 30h ; Apr dfb 31h ; May dfb 30h ; Jun dfb 31h ; Jul dfb 31h ; Aug dfb 30h ; Sep dfb 31h ; Oct dfb 30h ; Nov dfb 31h ; Dec ;BUFFER_ASCII CONVERT BCD IN BUFFER START $30 - $35 ; ENTRY: BCD NUMBER IN TRANSMIT BUFFER ; EXIT: ASCII CODE IN TRANSMIT BUFFER BUFFER_ASCII: MOV R7,#06H MOV R0,#30H NEXT_ASCII: MOV A,@R0 LCALL BCD_ASCII MOV @R0,A INC R0 DJNZ R7,NEXT_ASCII RET ;SEND_BUFFER SEND ASCII CODE IN TRANSMIT BUFFER TO SERIAL PORT ; THEN DATA SEPERATOR /32/32 ; ENTRY: ASCII CODE IN TRANSMIT BUFFER ; EXIT: NO SEND_BUFFER: MOV R7,#06H MOV R0,#35H NEXT_BYTE: MOV A,@R0 LCALL SEND ;SEND OUT TO SERIAL PORT DEC R0 DJNZ R7,NEXT_BYTE lcall cr_lf RET ;service_int0 activates three output port manually service_int0: push acc setb 0fh mov a,output cpl a mov p1,a pop acc reti ;COMPARE TWO 16 BIT BINARY NUMBER ; ENTRY: R0 FIRST OPERAND ; R1 SECOND OPERAND ; EXIT: C=1 FIRST OPERAND < SECOND OPERAND ; C=0 FIRST OPERAND >= SECOND OPERAND COMPARE: CLR C ; MOV A,@R0 SUBB A,@R1 INC R0 INC R1 MOV A,@R0 SUBB A,@R1 RET ; ;########################################################################### ;# MAIN PROGRAM # ;########################################################################### CURRENT_TIME_L: EQU 40H CURRENT_TIME_H: EQU 41H CURRENT_PROG_L: EQU 42H CURRENT_PROG_H: EQU 43H COUNT_L: EQU 92h ;7AH ; <--- find adjust in case of oscillation ; frequency is not a 3.579545 MHz COUNT_H: EQU 8BH ; interrupt every 3.579545 MHz/12*(65536-29830) ; = 10 Hz MAIN_TIMER: MOV SP,#60H ; stack area start $60-$7F mov light,#00h mov p1,#11111111b ; off output clr serial ; clr blink mov sec100,#00h mov econo,#00h mov tl0adj,#92h ; for adjustment later via user calibrate mov a,warm_code cjne a,#"%",cold_boot sjmp warm_boot cold_boot: mov warm_code,#"%" mov pgm_buffer,#eof ; blank pgm at power up MOV SEC,#00D MOV MIN,#30H MOV HOUR,#12H MOV DAY,#29H MOV MONTH,#04H MOV YEAR,#37H mov output,#00h warm_boot: SETB EA ; ENABLE ALL INTERRUPT SETB ET0 ; ENABLE TIMER 0 INTERRUPT setb ex0 ; enable external interrupt MOV TMOD,#00000001B ; SET MODE 1 T0 (16 BIT DIVIDER) LCALL INIT SETB PT0 ; TIMER 0 HIGHEST PIORITY MOV DPTR,#TITLE LCALL SEND_STRING mov th0,#count_h ;start timer mov tl0,#count_l setb tr0 ;start timer TEST10: jnb ri,test10 ; polls receive buffer and wait command clr ri mov a,sbuf cjne a,#"A",skip_modem_init ; SKIP MODEM INITIALISED STRING lcall recive ; SEARCH "AT" STRING cjne a,#"T",skip_modem_init dummy_init: lcall recive cjne a,#cr,dummy_init ; UNTIL END OF STRING sjmp test10 skip_modem_init: orl a,#20h ; accept upper & lower cjne a,#"o",com10 sjmp off_serial com10: cjne a,#"t",com11 sjmp transmit_time com11: cjne a,#"z",com12 sjmp adjust_clock com12: cjne a,#"e",com13 sjmp set_time com13: cjne a,#"d",com14 sjmp set_date com14: cjne a,#"?",com15 ljmp print_com com15: cjne a,#"s",com16 ljmp speed_up com16: cjne a,#"p",com17 ljmp program_time com17: cjne a,#"r",com18 ljmp read_pgm com18: cjne a,#"c",com19 ljmp clear_io com19: cjne a,#"/",com20 ljmp once com20: lcall send_prompt LJMP TEST10 RUN2: MOV TL0,#COUNT_L MOV TH0,#COUNT_H SETB TR0 ; START TIMER RET ;off_serial stop transmit current date and time to terminal off_serial: clr serial LCALL SEND_PROMPT sjmp test10 ;transmit_time start send current date and time to terminal transmit_time: setb serial sjmp test10 ;adjust_clock change low byte of timer 0 adjust_clock: lcall cr_lf mov a,tl0adj lcall send_ascii lcall cr_lf mov a,#"?" lcall send lcall get_byte mov tl0adj,a lcall send_prompt ljmp test10 ;set_time enter current time set_time: mov dptr,#time_set lcall send_string lcall get_byte mov hour,a ; save hour lcall get_byte mov min,a ; save min lcall get_byte mov sec,a ; save sec lcall send_time lcall send_prompt ljmp test10 ;set_date enter current date set_date: mov dptr,#date_set lcall send_string lcall get_byte mov day,a lcall get_byte mov month,a lcall get_byte mov year,a lcall send_time lcall send_prompt ljmp test10 ;print_com shows command listing print_com: mov dptr,#command lcall send_string lcall send_prompt ljmp test10 ;speed_up simulate output at high speed speed_up: cpl sim ljmp test10 ;program_time wait file from terminal write to on chip ram ; start $30-$63 60 bytes or 20 line accepted ; program format: ; :01 05 2030 1 1 0 1 0 0 1 1crlf ; :02 06 2120 1 0 0 0 1 1 0 1crlf ; :00crlf ; where ; : initiate start of line ; 01 record 1,2,3,... ; 05 date ; 2030 time ; 1 1 0 1 0 0 1 1 digital output ; crlf end of line flag ; 00 end of record flag ; ; maximum program storage provides 7 days, i.e. each day require four ; byte, thus total byte is 28 bytes from $30 - $50 program_time: clr tr0 ; stop timer before so after program mov dptr,#program ; loading is finished actual time need lcall send_string ; to be adjusted again. lcall cr_lf mov r0,#pgm_buffer pgm1: lcall recive cjne a,#":",pgm1 lcall get_byte ; skip line cjne a,#00h,pgm2 ; end of file detected sjmp stop_pgm pgm2: lcall recive ; skip space lcall get_byte ; get date byte mov @r0,a ; save date lcall recive ; skip space inc r0 lcall get_byte ; get hour byte mov @r0,a ; save hour inc r0 lcall get_byte mov @r0,a ; save min inc r0 mov r7,#08d ; get control I/O bit pgm3: lcall recive ; skip space lcall recive ; mov b,a ; lcall SEND_XOFF ; pause string sending from terminal ; mov a,b cjne a,#"0",pgm4 clr c sjmp pgm5 pgm4: setb c pgm5: mov a,@r0 rlc a mov @r0,a ; lcall SEND_XON ; ready to receive again djnz r7,pgm3 ; loop 8 times pgm6: lcall recive cjne a,#lf,pgm6 inc r0 sjmp pgm1 ; read next line stop_pgm: mov @r0,#eof ; end of file lcall recive cjne a,#lf,stop_pgm mov dptr,#finish_pgm lcall send_string lcall send_prompt setb tr0 ; resume timer interrupt again ljmp test10 ;read_pgm read internal program for checking ; reteive internal program send to terminal for checking ; or changing current settings read_pgm: lcall cr_lf mov r0,#pgm_buffer read2: mov a,@r0 cjne a,#eof,read3 ; until eos (0FH) found mov dptr,#end_of_file lcall send_string sjmp read4 read3: lcall send_ascii ; send day lcall space inc r0 mov a,@r0 ; get hour lcall send_ascii ; send hour mov a,#":" lcall send inc r0 mov a,@r0 lcall send_ascii ; send min lcall space mov dptr,#output_prompt lcall send_string inc r0 mov a,@r0 mov r7,#08h read_io: rlc a mov b,a jc send_on mov a,#"-" lcall send sjmp next_io_bit send_on: mov a,#"O" lcall send next_io_bit: lcall space mov a,b djnz r7,read_io lcall cr_lf inc r0 sjmp read2 read4: lcall send_prompt ljmp test10 ;clear_io clear all 8 bit p1.0-p1.7 clear_io: mov output,#00000000b mov p1,#11111111b ; clear port1 also lcall send_time ; display results lcall send_prompt ljmp test10 ;once read current time once once: lcall send_time lcall send_prompt ljmp test10 ;SEND_STRING SEND STRING CONSTANT TO TERMINAL ; ENTRY: DPTR ; EXIT: FOUND EOS ; SEND_STRING: CLR A MOVC A,@A+DPTR CJNE A,#EOS,SEND_STRING1 RET SEND_STRING1: PUSH DPL PUSH DPH LCALL SEND POP DPH POP DPL INC DPTR SJMP SEND_STRING ;********************************************************************** ; STRING CONSTANT AREA ;********************************************************************** TITLE: DFB cr,lf,"Miniature Realtime Controller RTC-3707",CR,LF DFB "Designed by Wichit Sirichote" DFB CR,LF PROMPT: DFB "& ",EOS command: dfb cr,lf dfb "o return prompt",cr,lf dfb "t send time",cr,lf dfb "z adj. time base",cr,lf dfb "e enter current time",cr,lf dfb "d enter current date",cr,lf dfb "s stroke setting",cr,lf dfb "p program timer",cr,lf dfb "r read program",cr,lf dfb "c clear I/O",cr,lf dfb "/ send time once",cr,lf dfb "? help command",cr,lf dfb eos finish_pgm: dfb "Program stored",cr,lf,eos program: dfb cr,lf,"Ready to receive program",eos output_prompt: dfb "OUTPUT [1..8] ",eos time_set: dfb cr,lf,"Enter current time > ",eos date_set: dfb cr,lf,"Enter current date > ",eos end_of_file: dfb "EOF",eos WHAT?: DFB "WHAT?",CR,LF,EOS END