; Various functions: init, (RAM) disk, mmc, timer ; This file needs to get split up. ; ; Copyright (C) 2010 Sprite_tm ; Copyright (C) 2010 Leo C. ; ; This file is part of avrcpm. ; ; avrcpm is free software: you can redistribute it and/or modify it ; under the terms of the GNU General Public License as published by ; the Free Software Foundation, either version 3 of the License, or ; (at your option) any later version. ; ; avrcpm is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with avrcpm. If not, see . ; ; $Id$ ; ; ------------------- DRAM Refresh Interrupt -------------------- .cseg ; Refresh interupt; exec 2 cbr cycles INTERRUPT OC2Aaddr sbis P_RAS,ram_ras ;2 reti ; CAS RAS cbi P_CAS,ram_cas ;2 1| 1| ; 1| 1| cbi P_RAS,ram_ras ;2 |0 1| ; |0 1| nop ;1 |0 |0 ; nop ;1 |0 |0 sbi P_RAS,ram_ras ;2 |0 |0 ; |0 |0 dram_wait DRAM_WAITSTATES-1 ; | | ; nop ;1 |0 |0 cbi P_RAS,ram_ras ;2 |0 1| ; |0 1| sbi P_CAS,ram_cas ;2 |0 |0 ; |0 |0 sbi P_RAS,ram_ras ;2 1| |0 ; 1| 1| reti ;4 --> 21 cycles ;Print a unsigned lonng value to the uart ; temp4:temp3:temp2:temp = value print_ultoa: push yh push yl push z_flags push temp4 push temp3 push temp2 push temp clr yl ;yl = stack level ultoa1: ldi z_flags, 32 ;yh = temp4:temp % 10 clr yh ;temp4:temp /= 10 ultoa2: lsl temp rol temp2 rol temp3 rol temp4 rol yh cpi yh,10 brcs ultoa3 subi yh,10 inc temp ultoa3: dec z_flags brne ultoa2 cpi yh, 10 ;yh is a numeral digit '0'-'9' subi yh, -'0' push yh ;Stack it inc yl cp temp,_0 ;Repeat until temp4:temp gets zero cpc temp2,_0 cpc temp3,_0 cpc temp4,_0 brne ultoa1 ldi temp, '0' ultoa5: cpi yl,3 ; at least 3 digits (ms) brge ultoa6 push temp inc yl rjmp ultoa5 ultoa6: pop temp ;Flush stacked digits rcall uartputc dec yl brne ultoa6 pop temp pop temp2 pop temp3 pop temp4 pop z_flags pop yl pop yh ret ;Prints temp2:temp in hex to the uart printhexw: push temp mov temp,temp2 rcall printhex pop temp ;fall thru ;Prints temp in hex to the uart printhex: swap temp rcall printhexn swap temp ;fall thru ;Prints the lower nibble printhexn: push temp andi temp,0xf cpi temp,0xA brlo printhexn_isno subi temp,-7 printhexn_isno: subi temp,-'0' rcall uartputc pop temp ret ;Prints the zero-terminated string following the call statement. printstr: push zh push zl push yh push yl push temp in yh,sph in yl,spl ldd zl,y+7 ldd zh,y+6 lsl zl rol zh printstr_loop: lpm temp,z+ cpi temp,0 breq printstr_end rcall uartputc cpi temp,13 brne printstr_loop ldi temp,10 rcall uartputc rjmp printstr_loop printstr_end: adiw zl,1 ;rounding lsr zh ror zl std y+7,zl std y+6,zh pop temp pop yl pop yh pop zl pop zh ret .dseg .cseg ; **************************************************************************** ; ------------- system timer 1ms --------------- .dseg delay_timer1: .byte 1 delay_timer2: .byte 1 timer_base: timer_ms: .byte 2 timer_s: .byte 4 ; don't change order here, clock put/get depends on it. cntms_out: ; register for ms .byte 2 utime_io: ; register for uptime. .byte 4 cnt_1ms: .byte 2 uptime: .byte 4 timer_top: .equ timer_size = timer_top - timer_base .equ clkofs = cnt_1ms-cntms_out .equ timerofs = cnt_1ms-timer_ms .cseg ; Timer/Counter1 Compare Match B interrupt INTERRUPT OC1Baddr push zl in zl,SREG push zl push zh inm8 zl,OCR1BL inm8 zh,OCR1BH addiw z,F_CPU/1000 outm8 OCR1BH,zh outm8 OCR1BL,zl #if DRAM_8BIT /* Implies software uart */ lds zl,srx_char_to subi zl,1 brcs syscl0 sts srx_char_to,zl brne syscl0 rcall srx_to syscl0: #endif lds zl,delay_timer1 subi zl,1 brcs syscl_t1n sts delay_timer1,zl syscl_t1n: lds zl,delay_timer2 subi zl,1 brcs syscl_t2n sts delay_timer2,zl syscl_t2n: lds zl,cnt_1ms lds zh,cnt_1ms+1 adiw z,1 sts cnt_1ms,zl sts cnt_1ms+1,zh cpi zl,low(1000) ldi zl,high(1000) ;doesn't change flags cpc zh,zl brlo syscl_end sts cnt_1ms,_0 sts cnt_1ms+1,_0 lds zl,uptime+0 inc zl sts uptime+0,zl brne syscl_end lds zl,uptime+1 inc zl sts uptime+1,zl brne syscl_end lds zl,uptime+2 inc zl sts uptime+2,zl brne syscl_end lds zl,uptime+3 inc zl sts uptime+3,zl syscl_end: pop zh pop zl out SREG,zl pop zl reti ; wait for temp ms delay_ms: sts delay_timer1,temp dly_loop: lds temp,delay_timer1 cpi temp,0 brne dly_loop ret ; clockget: ldi temp,0xFF subi temp2,TIMER_MSECS brcs clkget_end ;Port number in range? ldiw z,cntms_out breq clkget_copy ;lowest byte requestet, latch clock cpi temp2,6 brsh clkget_end ;Port number to high? add zl,temp2 brcc PC+2 inc zh ld temp,z clkget_end: ret clkget_copy: ldi temp2,6 cli clkget_l: ldd temp,z+clkofs st z+,temp dec temp2 brne clkget_l sei lds temp,cntms_out ;req. byte in temp ret clockput: subi temp2,TIMERPORT brcs clkput_end ;Port number in range? brne clkput_1 ; clock control cpi temp,starttimercmd breq timer_start cpi temp,quitTimerCmd breq timer_quit cpi temp,printTimerCmd breq timer_print cpi temp,uptimeCmd brne cp_ex rjmp uptime_print cp_ex: ret timer_quit: rcall timer_print rjmp timer_start clkput_1: dec temp2 ldiw z,cntms_out breq clkput_copy ;lowest byte requestet, latch clock cpi temp2,6 brsh clkput_end ;Port number to high? add zl,temp2 brcc PC+2 inc zh st z,temp clkput_end: ret clkput_copy: st z,temp adiw z,5 ldi temp2,6 cli clkput_l: ldd temp,z+clkofs st z+,temp dec temp2 brne clkput_l sei ret ; start/reset timer ; timer_start: ldiw z,timer_ms ldi temp2,6 cli ts_loop: ldd temp,z+timerofs st z+,temp dec temp2 brne ts_loop sei ret ; print timer ; timer_print: push yh push yl ldiw z,timer_ms ; put ms on stack (16 bit) cli ldd yl,z+timerofs ld temp2,z+ sub yl,temp2 ldd yh,z+timerofs ld temp2,z+ sbc yh,temp2 brsh tp_s addiw y,1000 sec tp_s: push yh push yl ldd temp,z+timerofs ld yl,z+ sbc temp,yl ldd temp2,z+timerofs ld yh,z+ sbc temp2,yh ldd temp3,z+timerofs ld yl,z+ sbc temp3,yl sei ldd temp4,z+timerofs ld yh,z+ sbc temp4,yh printnewline printstring "Timer running. Elapsed: " rcall print_ultoa printstring "." pop temp pop temp2 ldi temp3,0 ldi temp4,0 rcall print_ultoa printstring "s." pop yl pop yh ret uptime_print: ldiw z,cnt_1ms cli ld temp,z+ push temp ld temp,z+ push temp ld temp,z+ ld temp2,z+ ld temp3,z+ sei ld temp4,z+ printnewline printstring "Uptime: " rcall print_ultoa printstring "," ldi temp3,0 ldi temp4,0 pop temp2 pop temp rcall print_ultoa printstring "s." ret ; --------------- Debugging stuff --------------- ; Print a line with the Z80 main registers ;.if INS_DEBUG zflags_to_ch: .db "SZ H PNC",0,0 printregs: printnewline push zl push zh ldiw z,zflags_to_ch*2 mov temp2,z_flags pr_zfl_next: lpm temp,z+ tst temp breq pr_zfl_end cpi temp,' ' ; Test if no flag breq pr_zfl_noflag sbrs temp2,7 ; ldi temp,' ' ; Flag not set rcall uartputc pr_zfl_noflag: rol temp2 rjmp pr_zfl_next pr_zfl_end: pop zh pop zl printstring " A =" mov temp,z_a rcall printhex printstring " BC =" lds temp2,z_b lds temp, z_c rcall printhexw printstring " DE =" lds temp2,z_d lds temp, z_e rcall printhexw printstring " HL =" lds temp2,z_h lds temp, z_l rcall printhexw printstring " SP =" movw temp, z_spl rcall printhexw printstring " PC =" movw temp, z_pcl rcall printhexw printstring " " movw xl,z_pcl mem_read rcall printhex printstring " " adiw x,1 mem_read rcall printhex printstring " " adiw x,1 mem_read rcall printhex printstring " " ret ;.endif