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

; S t a r t e r 1 _ D e m o - Picoblaze application for the BASYS or NEXYS kit
;
; # The command below will create a BlockROM for the hardware design
VHDL "JTAG_Loader_ROM_form.vhd", "Starter1_rom.vhd", "Starter1_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
Hex0 DSIO 0 ; Least significant digit
Hex1 DSIO 1 ; Least significant digit
Hex2 DSIO 2 ; Least significant digit
Hex3 DSIO 3 ; Least significant digit
Hex_lo DSIO 4 ; Two least sign. digits
Hex_hi DSIO 5 ; Two most sign. digits
Dp DSIO 6 ; Four decimal points
Blanking DSIO 7 ; Display Blanking
Timer_Scale DSIO 8 ; Timer scale (1 = 0.01 sec)
Led DSIO 9 ; 8-Leds

DIPSW_port DSIN 20 ; 8-Dip Switches
Buttons DSIN 21 ; 4-push buttons
JA DSIN 22 ; 4-bit PMOD
; --------------------------------------------- Hardware multiplier ----------
A DSOUT 32
B DSOUT 33
AxB_LowByte DSIN 32
AxB_HighByte DSIN 33
; =============================================================================
; = 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 ; Button: pressed / hold down
R_State EQU sA ; State register (used ???)
; -----------------------------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

; ============================================================================
; = Scratch pad memory locations
; ============================================================================
Count_0 EQU 0 ; Low byte
Count_1 EQU 1 ;
Count_2 EQU 2 ;
Count_3 EQU 3 ; High byte
Counter EQU 4 ; Low byte of a x-byte counter
Rotary_Cnt EQU 32 ; For test purpose

Last_Buttons EQU 63 ; Temp Storage

; -----------------------------------------------------------------------------
; Initialise the system
Cold_Start: LOAD R0, 1 ; Scale rate 1 = ???
OUT R0, Timer_Scale ; Timer used for interrupt
LOAD R0, $0F
OUT R0, Dp ; Turn of all Decimal points
LOAD R0, $0C
OUT R0, Blanking ; Blank two leftmost disp.
EINT ; enable interrupt
Demo_loop:
CALL Counter_routine2 ; Allways call ..
CALL Demo_calls1 ; Demostration calls
JUMP Demo_loop ; Repeat
; The main program loop stops here
; =============================================================================
; (note 1) The routine must not change the Z flag - which the case here.
Demo_Calls1:
IN R8, Buttons ; Read 4 Buttons to R8
TEST R8, 1 ; Test if Btn0 pressed
CALL Z, Rotary_encoder1 ; If not call .. (note 1)
CALL NZ, Display_demo1 ; If pressed call ..
TEST R8, 2
CALL NZ, Counter_routine1 ; Call if Btn1 pressed
TEST R8, 4
CALL NZ, Indirect_demo1 ; Call if Btn2 pressed
TEST R8, 8
CALL NZ, Indirect_demo2 ; Call if Btn3 pressed
RET
; =============================================================================
Display_demo1:
IN R0, DIPSW_port ; Read 8 Switches to R0
OUT R0, Led ; Write to 8 Leds
OUT R0, Hex_lo ; Display at rightmost Displays
LOAD R0, $0C
OUT R0, Blanking ; Blank two leftmost Displays
RET
; =============================================================================
Rotary_encoder1: ; Drehschalt-encoder
IN R0, JA ; Read from PMOD @ JA(1 to 4)
OUT R0, led ; Display @ Leds
RET
; =============================================================================
Counter_routine1:
LOAD R0, 0 ; R0 = constant = 0
OUT R0, Blanking ; No displays blanked
IN R2, Hex_lo ; Read low byte
ADD R2, 1 ; + 1
OUT R2, Hex_lo ; Store low byte
IN R2, Hex_hi ; Read high byte
ADDC R2, 0 ; + Carry
OUT R2, Hex_hi ; Store high byte
RET
; =============================================================================
Counter_routine2:
LOAD R0, Counter ; Let R0 point first Counter byte
Counter_loop:
LOAD R1, 1 ; In order to set Carry=1
SR0 R1 ; Two instrucions needed
FETCH R1, R0 ; Read a byte of the counter
ADDC R1, 0 ; Add one
STORE R1, R0 ; Write the byte back
RET NC ; Return if no carry
ADD R0, 1 ; Point at the next byte
JUMP Counter_loop ; Repeat

; =============================================================================
Indirect_demo1:
LOAD R0, 0
OUT R0, Blanking ; Use all four 7-segm disp.
LOAD R0, Hex3 + 1 ; R0 = address of Hex3+1
loopx:
SUB R0, 1 ; Let R0 point at next Disp.
OUT R0, R0 ; Display value of R0
RET Z ; Return if Zero
JUMP loopx ; One more turn
; ==============================================================================
Indirect_demo2:
LOAD R0, 0
OUT R0, Blanking ; Use all four 7-segm disp.
IN R0, DIPSW_port ; R0= Dip switches
ADD R0, Count_0 ; R0= pointer to Count_0
FETCH R1, R0 ; R1= Byte from Internal RAM
OUT R1, Hex_lo ; Display rightmost
ADD R0, 1 ; Point at next byte
FETCH R1, R0 ; Fetch next RAM byte
OUT R1, Hex_hi ; Display leftmost

RET
; ==============================================================================
Multiplier_demo:
LOAD R0, 0
OUT R0, Blanking
IN R4, DIPSW_port ; R4 = Switch 7:0
AND R4, $0F ; R4 = 0000 & Switch 3:0
OUT R4, A ; A = Switch 3:0
OUT R4, Hex0 ; Display at Hex 0
IN R4, DIPSW_port ; R4 = Switch 7:0
SR0 R4 ; R4 = 0 & Switch 7:1
SR0 R4 ; R4 = 00 & Switch 7:2
SR0 R4 ; R4 = 000 & Switch 7:3
SR0 R4 ; R4 = 0000 & Switch 7:4
OUT R4, B ; A = Switch 7:4
OUT R4, Hex1 ; Display at Hex 1
IN R4, AxB_LowByte ; Get low byte of result
OUT R4, Hex_Hi ; Display at Hex 3 + Hex 2
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

; == Called by interrupt ======= Interrupt service routine (ISR) ===============
ORG $3E0
ISR:
CALL Scan_button_rutine
FETCH IR2, Count_0
ADD IR2, 1
STORE IR2, Count_0
FETCH IR2, Count_1
ADDC IR2, 0
STORE IR2, Count_1
FETCH IR2, Count_2
ADDC IR2, 0
STORE IR2, Count_2
FETCH IR2, Count_3
ADDC IR2, 0
STORE IR2, Count_3
RETI ENABLE
;
; ============== Interrupt vector ==============================================
ORG $3FF
JUMP ISR
END
; PPM_Leds_on DSIO 10
; PCM0 DSIO 11
; PCM1 DSIO 12
; PCM2 DSIO 13
; PCM3 DSIO 14
; PCM4 DSIO 15
; PCM5 DSIO 16
; PCM6 DSIO 17
; PCM7 DSIO 18
Starter1_demo.htm