; Simple Picoblaze application for the BASYS kit

;
VHDL "JTAG_Loader_ROM_form.vhd", "Display_demo_rom.vhd", "Display_demo_rom"
; COE "Romfile.COE"
; EXEC "JTAG_LOADER.BAT"
; Port definitions
;
; ====================================================================
DIPSW_port DSIN $08 ; 8-Dip Switches
Buttons DSIN $09 ; 4-push buttons

Bcd0 DSIO $00 ; Least significant digit
Bcd1 DSIO $01 ; Least significant digit
Bcd2 DSIO $02 ; Least significant digit
Bcd3 DSIO $03 ; Least significant digit
Bcd_lo DSIO $04 ; Two least sign. digits
Bcd_hi DSIO $05 ; Two most sign. digits
Dp DSIO $06 ; Four decimal points
Scale DSOUT $07 ; Time scale for display
LEDS_port DSOUT $08 ; 8-Leds

; This Scale not testet yet - please try
; =============================================================================
;
; Special Register usage
;
mode_reg EQU sF ; operating mode of processor
;
; Two registers to form a 16-bit counter used to count
; interrupt pulses generated at 1us intervals.
;
int_counter_lsb EQU sD ; lower 8-bits
int_counter_msb EQU sC ; upper 8-bits
seconds EQU s5
minuts
EQU s6
hours
EQU s7
;
;
; ============================================================================
; scratch pad memory locations
temp EQU 5 ; used to save other values
;
;
; UART character strings will be stored in scratch pad memory ending in CR.
; A string can be up to 16 characters with the start location defined by this .
;
string_start DS $10

; Initialise the system
;
cold_start:
LOAD s0, $33
OUT s0, LEDS_port ;

; CALL Delay250ms
; CALL Delay250ms
; CALL Delay250ms
; CALL Delay250ms

LOAD s0, $55
OUT s0, LEDS_port ;

CALL Delay250ms

LOAD s2, $75
STORE s2, temp ; save value
FETCH s3, temp ; retrieve value
;
LOAD int_counter_lsb, $0F; clear 'us' interrupt counter
LOAD int_counter_msb, 0
OUT int_counter_lsb, Dp

EINT ; enable the 1us interrupts
;
;
; Start of the main program loop.
;

main_loop:
IN s4, Buttons
TEST s4, 2
CALL NZ, Show_DIPSW
TEST s4, 1
JUMP NZ, main_loop
ADD Seconds, 1
ADDC Minuts, 0
OUT Seconds, Bcd_lo
OUT Minuts, Bcd_hi
; OUT int_counter_lsb, Bcd_lo
; OUT int_counter_msb, Bcd_hi
Show_Counter:
OUT int_counter_msb, LEDS_port
JUMP main_loop
; =============================================================================
Show_DIPSW:
IN s0, DIPSW_port
OUT s0, LEDS_port ; turn on leds
CALL Delay250ms
RET

; =============================================================================
delay1us: ; 1us delay loop - assumes 50MHz clock
LOAD s0, 12 ; need to check this delay
delay1us1: SUB s0, $01
JUMP NZ, delay1us1
RET
; =============================================================================
delay16ms: ; approx. 16ms delay loop - assumes 50MHz clock
LOAD s2, $50 ; 80 decimal
delay16ms0: LOAD s1, $C8 ; 200 decimal (need to check this delay)
delay16ms1: CALL delay1us
SUB s1, 1
JUMP NZ, delay16ms1
SUB s2, 1
JUMP NZ, delay16ms0
RET

; =============================================================================
delay250ms: ; approx. 250ms delay loop - assumes 50MHz clock
; RET ; for debug purposes
LOAD s3, 16 ; need to check this delay
delay250_1: CALL delay16ms
SUB s3, $01
JUMP NZ, delay250_1
RET

; =============================================================================
; Interrupt service routine (ISR)
;
; The interrupt is used to increment a 16-bit counter formed with two registers
; called [int_counter_msb,int_counter_lsb]. This provides a count of the number
; of micro-seconds elapsed. The counter is 'free running' in that it will count
; up to 65,535 and then roll over to zero. The count value is then used in other
; parts of the program as required and where it is less time critical.
;
; The ISR only uses the specified counter registers
;
ORG $3FC
ISR:
ADD int_counter_lsb, 1 ; add 1us to 16-bit counter
ADDC int_counter_msb, 0
RETI ENABLE
;
; Interrupt vector
;
ORG $3FF
JUMP ISR