;-----------------------------------------
; CRT0BOOT.S
; by Oliver Kraus
;-----------------------------------------

;-----------------------------------------
; Stack and Jump Area
;-----------------------------------------
	.module  crt0boot.s

;   We could use a fixed and absolut area for the stack
;   .area   STACK  (ABS)
;   .org  0x0100
;   But it would be better to put it in the _BSS area.
;   This allows a more flexible adaption to other hardware.
	.area _BSS
__stack_end::
	.blkb 96         ; CHANGE THIS VALUE, IF THERE IS MORE MEMORY AVAILABLE
__stack_begin::


;-----------------------------------------
; Jump Area (put it into _BSS area)
;-----------------------------------------
	.area _BSS
__irt_table::
	.blkb 48

;-----------------------------------------
; Global System Variables
; Note, that the variable _os_null_ptr 
; can be found in crt0base.s
;-----------------------------------------

	.area   _BSS
_os_io_base::
	.blkb 2
_os_sei_cnt::
	.blkb 1

;-----------------------------------------
; Reset Code
;-----------------------------------------
		.area _CODE

__irt_none1:   ldx __irt_table
					jsr 0,x
					rti
__irt_none2:   ldx __irt_table+2
					jsr 0,x
					rti
__irt_none3:   ldx __irt_table+4
					jsr 0,x
					rti
__irt_sci:     ldx __irt_table+6
					jsr 0,x
					rti
__irt_spi:     ldx __irt_table+8
					jsr 0,x
					rti
__irt_paie:    ldx __irt_table+10
					jsr 0,x
					rti
__irt_pao:     ldx __irt_table+12
					jsr 0,x
					rti
__irt_to:      ldx __irt_table+14
					jsr 0,x
					ldx  _os_io_base
					ldaa #0x080          ; Clear timer overflow bit
					staa 0x025,x
					rti
__irt_toc5:    ldx __irt_table+16
					jsr 0,x
					rti
__irt_toc4:    ldx __irt_table+18
					jsr 0,x
					rti
__irt_toc3:    ldx __irt_table+20
					jsr 0,x
					rti
__irt_toc2:    ldx __irt_table+22
					jsr 0,x
					rti
__irt_toc1:    ldx __irt_table+24
					jsr 0,x
					rti
__irt_tic3:    ldx __irt_table+26
					jsr 0,x
					rti
__irt_tic2:    ldx __irt_table+28
					jsr 0,x
					rti
__irt_tic1:    ldx __irt_table+30
					jsr 0,x
					rti
__irt_rti:     ldx __irt_table+32   
					jsr 0,x
					ldx  _os_io_base     
					ldaa #0x040          ; Clear real-time interrupt-flag
					staa 0x025,x
					rti
__irt_irq:     ldx __irt_table+34
					jsr 0,x
					rti
__irt_xirq:    ldx __irt_table+36
					jsr 0,x
					rti
__irt_swi:     ldx __irt_table+38
					jsr 0,x
					rti
__irt_illegal: ldx __irt_table+40
					jsr 0,x
					rti
__irt_cop:     ldx __irt_table+42
					jsr 0,x
					rti
__irt_clock:   ldx __irt_table+44
					jsr 0,x
					rti


__dummy_rts::
			rts

__build_irt_table:
			ldy  #__dummy_rts
			ldx  #__irt_table
			ldab #24
1$:      sty  0,x
			inx
			inx
			decb
			bne  1$
			rts

;-----------------------------------------------------------
__irt_reset:
;-----------------------------------------------------------
 
; RAM and I/O Mapping Register
; RAM Position: $0000 (Bit 4-7)    I/O Position: $1000 (Bit 0-3)
			ldx  #0x1000      ;  3  0
			stx  _os_io_base  ;  4  3  
			ldaa #0x01        ;  2  7
			staa 0x3d,x       ;  5  9

; Main Timer and Real-Timer Interrupt/Pulse Accumulator Register
; Timer Overflow Enable (Bit 7):
;      0   No Timer Overflow Interrupt
;      1   Timer Overflow Interrupt
; Real Time Interrupt Enable (Bit 6):
;      0   No Real Time Interrupt
;      1   Real Time Interrupt
; Timer Prescalar Select (Bit 0-1):
;     00   Factor 1
;     01   Factor 4
;     10   Factor 8
;     11   Factor 16
;
			ldaa #0b11000011     ;  2 14
			staa 0x24,x          ;  5 16


; OPTION Register
;     Bit 7: Analog/Digital Conversion Charge pump (1 = on)
;     Bit 6: A/D und EEPROM clock select (hier: 0 = E-Clock)
;     Bit 5: IRQ Edge-Sensitive  (0 = default)
;     Bit 4: Delay (1 = default)
;     Bit 0-1: Watchdog Rate
;          Bits   Div.Faktor
;          00     1
;          01     4
;          10    16
;          11    64
			ldaa #0x093    ;  2 21
			staa 0x039,x   ;  5 23

; pulse accu ctrl register (PACTL)
;  Bit 8: direction Bit 7 Port A (0 = input)
;  Bit 7: pulse accu enable (1 = enable)
;
;  Bit 2-3: 0
;  Bit 0-1: (RTR1, RTR0) RTI Rate:
;  RTR1, RTR0     8 MHz
;   0     0      4.10 ms
;   0     1      8.19 ms  (hier)
;   1     0     16.38 ms
;   1     1     32.77 ms
;
			ldaa #0b00000001
			staa 0x26,x

			lds     #__stack_begin-1   ; initialize stack pointer
			jsr     __build_irt_table  ; build the interrupt table

			ldx     #0                 ; clear the NULL pointer
			stx     *_os_null_ptr      

			clr     _os_sei_cnt        ; clear interrupt disable counter

			cli
			jsr     _main              ; main()
_exit::;

exit::   bra     exit
___main::
			rts   ; return from function


;-----------------------------------------
; _os_set_irq
; C-Call: void os_set_irq(int number, void (*fn)() )
;-----------------------------------------

_os_set_irq::
			pshy  ; Save stack frame
			tsy   ; Set current stack frame
			pshx

			ldd   *ZD0
			clra
			lsld
			addd  #__irt_table
			xgdx
			ldd   4,y
			std   0,x

			pulx
			puly  ; Restore stack frame
			rts   ; return from function

;-----------------------------------------
; _os_set_irq
; C-Call: void (*os_get_irq(int number))()
;-----------------------------------------

_os_get_irq::
			pshy  ; Save stack frame
			tsy   ; Set current stack frame
			pshx

			ldd   *ZD0
			clra
			lsld
			addd  #__irt_table
			xgdx
			ldd   0,x
			std   *ZD0

			pulx
			puly  ; Restore stack frame
			rts   ; return from function


;-----------------------------------------
; _os_disable
; C-Call: void os_disable()
;-----------------------------------------
_os_disable::
			sei
			inc _os_sei_cnt
			rts

;-----------------------------------------
; _os_enable
; C-Call: void os_enable()
;-----------------------------------------
_os_enable::
			tst _os_sei_cnt
			beq 1$
			dec _os_sei_cnt
			bne 1$
			cli
1$:      rts
			

;-----------------------------------------
; Boot-Table
;-----------------------------------------
	.area   BOOTLIST     (ABS)
	.org    0xffd0
	.word   __irt_none1           ; 0xffd0
	.word   __irt_none2           ; 0xffd2
	.word   __irt_none3           ; 0xffd4
	.word   __irt_sci             ; 0xffd6  SCI Serial System
	.word   __irt_spi             ; 0xffd8  SPI Serial Transfer complete
	.word   __irt_paie            ; 0xffda  Pulse Akku Input Edge
	.word   __irt_pao             ; 0xffdc  Pulse Akku Overflow
	.word   __irt_to              ; 0xffde  Timer Overflow
	.word   __irt_toc5            ; 0xffe0
	.word   __irt_toc4            ; 0xffe2
	.word   __irt_toc3            ; 0xffe4
	.word   __irt_toc2            ; 0xffe6
	.word   __irt_toc1            ; 0xffe8
	.word   __irt_tic3            ; 0xffea
	.word   __irt_tic2            ; 0xffec
	.word   __irt_tic1            ; 0xffee
	.word   __irt_rti             ; 0xfff0  Real Time Interrupt
	.word   __irt_irq             ; 0xfff2  Maskable Interrupt, Interrupt Request (IRQ)
	.word   __irt_xirq            ; 0xfff4  Nonmaskable Interrupt Request (XIRQ)
	.word   __irt_swi             ; 0xfff6  Software Interrupt (SWI)
	.word   __irt_illegal         ; 0xfff8  Illegal Opcode
	.word   __irt_cop             ; 0xfffa  COP Watchdog Time-Out
	.word   __irt_clock           ; 0xfffc  Clock Monitor Fail
	.word   __irt_reset           ; 0xfffe  Power On Reset (POR) oder RESET Pin
