; ===============================================================================

; Ping Pong - Picoblaze application for the BASYS kit
;
; # The command below will create a BlockROM for the hardware design
VHDL "JTAG_Loader_ROM_form.vhd", "Display_demo_rom.vhd""Display_demo_rom"
; # The commands below will download code directly to BROM via JTAG
; # Note! Will only works with Printerport JTAG or Xilinx USB JTAG programmer
; COE "Romfile.COE"
; EXEC "JTAG_LOADER.BAT"
; # Please comment out the commands above when not used

; ==============================================================================
; Port Definitions DSIO = both IN and OUT locations
Bcd0 DSIO 0 ; Least significant digit
Bcd1 DSIO 1 ; Least significant digit
Bcd2 DSIO 2 ; Least significant digit
Bcd3 DSIO 3 ; Least significant digit
Bcd_lo DSIO 4 ; Two least sign. digits
Bcd_hi DSIO 5 ; Two most sign. digits
Dp DSIO 6 ; Four decimal points
Timer_Scale DSOUT 7 ; Timer scale (1 = 0.01 sec)
Led DSIO 9 ; 8-Leds
DIPSW_port DSIN 20 ; 8-Dip Switches
Buttons DSIN 21 ; 4-push buttons
; ----------------------------------------------------------------------------
Scan_Code DSIN 24 ; From keyboard
Scan_Ready DSIN 25 ; Bit0 = Readyflag
; ----------------------------------------------------------------------------
VideoRAM DSIO 32 ; 4-bit <- Line:Pixel
Line DSIO 33
Pixel DSIO 34
NewLine DSOUT 35 ; Automatic Line+1
NewPixel DSOUT 36 ; Automatic Pixel+1
CrLf DSOUT 37 ; Automatic Line:Pixel+1

HCnt DSIN 40
VCnt DSIN 41

; =============================================================================
; = Register usage
; =============================================================================
R0 EQU s0
R1
EQU s1
R2
EQU s2
R3
EQU s3
R4
EQU s4
R5
EQU s5
R6
EQU s6
R7
EQU s7
R8
EQU s8
; -----------------------------Special register use----------------------------
R_Button EQU s9
R_State
EQU sA
; -----------------------------Interrupt registers-----------------------------
; This registers should only be used in ISR or rutines call from ISR
IR0 EQU sB ; Reg used by Interrupt
IR1 EQU sC ; Reg used by Interrupt
IR2 EQU sD ; Reg used by Interrupt
; -----------------------------Not used in this program------------------------
Mode_reg EQU sF ; operating mode of processor


Start_Stop EQU %010000 ; <- R_Button
Lap_Reset EQU %100000 ; <- R_Button
; ============================================================================
; = Scratch pad memory locations
; ============================================================================
Counter EQU 0
Counter_HB EQU 1

; -----------------------------------------------------------------------------
Last_Buttons EQU 18

Half_sec EQU 20
; -----------------------------------------------------------------------------
; Initialise the system
;
Cold_Start: LOAD R0, 5
OUT R0, Timer_Scale
LOAD R0, $0B
OUT R0, Dp
LOAD R0, 5
OUT R0, Line
OUT R0, Pixel
EINT ; enable interrupt
;
; #############################################################################
; # M a i n must be called from every state
; #############################################################################
Main:

; ==============================================================================
Demo_loop:
wait0:
IN R0, Scan_Ready
TEST R0, 1
JUMP NZ, Wait0
wait1:
IN R0, Scan_Ready
TEST R0, 1
JUMP Z, wait1
ADD R1, 1
OUT R1, Led
IN R0, BCD_lo
OUT R0, BCD_hi
IN R0, Scan_Code
OUT R0, BCD_lo
JUMP Demo_loop

; == Called by interrupt =======================================================
; This rutine let Decimal Point 2 toggle every 0.5 sec
Half_Sec_Rutine:
IN IR1, Dp
XOR IR1, $04
OUT IR1, Dp
RET
no_blink:
LOAD IR1, $0F
OUT IR1, Dp
RET

; == Called by interrupt =======================================================
; This rutine will detect if any Buttons pressed since the last call
; Detections will be stored in Button_Reg together with the actual status
Scan_button_rutine:
IN IR0, Buttons ; Read New xxxx.3210 buttons
FETCH IR1, Last_Buttons ; Get the Last scan
STORE IR0, Last_Buttons ; Remember the xxxx.3210 for later
XOR IR1, $0F ; Negate bit 3..0
AND IR1, IR0 ; Pressed <= not Last and New
SL0 IR1
SL0 IR1
SL0 IR1
SL0 IR1
OR R_Button, IR1 ; Set if any pressed
AND R_Button, $F0
OR R_Button, IR0
RET

; ==============================================================================
Pattern1:
IN IR0, VideoRAM
ADD IR0, 1
OUT IR0, NewLine
IN IR0, VideoRAM
ADD IR0, 1
OUT IR0, CrLf
RET
; ==============================================================================
Pattern2:
IN IR0, VideoRAM
IN IR1, DIPSW_port
ADD IR0, IR1
OUT IR0, NewLine
IN IR0, VideoRAM
ADD IR0, 1
OUT IR0, CrLf

RET
; ==============================================================================
Demo_Counter:
FETCH IR0, Counter
ADD IR0, 1
STORE IR0, Counter
OUT IR0, Bcd_Lo
FETCH IR0, Counter + 1
ADDC IR0, 0
STORE IR0, Counter + 1
OUT IR0, Bcd_Hi
RET
; ==============================================================================
Analyser:
LOAD IR2, 2
IN IR1, Scan_Ready
TEST IR1, %01000000
JUMP NZ, xxx
LOAD IR2, 4
xxx:
OUT IR2, CrLf
RET
; == Called by interrupt ======= Interrupt service routine (ISR) ===============
ORG $3E0
ISR:
CALL Pattern2

RETI ENABLE
;
; Interrupt vector
;
ORG $3FF
JUMP ISR
END