                  ; KCPSM3 PicoBlaze DIGITAL-OSZILLOSKOP by cm 1/2009
                  ; Wave-RAM auslesen und anzeigen
                  ; Referenz-Triggerpunkt wird von wave_ram berechnet,
                  ; wir fangen immer bei Adresse 0 an
                  ; Port-Definitionen
                  ;Eingangsports
                  CONSTANT in_status, 00
                  CONSTANT in_ps2, 01
                  CONSTANT in_triglevel, 02
                  CONSTANT in_hystlevel, 03
                  CONSTANT in_y1base, 04
                  CONSTANT in_y2base, 05
                  CONSTANT in_offsetlow, 06
                  CONSTANT in_offsethi, 07
                  CONSTANT in_wave1data, 08
                  CONSTANT in_wave2data, 09
                  ;Ports in parser.vhd
                  CONSTANT out_adrlow, 10
                  CONSTANT out_adrhi, 11
                  CONSTANT out_data, 12
                  ;Ports extern
                  CONSTANT out_control, 40
                  CONSTANT out_triglevel, 42
                  CONSTANT out_hystlevel, 43
                  CONSTANT out_wavelow, 46    ;Wave-RAM-Adresse
                  CONSTANT out_wavehi, 47
                  ;Grafik-Befehle
                  CONSTANT gcmd_xdata, 00
                  CONSTANT gcmd_ydata, 01
                  CONSTANT gcmd_move, 02
                  CONSTANT gcmd_point, 03
                  CONSTANT gcmd_line, 04
                  CONSTANT gcmd_rect, 05
                  CONSTANT gcmd_fill, 06
                  CONSTANT gcmd_xtrig, 08
                  CONSTANT gcmd_ytrig, 09
                  CONSTANT gcmd_xgrid, 0C
                  CONSTANT gcmd_ygrid, 0D
                  CONSTANT gcmd_color, 0F
                  ;Text-Befehle
                  CONSTANT tcmd_xcursor, 20
                  CONSTANT tcmd_ycursor, 21
                  CONSTANT tcmd_color, 23
                  ;Scratchpad Memory 4 x 8 Bytes
                  NAMEREG s3, y1
                  NAMEREG s4, y2
                  NAMEREG s5, y1base
                  NAMEREG s6, y2base
                  ;NAMEREG s7, xcount
                  NAMEREG s8, x
                  NAMEREG s9, y
                  NAMEREG sA, tptr_low
                  NAMEREG sB, tptr_hi
                  NAMEREG sC, acc
                  NAMEREG sD, mode            ; Plot-Mode
                  NAMEREG sE, color           ; Plot-Color
                  NAMEREG sF, mask
                  ;
                  ;=========================================================================
                  ;Hauptschleife
                  ;=========================================================================
      cold_start: 
                  CALL init
          aquire: 
                  CALL reset_trigger
                  LOAD tptr_low, 00
                  LOAD acc, 20                ; " "
                  CALL txt_wr
    wait_aquired: 
                  CALL refresh
                  INPUT s0, in_status         ; Trigger DONE true abwarten
                  TEST s0, 04
                  JUMP Z, wait_aquired
                  CALL disable_trigger
                  LOAD tptr_low, 00
                  LOAD acc, 54                ; "T"
                  CALL txt_wr
          getkey: 
                  INPUT s0, in_ps2
                  COMPARE s0, 2D              ; R-Taste
                  JUMP Z, aquire
                  COMPARE s0, 29              ; Space-Taste STOP/Einzelschritt
                  JUMP Z, getkey
                  INPUT s0, in_status         ; Key-Status
                  TEST s0, 08
                  CALL wait_key_release
                  JUMP aquire
         refresh: 
                  CALL wait_framedone
                  CALL gclear
                  CALL y1display
                  CALL y1logic
                  ;CALL y2display
                  RETURN
         y1logic: 
                  INPUT y1base, in_y1base
                  LOAD acc, 80
                  OUTPUT acc, gcmd_xtrig
                  LOAD x, 00
                  CALL setReadAddr
                  LOAD color, 03
                  OUTPUT color, gcmd_color
                  LOAD mask, 01
                  LOAD y1base, 0C
y1logictraceloop: 
                  LOAD x, 00
                  LOAD y, y1base
                  INPUT y1, in_wave1data
                  AND y1, mask
                  JUMP NZ, y1logic0prep
                  ADD y, 08
    y1logic0prep: 
                  LOAD mode, gcmd_move        ; Startpunkt links
                  CALL plotxy
                  LOAD mode, gcmd_point
     y1logicloop: 
                  CALL setReadAddr
                  LOAD y, y1base
                  LOAD color, 03
                  OUTPUT color, gcmd_color
                  INPUT y1, in_wave1data
                  AND y1, mask
                  JUMP NZ, y1logic0
                  LOAD color, 01
                  OUTPUT color, gcmd_color
                  ADD y, 04
        y1logic0: 
                  CALL plotxy
                  ADD x, 01
                  COMPARE x, FF
                  JUMP NZ, y1logicloop
                  SL0 mask
                  ADD y1base, 10
                  COMPARE y1base, 8C
                  JUMP NZ, y1logictraceloop
                  RETURN
       y1display: 
                  INPUT y1base, in_y1base
                  INPUT acc, in_hystlevel
                  OUTPUT acc, out_hystlevel
                  INPUT acc, in_triglevel
                  OUTPUT acc, out_triglevel
                  CALL accOffset
                  ADD acc, y1base
                  OUTPUT acc, gcmd_ytrig
                  LOAD acc, 80
                  OUTPUT acc, gcmd_xtrig
                  LOAD x, 00
                  CALL setReadAddr
                  INPUT y1, in_wave1data
                  CALL y1offset
                  LOAD mode, gcmd_move        ; Startpunkt links
                  CALL plotxy
                  LOAD mode, gcmd_line
                  LOAD color, 02
                  OUTPUT color, gcmd_color
   y1refreshloop: 
                  ADD x, 01
                  CALL setReadAddr
                  INPUT y1, in_wave1data
                  CALL y1offset
                  CALL plotxy
                  COMPARE x, FF
                  JUMP NZ, y1refreshloop
                  RETURN
       y2display: 
                  INPUT y2base, in_y2base
                  LOAD x, 00
                  CALL setReadAddr
                  INPUT y2, in_wave2data
                  CALL y2offset
                  LOAD mode, gcmd_move        ; Startpunkt links
                  CALL plotxy
                  LOAD mode, gcmd_line
                  LOAD color, 01
                  OUTPUT color, gcmd_color
   y2refreshloop: 
                  ADD x, 01
                  CALL setReadAddr
                  INPUT y2, in_wave2data
                  CALL y2offset
                  CALL plotxy
                  COMPARE x, FF
                  JUMP NZ, y2refreshloop
                  RETURN
     setReadAddr: 
                  LOAD s0, 00
                  INPUT acc, in_offsetlow
                  ADD acc, x
                  OUTPUT acc, out_wavelow
                  INPUT acc, in_offsethi
                  ADDCY acc, s0
                  OUTPUT acc, out_wavehi
                  RETURN
        y1offset: ; Byte y1 skalieren (0,75), negieren und mit Offset versehen, Ergebnis in y
                  LOAD y, y1
                  SR0 y                       ; y1 div 2
                  ADD y1, y
                  SRA y1                      ; Zwischenergebnis jetzt in y1
                  LOAD y, BF                  ;  von 192 abziehen (Nullpunkt oben), y max=191=$BF
                  SUB y, y1                   ; Wert in y jetzt zwischen 0 (oben) und 191 (unten)
                  ADD y, y1base
                  RETURN
        y2offset: ; Byte y2 skalieren (0,75), negieren und mit Offset versehen, Ergebnis in y
                  LOAD y, y2
                  SR0 y                       ; y2 div 2
                  ADD y2, y
                  SRA y2
                  LOAD y, BF                  ;  von 192 abziehen (Nullpunkt oben), y max=191=$BF
                  SUB y, y2
                  ADD y, y2base
                  RETURN
       accOffset: ; Byte acc skalieren (0,75) und negieren, Ergebnis in acc
                  LOAD s0, acc
                  SR0 s0                      ; acc div 2
                  ADD acc, s0
                  SRA acc                     ; Zwischenergebnis jetzt in y1
                  LOAD s0, BF                 ;  von 192 abziehen (Nullpunkt oben), y max=191=$BF
                  SUB s0, acc
                  LOAD acc, s0
                  RETURN
                  ;=========================================================================
                  ;Grafik- und Text-Subroutinen
                  ;=========================================================================
          plotxy: 
                  ;plot at point x,y with mode (MOVE, POINT, LINE etc).
                  INPUT s0, in_status         ; letzter Befehl fertig?
                  TEST s0, 01
                  JUMP Z, plotxy
                  OUTPUT x, gcmd_xdata
                  OUTPUT y, gcmd_ydata
                  LOAD s0, 00
                  OUTPUT s0, (mode)           ; Befehl triggern
                  RETURN
          txt_wr: 
                  ; acc in Textbuffer schreiben an Position tptr_low, tptr_hi und ptr erhöhen
                  OUTPUT tptr_hi, out_adrhi
                  OUTPUT tptr_low, out_adrlow
                  OUTPUT acc, out_data
                  LOAD s0, 01
                  ADD tptr_low, s0
                  LOAD s0, 00
                  ADDCY tptr_hi, s0
                  RETURN
                  ;=========================================================================
                  ;Steuerungs-Subroutinen
                  ;=========================================================================
                  ; Ende der Frame-Anzeige abwarten (Flicker!)
  wait_framedone: 
                  INPUT s0, in_status         ; FRAMEDONE false abwarten
                  TEST s0, 02
                  JUMP NZ, wait_framedone
     frame_done2: 
                  INPUT s0, in_status         ; FRAMEDONE true abwarten
                  TEST s0, 02
                  JUMP Z, frame_done2
                  RETURN
          sdelay: 
                  LOAD s0, FF
     sdelay_loop: 
                  SUB s0, 01
                  JUMP NZ, sdelay_loop
                  RETURN
wait_key_release: 
                  INPUT s0, in_status         ; Key losgelassen abwarten
                  TEST s0, 08
                  JUMP NZ, wait_key_release
                  RETURN
   reset_trigger: 
                  LOAD s0, 01                 ; trig_reset
                  OUTPUT s0, out_control
                  LOAD s0, 02                 ; trig_ena
                  OUTPUT s0, out_control
                  RETURN
 disable_trigger: 
                  LOAD s0, 00                 ; trig_ena low
                  OUTPUT s0, out_control
                  RETURN
            init: CALL sdelay
                  LOAD s0, 00
                  OUTPUT s0, out_wavehi
                  LOAD s0, 80
                  OUTPUT s0, out_wavelow
                  LOAD acc, 10
                  OUTPUT acc, gcmd_xgrid
                  OUTPUT acc, gcmd_ygrid
                  CALL tclear
                  LOAD tptr_low, 00
                  LOAD tptr_hi, 00
          gclear: ; Grafikfenster löschen: Rechteck mit Farbe 0 zeichnen
                  LOAD x, 00
                  LOAD y, 00
                  LOAD mode, gcmd_move
                  CALL plotxy
                  LOAD s0, 00
                  OUTPUT s0, gcmd_color
                  LOAD x, FF
                  LOAD y, BF
                  LOAD mode, gcmd_fill
                  CALL plotxy
     gclear_wait: 
                  INPUT s0, in_status         ; letzter Befehl fertig?
                  TEST s0, 01
                  JUMP Z, gclear_wait
                  RETURN
          tclear: ; Text löschen
                  LOAD tptr_low, 00
                  LOAD tptr_hi, 00
                  LOAD acc, 20
      erase_loop: 
                  CALL txt_wr
                  COMPARE tptr_hi, 0F
                  JUMP NZ, erase_loop
      statusline: 
                  LOAD tptr_low, 46
                  LOAD tptr_hi, 00
                  LOAD acc, 63                ; "c"
                  CALL txt_wr
                  LOAD acc, 27                ; "'"
                  CALL txt_wr
                  LOAD acc, 74                ; "t"
                  CALL txt_wr
                  LOAD acc, 20                ; " "
                  CALL txt_wr
                  LOAD acc, 53                ; "S"
                  CALL txt_wr
                  LOAD acc, 43                ; "C"
                  CALL txt_wr
                  LOAD acc, 4F                ; "O"
                  CALL txt_wr
                  LOAD acc, 50                ; "P"
                  CALL txt_wr
                  LOAD acc, 45                ; "E"
                  CALL txt_wr
                  RETURN
