*
* This file is the interface between the software
* and the hardware of GALer. The routines of this file
* control the hardware.
*
* needed C-compiler optines: register parameter, 32 bit integer
*
* used assembler: asm of SAS/C 6.51
*
* assemble: asm Port.asm
*
* assumed scratch registers of the compiler: D0, D1, A0, A1



                INCLUDE "hardware/cia.i"


GAL16V8         EQU     1               ; type of GAL
GAL20V8         EQU     2
GAL22V10        EQU     3
GAL20RA10       EQU     4


IC1             EQU     3               ; number of IC
IC2             EQU    11               ; IC2 only for elektor
IC3             EQU     0               ; IC1-4       : write only
IC4             EQU     1
IC5             EQU     2
IC6a            EQU     0               ; IC6, IC7: read only
IC6c            EQU     4
IC7             EQU     1


HW_GALER_1_0    EQU     1               ; Hardware-Version
HW_GALER_1_2    EQU     2
HW_GALER_1_3    EQU     3
HW_ELEKTOR_II   EQU    10

ON              EQU     1               ; for control of the LED
OFF             EQU     0

PROG            EQU     1               ; Edit-Mode of GAL
VERIFY          EQU     0

LOW             EQU     0               ; level
HIGH            EQU     1


ciab            EQU     $BFD000

ciaaprb         EQU     $BFE101
ciaaddrb        EQU     $BFE301
ciabpra         EQU     $BFD000
ciabddra        EQU     $BFD200






        SECTION code,CODE


        XDEF    @InitParPort            ; initialize parallel port
        XDEF    @RestoreParPort         ; restore parallel-port
        XDEF    @InitHardware           ; initialize GAL programmer
        XDEF    @WriteByte              ; write byte in shift register
        XDEF    @ReadByte               ; read byte out of shift register
        XDEF    @SetGAL                 ; set type of GAL
        XDEF    @VeditOn                ; edit voltage on
        XDEF    @VeditOff               ; disable edit off
        XDEF    @LED                    ; control LED
        XDEF    @EnableVcc              ; switch +5V on
        XDEF    @DisableVcc             ; switch +5V off
        XDEF    @EnableVEdit            ; enable edit voltage
        XDEF    @DisableVEdit           ; disable edit voltage
        XDEF    @EnableOutput           ; Ausgangs-Treiber aktivieren
        XDEF    @DisableOutput          ; Ausgangs-Treiber deaktiviern
        XDEF    @SetRow                 ; set address at RAG0-RAG5
        XDEF    @SDIn                   ; set level of SDIn input
        XDEF    @SDOut                  ; get level at SDOut output
        XDEF    @Clock                  ; clock impuls at SCLK input
        XDEF    @STRImpuls              ; make STR impuls
        XDEF    @EditMode               ; set bits for edit mode
        XDEF    @ExitEditMode           ; exit edit mode and switch off +5V
        XDEF    @SetPV                  ; set PV (VERIFY or PROG)
        XDEF    @SetVolt                ; set voltage for edit mode
        XDEF    @SetPESSAVE             ; set level of PESSAVE pin
        XDEF    @SetERASE               ; set level of ERASE pin
        XDEF    @SetCLR                 ; set level of CLR pin
        XDEF    @SetARCH                ; set level of ARCH pin
        XDEF    @SetBE                  ; set level of BE pin
        XDEF    @SetANDBE               ; set level of ANDBE pin
        XDEF    @PollDelay              ; wait some micro seconds

        XDEF    _cia_timer_low
        XDEF    _cia_timer_high
        XDEF    _cia_timer_cr
        XDEF    _cia_timer_start
        XDEF    _cia_timer_stop
        XDEF    _hw_version


        XREF    _GALType
        XREF    _outIC1
        XREF    _outIC2
        XREF    _outIC3
        XREF    _outIC4
        XREF    _outIC5

        XREF    @WaitForTimer

        XREF    _LVOForbid
        XREF    _LVOPermit

        XREF    _prog_volt






* initialize parallel port
@InitParPort:
        move.b  ciaaddrb,cia_addrb      ; save direction of CIAs
        move.b  ciabddra,cia_bddra

        move.b  #%11111111,ciaaddrb     ; data as output
        and.b   #%11111010,ciabddra     ; use BUSY as input
                                        ; use SEL as input (for elektor`s
        rts                             ; hardware)





* restore state of parallel port
@RestoreParPort:
        move.b  cia_addrb,ciaaddrb      ; Restore data direction of CIAs
                                        ; but don't restore the state of
        move.b  cia_bddra,d0            ; the outputs. Otherwise GALer could
        and.b   #%11111010,ciabddra     ; get a command like Vcc or VEdit on.
        and.b   #%00000101,d0
        or.b    d0,ciabddra
        rts





* initialize hardware: switch all outputs low
* Parameter: none
@InitHardware:
        
        cmp.l   #HW_ELEKTOR_II,_hw_version  ; which hardware version?
        bne.s   ih_galer_hw
                                            ; elektor hardware
        moveq   #IC1,d1
        moveq   #0,d0
        bsr     @WriteByte

        moveq   #IC2,d1
        moveq   #0,d0
        bsr     @WriteByte

        moveq   #IC4,d1
        moveq   #0,d0
        bsr     @WriteByte
        bra.s   ih_end


                                            ; GALer hardware
ih_galer_hw:
        or.b    #%00001000,ciaaprb      ; PD3=H: Decoder deaktivieren!
        and.b   #%00001000,ciaaprb      ; alle anderen Datenleitungen auf LOW
                        ; ACHTUNG!!!: PD3 darf nur auf LOW-Pegel gehen
                        ; (Decoder aktiviert werden), wenn durch PD0 und
                        ; PD1 das IC, das angesprochen werden soll, bereits
                        ; selektiert ist. Ansonsten bekommt ein IC einen Takt-
                        ; impuls und beim nächsten Strobe liegen dann die
                        ; falschen Daten an.
        moveq   #IC1,d1
        moveq   #0,d0
        bsr     @WriteByte              ; Ausgänge von IC1 auf LOW      

        moveq   #IC3,d1
        moveq   #0,d0
        bsr     @WriteByte              ; Ausgänge von IC3 auf LOW      

        moveq   #IC4,d1
        moveq   #0,d0
        bsr     @WriteByte              ; Ausgänge von IC4 auf LOW      

        moveq   #IC5,d1
        moveq   #0,d0
        bsr     @WriteByte              ; Ausgänge von IC5 auf LOW      

ih_end: rts





* WriteByte:
* write a byte "byte" into the IC "IC"
* IC can be: GALer:   IC = IC1, IC3, IC4, IC5
*            Elektor: IC = IC1, IC2, IC4
* MSB is transfered first
* call: WriteByte(byte, IC)
@WriteByte:
        movem.l d2/d3,-(sp)             ; save register
                                        ; d0: data byte
                                        ; d1: IC

        cmp.l   #IC1,d1                 ; save values which are to
        bne.s   wb_1                    ; be written into the ICs
        move.l  d0,_outIC1
        bra.s   wb_c
wb_1    cmp.l   #IC2,d1
        bne.s   wb_2
        move.l  d0,_outIC2
        bra.s   wb_c
wb_2    cmp.l   #IC3,d1
        bne.s   wb_3
        move.l  d0,_outIC3
        bra.s   wb_c
wb_3    cmp.l   #IC4,d1
        bne.s   wb_4
        move.l  d0,_outIC4
        bra.s   wb_c
wb_4    move.l  d0,_outIC5
wb_c

        cmp.l   #HW_ELEKTOR_II,_hw_version  ; which hardware is connected?
        bne.s   wb_galer_hw

                                ;*** elektor hardware ***
        
                                ; loading a shift register runs like this:
                                ;  1. store all 24 bit in a CPU-register
                                ;  2. shift them into the shift registers
                                ;  3. set STR of the shift register low to
                                ;     load them

        and.b   #%11110111,ciaaprb      ; set STR of the shift registers low

        move.l  _outIC2,d2              ; store the data of all shift
        rol.l   #8,d2                   ; registers in d2
        move.l  _outIC1,d3
        move.b  d3,d2
        rol.l   #8,d2
        move.l  _outIC4,d3
        move.b  d3,d2
        rol.l   #8,d2

        moveq   #3*8-1,d3               ; loop counter: number of shift
                                        ; registers 3; size 8 bit

wb_l1:  rol.l   #1,d2                   ; get MSB to bit 0
        move.b  d2,d0
        and.b   #%00000001,d0           ; get this bit in d0
        and.b   #%11111110,ciaaprb      ; clear D0 of parallel port
        or.b    d0,ciaaprb              ; set D0 according to this bit
        or.b    #%00000010,ciaaprb      ; set CLK low
        nop                             ; wait a little
        nop
        nop
        and.b   #%11111101,ciaaprb      ; set CLK high
        dbf     d3,wb_l1                ; shift 24 bits

        or.b    #%00001000,ciaaprb      ; set STR of the shift registers high
        bra.s   wb_end



wb_galer_hw:                    ;*** GALer hardware ***


        and.b   #%11111100,ciaaprb      ; PD0 und PD1 setzen (IC aus-
        or.b    d1,ciaaprb              ; wählen)
        and.b   #%11110111,ciaaprb      ; Decoder aktivieren

        moveq   #7,d3                   ; Schleifenzähler
        ror.b   #3,d0                   ; MSB nach D4 (Datenleitung)

wb_l    move.b  d0,d2                   ; Datenbyte sichern
        and.b   #%00010000,d2           ; Datenbit ausmaskieren
        or.b    d2,ciaaprb              ; Datenbit (PD4) vom Par.-Port setzen

        or.b    #%00001000,ciaaprb      ; Clock-Impuls durch PD3 geben
        and.b   #%11110111,ciaaprb      ; LOW-HIGH Übergang

        and.b   #%11101111,ciaaprb      ; Datenbit (PD4) auf LOW

        rol.b   #1,d0                   ; nächstniedrigeres Bit senden
        dbf     d3,wb_l

        or.b    #%00001000,ciaaprb      ; Decoder wieder deaktivieren!!!
                                        ; (sehr WICHTIG, siehe InitHardware)
        or.b    #%00000100,ciaaprb      ; PD2 (Strobe) auf HIGH-> Daten werden
        and.b   #%11111011,ciaaprb      ; vom Schieberegister in das Datenreg.
                                        ; übernommen. Dann PD2 wieder auf LOW.
wb_end  movem.l (sp)+,d2/d3
        rts





* SetGAL:
* define type of GAL (GAL16V8, GAL20V8, GAL22V10, GAL20RA10)
* call: SetGAL(type);
*
@SetGAL:
        move.l  d0,_GALType
        rts





* VeditOn:
* switch GALer's voltage converter on (IC9)
* elektor's hardware does not support this, so just skip
* call: VeditOn();
@VeditOn:
        cmp.l   #HW_ELEKTOR_II,_hw_version
        beq.s   von_end

        move.l  #IC1,d1
        or.l    #%00001,_outIC1         ; Q1 von IC1 auf HIGH => VeditOn
        move.l  _outIC1,d0
        bsr     @WriteByte              ; IC1 setzen
von_end rts





* VeditOff:
* switch GALer's voltage converter off (IC9)
* elektor's hardware does not support his, so just skip
* call: VeditOff();
@VeditOff:
        cmp.l   #HW_ELEKTOR_II,_hw_version
        beq.s   voff_end

        move.l  #IC1,d1
        and.l   #%11111110,_outIC1      ; Q1 von IC1 auf LOW => VeditOff
        move.l  _outIC1,d0
        bsr     @WriteByte              ; IC1 setzen
voff_end
        rts





* EnableVEdit:
* switch edit voltage to pin 2 or pin 4 of the textool socket
* (pin depends on selected type of GAL)
* call: EnableVEdit();
@EnableVEdit:

        cmp.l   #HW_ELEKTOR_II,_hw_version  ; which hardware is connected?
        bne.s   ev_galer_hw
                                ;*** elektor hardware ***

        cmp.l   #GAL16V8,_GALType       ; 16V8 selected?
        bne.s   ev_c1

        move.l  _outIC4,d0
        and.l   #%11101111,d0
        moveq   #IC4,d1
        bsr     @WriteByte              ; set GAL16V8
        bra.s   ev_c2

ev_c1                                   ; 20V8, 22V10, 20RA10 selected
        move.l  _outIC4,d0
        or.l    #%00010000,d0
        moveq   #IC4,d1
        bsr     @WriteByte              ; set GAL20V8 etc.

ev_c2
        move.l  _outIC4,d0
        or.l    #%00100000,d0
        moveq   #IC4,d1
        bsr     @WriteByte              ; enable edit voltage (IC3a)
        bra.s   ev_end



ev_galer_hw                     ; *** GALer hardware ***

        moveq   #IC1,d1                 ; IC1 einstellen
        cmp.l   #GAL16V8,_GALType       ; 16V8 eingestellt?
        bne.s   eve_1                   ; nein, dann 20V8, 22V10, 20RA10

                                ;*** GAL16V8 ***
        moveq   #%00000100,d0           ; Q3 von IC1 auf HIGH
        bra.s   eve_2
                                ;*** 20V8, 22V10, 20RA10 ***
eve_1   moveq   #%00000010,d0           ; Q2 von IC1 auf HIGH

eve_2   or.l    d0,_outIC1
        move.l  _outIC1,d0
        bsr     @WriteByte
ev_end  rts





* DisableVEdit:
* remove edit voltage at pin 2 od pin 4
* (pin depends on selected type of GAL)
* call: DisableVEdit();
@DisableVEdit:

        cmp.l   #HW_ELEKTOR_II,_hw_version
        bne.s   dv_galer_hw
                                ;*** elektor hardware ***
        move.l  _outIC4,d0
        and.l   #%11011111,d0
        moveq   #IC4,d1
        bsr     @WriteByte              ; disable edit voltage (IC3a)
        bra.s   dv_end


dv_galer_hw:                    ;*** GALer hardware ***

        moveq   #IC1,d1                 ; IC1 einstellen
        cmp.l   #GAL16V8,_GALType       ; 16V8 eingestellt?
        bne.s   dve_1                   ; nein, dann wird 20V8 angenommen!
                                ;*** GAL16V8 ***
        move.l  #%11111011,d0           ; Q3 von IC1 auf LOW
        bra.s   dve_2
                                ;*** 20V8, 22V10, 20RA10 ***
dve_1   move.l  #%11111101,d0           ; Q2 von IC1 auf low

dve_2   and.l   d0,_outIC1
        move.l  _outIC1,d0
        bsr     @WriteByte
dv_end  rts





* LED:
* switch LED on/off
* ON:   LED on
* OFF:  LED off 
* call: LED(ON/OFF);
@LED:
        cmp.l   #HW_ELEKTOR_II,_hw_version
        bne.s   led_galer_hw
                                ;*** elektor hardware ***
        cmp.l   #ON,d0
        bne.s   led_4
        or.l    #%00000001,_outIC4
        bra.s   led_3
led_4   and.l   #%11111110,_outIC4
led_3   move.l  _outIC4,d0
        moveq   #IC4,d1
        bsr     @WriteByte
        bra.s   led_end

                                ;*** GALer hardware ***
led_galer_hw
        cmp.l   #ON,d0
        bne.s   led_2
        or.l    #%01000000,_outIC1
        bra.s   led_1
led_2   and.l   #%10111111,_outIC1
led_1   move.l  #IC1,d1
        move.l  _outIC1,d0
        bsr     @WriteByte              ; IC1 setzen
led_end rts





* EnableVcc:
* switch on voltage supply of GAL
* GAL16V8: pin 22 of the textool socket
* GAL20V8, 20RA10, 22V10: pin 24 of the textool socket
* call: EnableVcc();
@EnableVcc:

        movem.l d0-d7/a0-a6,-(sp)       ; Register retten
        move.l  #300000,d0              ; 300 ms warten
        jsr     @WaitForTimer
        movem.l (sp)+,d0-d7/a0-a6

        cmp.l   #HW_ELEKTOR_II,_hw_version
        bne.s   evc_galer_hw
                                ; *** elektor hardware ***
        move.l  _outIC4,d0
        cmp.l   #GAL16V8,_GALType       ; set voltage according to gal type
        bne.s   evc_3
        and.l   #%11101111,d0
        bra.s   evc_4
evc_3   or.l    #%00010000,d0
evc_4   moveq   #IC4,d1
        bsr     @WriteByte              ; seletct pin (22 or 24)

        move.l  _outIC4,d0
        or.l    #%00000001,d0
        moveq   #IC4,d1
        bsr     @WriteByte              ; switch on voltage supply (IC3b)
        bra.s   evc_end


evc_galer_hw:                   ; *** GALer hardware ***

        move.l  #IC1,d1                 ; IC1 selektieren
        cmp.l   #GAL16V8,_GALType       ; 16V8 eingestellt?
        bne.s   evc_1                   ; nein, dann wird 20V8 angenommen!!!
        moveq   #%00011000,d0           ; Q4,5 von IC1 auf HIGH=>+5V an Pin22
        bra.s   evc_2
evc_1   moveq   #%00010000,d0           ; Q5 auf HIGH => +5V an Pin 24  
evc_2   or.l    d0,_outIC1
        move.l  _outIC1,d0
        bsr     @WriteByte              ; IC1 setzen
evc_end rts





* DisableVcc:
* switch off voltage supply of GAL
* call: DisableVcc();
@DisableVcc:
        movem.l d0-d7/a0-a6,-(sp)       ; Register retten
        move.l  #50000,d0               ; sicherheitshalber 50mS warten, bis
        jsr     @WaitForTimer           ; das GAL die letzte Aktion richtig
        movem.l (sp)+,d0-d7/a0-a6

        cmp.l   #HW_ELEKTOR_II,_hw_version
        bne.s   dvc_galer_hw
                                ; *** elektor hardware ***
        move.l  _outIC4,d0
        and.l   #11111110,d0
        moveq   #IC4,d1
        bsr     @WriteByte
        bra.s   dvc_end


dvc_galer_hw                    ; *** GALer hardware ***

        move.l  #IC1,d1                 ; IC1 selektieren
        cmp.l   #GAL16V8,_GALType       ; 16V8 eingestellt?
        bne.s   dvc_1                   ; nein, dann wird 20V8 angenommen!!!
        move.l  #%11100111,d0           ; Q4,5 von IC1 auf LOW
        bra.s   dvc_2
dvc_1   move.l  #%11101111,d0           ; Q5 auf HIGH
dvc_2   and.l   d0,_outIC1
        move.l  _outIC1,d0
        bsr     @WriteByte              ; IC1 setzen
dvc_end rts





* EnableOutput:
* switch Output-Enable inputs (OE) of IC3, IC4, IC5 HIGH
* elektor hardware does not support this, so skip it
* call: EnableOutput();
@EnableOutput:
        cmp.l   #HW_ELEKTOR_II,_hw_version
        beq.s   eo_end

        move.l  #IC1,d1
        or.l    #%00100000,_outIC1
        move.l  _outIC1,d0
        bsr     @WriteByte
eo_end  rts





* DisableOutput:
* switch Output-Enable inputs (OE) of IC3, IC4, IC5 HIGH
* elektor hardware does not support this, so skip it
* call: EnableOutput();
@DisableOutput:
        cmp.l   #HW_ELEKTOR_II,_hw_version
        beq.s   do_end

        move.l  #IC1,d1
        and.l   #%11011111,_outIC1
        move.l  _outIC1,d0
        bsr     @WriteByte
do_end  rts





* ReadByte:
* read bit from IC6a, IC6c or byte from IC7
* call:   byte=ReadByte(source);
*         source: IC6a, IC6b, IC7
* PD3 is already HIGH, so reading is possible
* elektor's hardware does not support the testing of GALs, so skip it
@ReadByte:
        cmp.l   #HW_ELEKTOR_II,_hw_version
        beq     rb_end


        and.b   #%11111100,ciaaprb      ; set PD0 and PD1 LOW

        cmp.l   #HW_GALER_1_3,_hw_version
        beq     rb_version1_3           ; hardware version 1.3

; *** this is for the hardware versions 1.0, 1.1, 1.2 ***

        cmp.l   #IC6a,d0                ; read from IC6a?
        bne.s   rb_IC7                  ; no, then IC7
        or.b    #%00000001,ciaaprb      ; PD0 HIGH=>HIGH at Clk of IC7
                                        ; set PD0 HIGH =>IC6a is selected

        bsr     @PollDelay
 
        moveq   #0,d0
        move.b  ciabpra,d0
        not.b   d0                      ; invert
        and.b   #%00000001,d0           ; get BUSY bit
        bra     rb_end                  ; now we have the state of pin 22
rb_IC7
        moveq   #0,d0                   ; PD3 is HIGH=>reading is possible

        or.b    #%00000100,ciaaprb      ; set PD2 (Strobe) HIGH => put data
        and.b   #%11111011,ciaaprb      ; from input register into shift register
                                        ; then set PD2 LOW again
                                        ; PD3 is HIGH => reading is possible
        move.l  d2,-(sp)
        moveq   #7,d2                   ; loop counter
rb_l1   rol.b   #1,d0

        bsr     @PollDelay

        move.b  ciabpra,d1              ; get BUSY bit
        and.b   #%00000001,d1           ; AND BUSY bit
        or.b    d1,d0                   ; move BUSY bit in D0
        and.b   #%11111100,ciaaprb      ; set PD0 LOW => LOW at Clk of IC7
        or.b    #%00000001,ciaaprb      ; set PD0 HIGH => HIGH at Clk of IC7
                                        ; ==> next bit is available
        nop
        nop
        and.b   #%11111100,ciaaprb      ; set PD0 LOW=>IC6b is selected
        dbf     d2,rb_l1                ; read 8 bits
        not.b   d0                      ; invert them
        move.l  (sp)+,d2
        bra     rb_end


; *** this is for hardware version 1.3  ***

rb_version1_3:

        cmp.l   #IC6a,d0                ; read from IC6a?
        bne.s   rb_c1
                                        ; read IC6a
                                        ; PD0 and PD1 is LOW=>IC6a is selected
        bsr     @PollDelay
 
        moveq   #0,d0
        move.b  ciabpra,d0              ; read parallel port
        not.b   d0                      ; invert
        and.b   #%00000001,d0           ; get BUSY bit
        bra.s   rb_end                  ; now we have the state of pin 22


rb_c1   cmp.l   #IC6c,d0                ; read from IC6b?
        bne.s   rb_c2                   ; no, then IC7
                                        ; Read IC6c

        or.b    #%00000010,ciaaprb      ; PD0 LOW, PD1 HIGH => IC6c is selected
        moveq   #0,d0

        bsr     @PollDelay
 
        move.b  ciabpra,d0              ; read parallel port
        not.b   d0                      ; invert
        and.b   #%00000001,d0           ; get BUSY bit
        bra.s   rb_end                  ; now we have the state of pin 23


rb_c2                                   ; read IC7
        moveq   #0,d0                   ; PD3 is HIGH=>reading is possible

        or.b    #%00000101,ciaaprb      ; set PD2 (Strobe) HIGH => put data
        and.b   #%11111011,ciaaprb      ; from input register into shift register
                                        ; then set PD2 LOW again
                                        ; PD3 is HIGH => reading is possible

        move.l  d2,-(sp)
        moveq   #7,d2                   ; loop counter
rb_l2   rol.b   #1,d0

        bsr     @PollDelay

        move.b  ciabpra,d1              ; get BUSY bit
        and.b   #%00000001,d1           ; AND BUSY bit
        or.b    d1,d0                   ; move BUSY bit in D0
        and.b   #%11111100,ciaaprb      ; set PD0 LOW => LOW at Clk of IC7
        or.b    #%00000001,ciaaprb      ; set PD0 HIGH => HIGH at Clk of IC7
                                        ; ==> next bit is available
        dbf     d2,rb_l2                ; read 8 bits

        not.b   d0                      ; invert them
        move.l  (sp)+,d2

rb_end
        rts                             ; D0 is result





* SetRow:
* set address to RAG0-RAG5
* call: SetRow(row);
* row:    row which should be selected (0-63)
@SetRow:

        move.l  d0,-(sp)                ; Row (D0) auf Stack


        cmp.l   #GAL22V10,_GALType
        beq     setrow22V10
        cmp.l   #GAL20RA10,_GALType
        beq     setrow20RA10



        cmp.l   #HW_ELEKTOR_II,_hw_version
        bne     sr_galer_hw

                        ; *** elektor hardware ***
                                        ; RAG4 and RAG5 are equal for both,
                                        ; GAL16V8 and GAL20V8
        and.l   #%10111110,_outIC1      ; clear RAG4 and RAG5
        and.l   #%00100000,d0
        asl.b   #1,d0                   ; get RAG5
        or.l    d0,_outIC1              ; set RAG5
        move.l  (sp),d0
        and.l   #%00010000,d0
        asr.b   #4,d0                   ; get RAG4
        or.l    d0,_outIC1              ; set RAG4

        cmp.l   #GAL16V8,_GALType
        bne.s   sr_20V8

                        ; *** GAL16V8 ***
        move.l  (sp),d0
        and.l   #%00000001,d0           ; get RAG0
        asl.b   #2,d0
        and.l   #%11111011,_outIC1
        or.l    d0,_outIC1              ; set RAG0

        move.l  (sp),d0
        and.l   #%00000110,d0           ; get RAG1 and RAG2
        and.l   #%11111001,_outIC4
        or.l    d0,_outIC4              ; set RAG1 and RAG2

        move.l  (sp),d0
        and.l   #%00001000,d0           ; get RAG3
        asl.b   #2,d0
        and.l   #%11011111,_outIC1
        or.l    d0,_outIC1              ; set RAG3

        bra.s   sr_write

sr_20V8                 ; *** GAL20V8 ***
        move.l  (sp),d0
        and.l   #%00000001,d0           ; get RAG0
        asl.b   #4,d0
        and.l   #%11101111,_outIC1
        or.l    d0,_outIC1              ; set RAG0

        move.l  (sp),d0
        and.l   #%00000110,d0           ; get RAG1 and RAG2
        asl.b   #5,d0
        and.l   #%00111111,_outIC4
        or.l    d0,_outIC4              ; set RAG1 and RAG2

        move.l  (sp),d0
        and.l   #%00001000,d0           ; get RAG3
        asr.b   #2,d0
        and.l   #%11111101,_outIC4
        or.l    d0,_outIC4              ; set RAG3

sr_write                                ; write bytes to ICs
        move.l  #IC1,d1
        move.l  _outIC1,d0
        bsr     @WriteByte

        bra     setrowend



sr_galer_hw             ; *** GALer hardware ***

                        ; ***  GAL16V8 und GAL20V8  ***
                                    ; RAG5 setzen (bei 16 und 20V8 gleich)
        and.l   #$fe,_outIC5            ; Bit0(=RAG5) löschen
        asr.b   #5,d0                   ; Bit0 von D0=RAG5
        or.l    d0,_outIC5              ; RAG5=Bit von D0=> RAG5 gesetzt

        cmp.l   #GAL16V8,_GALType       ; GAL16V8?
        bne.s   setrow20V8              ; nein, dann GAL20V8 annehmen

                                ;*** GAL16V8 ***
                                    ; RAG0 setzen
        move.l  (sp),d0                 ; row holen
        and.l   #$ef,_outIC3            ; Bit4(=RAG0) löschen
        and.l   #1,d0                   ; Bit0 von "row" ausmaskieren
        asl.b   #4,d0
        or.l    d0,_outIC3              ; Bit4(=RAG0) setzen
                                    ; RAG1-RAG4 setzen
        move.l  (sp),d0                 ; row holen
        and.l   #$0f,_outIC4            ; Bit4-7(=RAG1-RAG4) löschen
        and.l   #%00011110,d0           ; Bit1-4 von "row" ausmaskieren
        asl.l   #3,d0                   ; an Bit4-7 schieben
        or.l    d0,_outIC4              ; RAG1-RAG4 setzen
        bra.s   write
                                ;*** GAL20V8 ***
setrow20V8                          ; RAG0 für GAL20V8 setzen
        move.l  (sp),d0                 ; row holen
        and.l   #%11011111,_outIC3      ; Bit5(=RAG0) löschen
        and.l   #1,d0                   ; Bit0 von "row" ausmaskieren
        asl.b   #5,d0
        or.l    d0,_outIC3              ; Bit5(=RAG0) setzen
                                    ; RAG4 setzen
        move.l  (sp),d0                 ; row holen
        and.l   #%01111111,_outIC4      ; Bit7(=RAG4) löschen
        and.l   #%00010000,d0           ; Bit4 von "row" ausmaskieren
        asl.l   #3,d0
        or.l    d0,_outIC4              ; Bit7(=RAG4) setzen
                                    ; RAG1-RAG3 setzen
        move.l  (sp),d0                 ; row holen
        and.l   #%11100011,_outIC4      ; Bit2-4(=RAG1-RAG3) löschen
        and.l   #%00001110,d0           ; Bit1-3 aus "row" ausmaskieren
        asl.l   #1,d0
        or.l    d0,_outIC4              ; RAG1-RAG3 setzen

write                               ; errechnete Werte in ICs schreiben
        move.l  #IC3,d1
        move.l  _outIC3,d0
        bsr     @WriteByte

        move.l  #IC4,d1
        move.l  _outIC4,d0
        bsr     @WriteByte

        move.l  #IC5,d1
        move.l  _outIC5,d0
        bsr     @WriteByte

        bra.s   setrowend

                        ; ***  GAL22V10 und GAL20RA10  ***
setrow22V10                     ; bei 22V10 und 20RA10 GALs wird RAG0-5 in
setrow20RA10                    ; das interne Schiebereg. des GALs getaktet,
                                ; da diese GALs keine RAG-Pins haben
        moveq   #5,d1                   ; D0 = Row
setrow1
        movem.l d0/d1,-(sp)
        and.l   #%0000001,d0            ; LSB ausmaskieren
        bsr.s   @SDIn                   ; RAGx ins Schieberegister des
        bsr     @Clock                  ; GALs takten
        movem.l (sp)+,d0/d1
        asr.b   #1,d0
        dbf     d1,setrow1

setrowend
        addq.l  #4,sp                   ; Stack korrigieren
        rts





* SDIn:
* set bit at SDIn input of the GAL (pin 11 of the textool socket)
* call: SDIn(bit);    bit: 0=LOW; 1=HIGH
@SDIn:

        cmp.l   #HW_ELEKTOR_II,_hw_version
        bne.s   sd_galer_hw
                                ; *** elektor hardware ***
        asl.b   #7,d0                   ; shift bit #0 to bit #7
        and.l   #%01111111,_outIC1      ; clear bit #7 of IC1
        or.l    d0,_outIC1
        move.l  _outIC1,d0
        move.l  #IC1,d1
        bsr     @WriteByte              ; set SDIn
        bra.s   sd_end

sd_galer_hw                     ; *** GALer hardware ***
                                        ; Bit steht in d0
        asl.b   #2,d0                   ; an die richtige Stelle schieben
        and.l   #%11111011,_outIC5      ; SDIn-Bit löschen
        or.l    d0,_outIC5              ; Bit auf LOW oder HIGH setzen
        move.l  #IC5,d1
        move.l  _outIC5,d0
        bsr     @WriteByte
sd_end  rts





* SDOut:
* read bit from SDOut (SDOut is an open drain output!) 
* pin 14 (GAL16V8, 22V10, 20RA10), pin 15 (GAL20V8) of the textool socket
* call: bit=SDOut();
* bit: 0: SDOut=LOW; 1: SDOut=HIGH
@SDOut:
        cmp.l   #HW_ELEKTOR_II,_hw_version
        bne.s   sdo_galer_hw
                                ; *** elektor hardware  ***
        cmp.l   #GAL20V8,_GALType
        beq.s   sdo_c1
        move.l  _outIC2,d0
        and.b   #%11101111,d0           ; select IC2a
        move.l  #IC2,d1
        bsr     @WriteByte
        nop                             ; nops are not really necessary
        nop
        nop
        move.b  ciabpra,d0              ; get BUSY bit
        and.l   #%00000001,d0
        bra.s   sdo_end
sdo_c1                              ; GAL20V8
        move.l  _outIC2,d0
        or.b    #%00010000,d0           ; select IC2b
        move.l  #IC2,d1
        bsr     @WriteByte
        nop                             ; nops are not really necessary
        nop
        nop
        move.b  ciabpra,d0              ; get BUSY bit
        and.l   #%00000001,d0
        bra.s   sdo_end


sdo_galer_hw                    ; *** GALer hardware ***
        move.l  #IC7,d0                 ; ein Byte aus IC7 holen
        bsr     @ReadByte               ; Bit0=Pin14, Bit1=Pin15

        cmp.l   #GAL20V8,_GALType       ; GAL20V8 eingestellt?
        beq.s   sdo_c2                  ; nein, dann 16V8, 22V10, 20RA10
        and.l   #1,d0                   ; Bit0 ausmaskieren
        bra.s   sdo_end                 ; D0=Bit
                                    ; GAL20V8
sdo_c2  asr.l   #1,d0                   ; SDOut-Bit an Bit-Pos. 0
        and.l   #1,d0
sdo_end                                 ; 32-Bit-Ergebnis in D0
        rts





* PollDelay
* wait about 10us
* This function does polling. I know that this is not a very good methode in
* a multitasking system. But we have to wait just some micro seconds.
* This is not possible when using the timer device or CIA timer interrupts.
* Using this things lasts at least 400us (timer device) or 180us (CIA timer
* interrupts). This is too long. So we have to poll, sorry.
*
* A0 will be changed!
@PollDelay:

        move.l  _cia_timer_low,a0       ; load timer
        move.b  #255,(a0)
        move.l  _cia_timer_high,a0
        clr.b  (a0)
                                        ; start timer
        move.l  _cia_timer_cr,a0
        move.b  _cia_timer_start,(a0)
 
        move.l  _cia_timer_low,a0
PD_loop:
        cmp.b   #250,(a0)               ; poll timer's low byte
        bhi.s   PD_loop

                                        ; stop timer
        move.l  _cia_timer_cr,a0
        move.b  _cia_timer_stop,(a0)

        rts

 





* Clock:
* generate Low-High-Low transition at GAL's clock input (pin 10 of the
* textool socket) - when calling this function SCLK must be Low already
*
* call: Clock();
@Clock:
        cmp.l   #HW_ELEKTOR_II,_hw_version
        bne.s   cl_galer_hw
                                ; *** elektor hardwar ***
        or.l    #%00000010,_outIC1      ; SCLK HIGH
        move.l  #IC1,d1
        move.l  _outIC1,d0
        bsr     @WriteByte

        and.l   #%111111101,_outIC1     ; SCLK LOW
        move.l  #IC1,d1
        move.l  _outIC1,d0
        bsr     @WriteByte
        bra.s   cl_end
        
cl_galer_hw                     ; *** GALer hardware ***
        or.l    #%00000010,_outIC5      ; SCLK-Bit auf HIGH
        move.l  #IC5,d1
        move.l  _outIC5,d0
        bsr     @WriteByte

        and.l   #%11111101,_outIC5      ; SCLK-Bit auf LOW
        move.l  #IC5,d1
        move.l  _outIC5,d0
        bsr     @WriteByte

cl_end  rts





* STRImpuls:
* set /STR low (pin 13 of the textool socket) for a duration of "STRLength"
* call: STRImpuls(long STRLength);
* STRLength: duration of the low impulse in microsecondes (32 bit!)
@STRImpuls:
        movem.l d0-d7/a0-a6,-(sp)       ; Register retten

        move.l  4,a6
        jsr     _LVOForbid(a6)          ; forbid task switching

        cmp.l   #HW_ELEKTOR_II,_hw_version
        bne.s   sim_galer_hw
                                ; *** elektor hardware **
        and.l   #%11110111,_outIC1      ; set STR LOW
        move.l  #IC1,d1
        move.l  _outIC1,d0
        bsr     @WriteByte

        cmp.l   #300,(sp)               ; writing a value into the IC needs
        bls.s   sim_c1                  ; about 300us, so it makes no sense
        move.l  (sp),d0                 ; to use the timer if the time to
        sub.l   #300,d0                 ; wait is less than 300us
        jsr     @WaitForTimer
sim_c1
        or.l    #%00001000,_outIC1      ; set STR HIGH
        move.l  #IC1,d1
        move.l  _outIC1,d0
        bsr     @WriteByte
        bra.s   sim_end


sim_galer_hw                    ; *** GALer hardware ***
        and.l   #%11110111,_outIC5      ; STR-Pin auf LOW
        move.l  #IC5,d1
        move.l  _outIC5,d0
        bsr     @WriteByte

        cmp.l   #100,(sp)               ; bis ein Wert in ein IC getaktet wird
        bls.s   sim_c2                  ; vergehen ca. 100us => keinen Timer
        move.l  (sp),d0                 ; Dauer des Impulses in Mikrosekunden
        jsr     @WaitForTimer           ; Low-Impuls
sim_c2
        or.l    #%00001000,_outIC5      ; STR-Pin wieder auf HIGH
        move.l  #IC5,d1
        move.l  _outIC5,d0
        bsr     @WriteByte

sim_end jsr     _LVOPermit(a6)          ; permit task switching

        movem.l (sp)+,d0-d7/a0-a6       ; Registerinhalte zurückholen
        rts





* SetPV:
* set P/V pin 
* call:  SetPV(mode);
* mode :   VERIFY (read, P/V low), PROG (write, P/V high)
@SetPV:
                                        ; mode = D0

        cmp.l   #HW_ELEKTOR_II,_hw_version
        bne.s   spv_galer_hw
                                ; *** elektor hardware ***

        cmp.l   #GAL16V8,_GALType
        bne.s   spv_c1
                                    ; *** GAL16V8 ***
        move.l  _outIC1,d1
        and.l   #%11101111,d1           ; clear P/V
        asl.b   #4,d0
        or.l    d0,d1                   ; set P/V according to mode
        move.l  d1,d0
        move.l  #IC1,d1
        bsr     @WriteByte
        bra     spv_end

spv_c1
        cmp.l   #GAL20V8,_GALType
        bne.s   spv_c2              ; *** GAL20V8 ***

        move.l  _outIC4,d1
        and.l   #%11110111,d1           ; clear P/V
        asl.b   #3,d0
        or.l    d0,d1                   ; set P/V according to mode
        move.l  d1,d0
        move.l  #IC4,d1
        bsr     @WriteByte
        bra.s   spv_end

spv_c2                              ;*** 22V10, 20RA10 ***
        move.l  _outIC4,d1
        and.l   #%10111111,d1           ; clear P/V
        asl.b   #6,d0
        or.l    d0,d1                   ; set P/V according to mode
        move.l  d1,d0
        move.l  #IC4,d1
        bsr     @WriteByte
        bra.s   spv_end



spv_galer_hw                    ; *** GALer hardware ***

        cmp.l   #GAL16V8,_GALType       ; GAL16V8?
        bne.s   spv_c3                  ; nein, dann 1

                                ;***  GAL16V8  ***
        move.l  _outIC3,d1
        and.l   #%11011111,d1
        asl.b   #5,d0                   ; Mode-Bit zu Bit 5 schieben
        or.l    d0,d1
        move.l  d1,d0                   ; P/V setzen
        move.l  #IC3,d1                 ; IC3 setzen
        bsr     @WriteByte
        bra.s   spv_end

spv_c3
        cmp.l   #GAL20V8,_GALType
        bne.s   spv_c4
                                ;***  GAL20V8  ***

        move.l  _outIC3,d1
        and.l   #%10111111,d1
        asl.b   #6,d0                   ; Mode-Bit zu Bit 6 schieben
        or.l    d0,d1
        move.l  d1,d0                   ; P,/V-Bit setzen
        move.l  #IC3,d1                 ; IC3 setzen
        bsr     @WriteByte
        bra.s   spv_end

spv_c4
                                ;***  22V10, 20RA10  ***

        move.l  _outIC4,d1
        and.l   #%11111011,d1
        asl.b   #2,d0
        or.l    d0,d1
        move.l  d1,d0                   ; P,/V-Bit setzen
        move.l  #IC4,d1                 ; IC4 setzen
        bsr     @WriteByte

spv_end
        rts






* Edit-Mode:
* switch GAL into edit mode: /STR = HIGH, P/V = LOW,
* SDOUT(open drain output!) = VIH, all VIL-pins = VIL
* call: EditMode(mode);
* mode: PROG or VERIFY (needed to select voltage)
@EditMode:
        movem.l d0-d7/a0-a6,-(sp)       ; Register sichern


        cmp.l   #HW_ELEKTOR_II,_hw_version
        bne.s   em_galer_hw
                                ; *** elektor hardware ***
        cmp.l   #GAL16V8,_GALType       ; GAL16V8
        bne.s   em_c7                   ; no, then goto em_c7
                                    ;*** GAL16V8 ***
        moveq   #IC4,d1
        moveq   #%00001000,d0
        bsr     @WriteByte

        moveq   #IC1,d1
        moveq   #%00001000,d0           ; set /STR high
        bsr     @WriteByte

        moveq   #IC2,d1
        moveq   #%00000000,d0           ; set SDOut high and
        bsr     @WriteByte
        bra     em_c2                   ; select voltage

em_c7   cmp.l   #GAL20V8,_GALType
        bne.s   em_c8               ;*** GAL20V8 ***

        moveq   #IC4,d1
        moveq   #%00000000,d0
        bsr     @WriteByte

        moveq   #IC1,d1
        moveq   #%00001000,d0           ; set /STR high
        bsr     @WriteByte

        moveq   #IC2,d1
        moveq   #%00010000,d0           ; set SDOut high and
        bsr     @WriteByte
        bra.s   em_c2                   ; select voltage

em_c8                           ;*** GAL20RA10 ***
                                ;*** GAL22V10  ***
        moveq   #IC4,d1
        moveq   #%00000000,d0
        bsr     @WriteByte

        moveq   #IC1,d1
        moveq   #%00001000,d0           ; set /STR high
        bsr     @WriteByte

        moveq   #IC2,d1
        moveq   #%00000000,d0           ; set SDOut high and
        bsr     @WriteByte
        bra.s   em_c2                   ; select voltage



em_galer_hw                     ; *** GALer hardware ***
        cmp.l   #GAL16V8,_GALType       ; GAL16V8?
        bne.s   em_c1                   ; nein, dann em_c1

                                ;*** GAL16V8 ***
        moveq   #IC3,d1                 ; IC3, P/V auf LOW
        moveq   #%00000000,d0
        bsr     @WriteByte

        moveq   #IC4,d1
        moveq   #%00000000,d0           ; IC4 initialisieren
        bsr     @WriteByte

        moveq   #IC5,d1                 ; /STR auf HIGH
        moveq   #%00011000,d0           ; IC5 initialisieren
        bsr     @WriteByte
        bra.s   em_c2


em_c1   cmp.l   #GAL20V8,_GALType
        bne.s   em_c5

                                ;*** GAL20V8 ***
        moveq   #IC3,d1                 ; IC3, P/V auf LOW
        moveq   #%00000000,d0
        bsr     @WriteByte

        moveq   #IC4,d1
        moveq   #%00000000,d0           ; IC4 initialisieren
        bsr     @WriteByte

        moveq   #IC5,d1                 ; /STR auf HIGH
        moveq   #%00101000,d0           ; IC5 initialisieren
        bsr     @WriteByte
        bra.s   em_c2


em_c5
                                ;*** GAL20RA10 ***
                                ;*** GAL22V10  ***

        moveq   #IC3,d1                 ; IC3, OPs auf VIL
        moveq   #%00000000,d0
        bsr     @WriteByte

        moveq   #IC4,d1
        moveq   #%00000000,d0           ; IC4, P/V auf LOW
        bsr     @WriteByte

        moveq   #IC5,d1                 ; /STR, SDOUT auf HIGH
        moveq   #%00011000,d0           ; IC5 initialisieren
        bsr     @WriteByte


em_c2
                                    ; richtige Spannung auswählen
        cmp.l   #VERIFY,(sp)            ; Lesen?
        bne.s   em_c3                   ; nein, dann Programmieren!

        moveq   #4,d0                   ; 12 Volt einstellen
        cmp.l   #GAL22V10,_GALType      ; wenn 22V10, dann 16.5 Volt
        bne.s   em_c6
        moveq   #0,d0
em_c6   bsr     @SetVolt
        bra.s   em_c4

em_c3   move.l  _prog_volt,d0           ; Programmierspannung einstellen
        bsr     @SetVolt

em_c4   bsr     @VeditOn                ; Edit-Spannung aufbauen

        move.l  #50000,d0               ; 50 ms warten, bis sich die
        jsr     @WaitForTimer           ; Edit-Spannung aufgebaut hat

        bsr     @EnableOutput           ; Bits anlegen
        bsr     @EnableVcc              ; Vcc anlegen

        move.l  #100000,d0              ; Prellzeit der Relais überbrücken
        jsr     @WaitForTimer

        bsr     @EnableVEdit            ; Edit-Spannung anlegen
                                    ; GAL befindet sich jetzt im Edit-Mode
        moveq   #5,d0                   ; 5 us warten bevor nächste Aktion
        jsr     @WaitForTimer           ; erlaubt ist

        movem.l (sp)+,d0-d7/a0-a6       ; Registerinhalte zurückholen
        rts





* ExitEditMode:
* Schaltet zuerst VEdit und VCC ab, dann wird der Inhalt der ICs
* zurückgesetzt.
* Aufruf: ExitEditMode();
@ExitEditMode:
        movem.l d0-d7/a0-a6,-(sp)       ; Register sichern

        bsr     @DisableVEdit

        bsr     @DisableVcc

        bsr     @InitHardware

        bsr     @EnableOutput

        movem.l (sp)+,d0-d7/a0-a6
        rts





* SetVolt:
* set voltage
* GALer:   select voltage by use of IC 10 and IC 11
* elektor: set bits of AD converter
* call:   SetVolt(value);
* value:  0=16.50 Volt; 1=15.75 Volt; 2=14.5 Volt; 3=14.00 Volt; 4=12.00 Volt
*
@SetVolt:
                                        ; Parameter in D0
        move.l  d0,-(sp)                ; Wert sichern

        cmp.l   #HW_ELEKTOR_II,_hw_version
        bne.s   sv_galer_hw
                                ; *** elektor hardware ***

        move.l  _outIC2,d1              ; clear all bits of IC 2 which
        and.l   #%00110000,d1           ; belongs to the DA converter

        tst     d0                      ; 16.5 V
        bne.s   sv_c1 
        or.l    #%01000100,d1
        bra.s   sv_c5

sv_c1   cmp     #1,d0                   ; 15.75 V
        bne.s   sv_c2
        or.l    #%10001111,d1
        bra.s   sv_c5

sv_c2   cmp     #2,d0                   ; 14.5 V
        bne.s   sv_c3
        or.l    #%10000101,d1
        bra.s   sv_c5

sv_c3   cmp     #3,d0                   ; 14.0 V
        bne.s   sv_c4
        or.l    #%10000001,d1
        bra.s   sv_c5

sv_c4                                   ; 12.0 V
        or.l    #%10000000,d1


sv_c5   move.l  d1,d0                   ; write value into d0
        moveq   #IC2,d1                 ; write IC number into d1
        bsr     @WriteByte              ; set voltage
        bra.s   sv_end



sv_galer_hw                     ; *** GALer hardware ***

        and.l   #%00000001,d0
        rol.l   #7,d0
        and.l   #%01111111,_outIC1
        or.l    d0,_outIC1              ; Q8 (Pin 11) von IC1 setzen
        move.l  _outIC1,d0
        move.l  #IC1,d1
        bsr     @WriteByte

        move.l  (sp),d0
        and.l   #%00000110,d0
        rol.l   #5,d0
        and.l   #%00111111,_outIC5
        or.l    d0,_outIC5              ; Q7 und Q8 von IC5 setzen
        move.l  _outIC5,d0
        move.l  #IC5,d1
        bsr     @WriteByte

sv_end  addq.l  #4,sp
        rts





*** The following routines are only for the 22V10 and/or 20RA10 GALs. ***



* SetPESSAVE:
* set PESSAVE pin (pin 4) of the GAL20RA10
* remark: this is routine is used for GAL22V10 only
* call: SetPESSAVE(pegel)
* parameter: pegel = HIGH or LOW

* SetERASE:
* set ERASE pin (pin 4) of the GAL22V10
* remark: this is routine is used for GAL22V10 only
* call: SetERASE(pegel)
* parameter: pegel = HIGH or LOW

@SetPESSAVE:
@SetERASE:

        cmp.l   #HW_ELEKTOR_II,_hw_version
        bne.s   ser_galer_hw
                                ; *** elektor hardware ***
        and.l   #%01111111,_outIC4
        cmp.l   #LOW,d0
        beq.s   ser_c1

        or.l    #%10000000,_outIC4
        bra.s   ser_c1


ser_galer_hw                    ; *** GALer hardware ***
        and.l   #%11110111,_outIC4
        cmp.l   #LOW,d0
        beq.s   ser_c1

        or.l    #%00001000,_outIC4

ser_c1  move.l  #IC4,d1
        move.l  _outIC4,d0
        bsr     @WriteByte

        rts





* SetCLR:
* set CLR pin (pin 6) of GAL22V10 and GAL20RA10
* call: SetCLR(pegel)
* parameter: pegel = HIGH or LOW

@SetCLR:

        cmp.l   #HW_ELEKTOR_II,_hw_version
        bne.s   sclr_galer_hw
                                        ; *** elektor hardware ***
        and.l   #%11111011,_outIC4
        cmp.l   #LOW,d0
        beq.s   sclr_c1
        or.l    #%00000100,_outIC4
        bra.s   sclr_c1


sclr_galer_hw                           ; *** GALer hardware ***
        and.l   #%11011111,_outIC4
        cmp.l   #LOW,d0
        beq.s   sclr_c1

        or.l    #%00100000,_outIC4

sclr_c1 move.l  #IC4,d1
        move.l  _outIC4,d0
        bsr     @WriteByte

        rts





* SetBE:
* set BE pin (pin 7) of GAL22V10 and GAL20RA10
* call: SetBE(pegel)
* parameter: pegel = HIGH or LOW

@SetBE:
        cmp.l   #HW_ELEKTOR_II,_hw_version
        bne.s   sbe_galer_hw
                                        ; *** elektor hardware ***
        and.l   #%11011111,_outIC1
        cmp.l   #LOW,d0
        beq.s   sbe_c1

        or.l    #%00100000,_outIC1

sbe_c1  move.l  #IC1,d1
        move.l  _outIC1,d0
        bsr     @WriteByte
        bra.s   sbe_end


sbe_galer_hw                            ; *** GALer hardware ***
        and.l   #%10111111,_outIC4
        cmp.l   #LOW,d0
        beq.s   sbe_c2

        or.l    #%01000000,_outIC4

sbe_c2  move.l  #IC4,d1
        move.l  _outIC4,d0
        bsr     @WriteByte

sbe_end rts





* SetARCH:
* set ARCH pin (pin 8) of GAL22V10 and GAL20RA10
* call: SetARCH(pegel)
* parameter: pegel = HIGH or LOW

@SetARCH:

        cmp.l   #HW_ELEKTOR_II,_hw_version
        bne.s   sar_galer_hw
                                        ; *** elektor hardware ***
        and.l   #%11111110,_outIC1
        cmp.l   #LOW,d0
        beq.s   sar_c1

        or.l    #%00000001,_outIC1

sar_c1  move.l  #IC1,d1
        move.l  _outIC1,d0
        bsr     @WriteByte
        bra.s   sar_end

sar_galer_hw                            ; *** GALer hardware ***
        and.l   #%01111111,_outIC4
        cmp.l   #LOW,d0
        beq.s   sar_c2

        or.l    #%10000000,_outIC4

sar_c2  move.l  #IC4,d1
        move.l  _outIC4,d0
        bsr     @WriteByte

sar_end rts





* SetANDBE:
* set ANDBE pin (pin 9) of GAL20RA10
* remark: this routine is for the 22V10 GAL only
* call: SetCLR(pegel)
* parameter: pegel = HIGH or LOW

@SetANDBE:

        cmp.l   #HW_ELEKTOR_II,_hw_version
        bne.s   sand_galer_hw
                                        ; *** elektor hardware ***
        and.l   #%10111111,_outIC1
        cmp.l   #LOW,d0
        beq.s   sand_c1

        or.l    #%01000000,_outIC1

sand_c1 move.l  #IC1,d1
        move.l  _outIC1,d0
        bsr     @WriteByte
        bra.s   sand_end


sand_galer_hw                           ; *** GALer hardware ***
        and.l   #%11111110,_outIC5
        cmp.l   #LOW,d0
        beq.s   sand_c2

        or.l    #%00000001,_outIC5

sand_c2 move.l  #IC5,d1
        move.l  _outIC5,d0
        bsr     @WriteByte

sand_end
        rts







        SECTION data,DATA


_cia_timer_low:     dc.l    0       ; address of TxLO
_cia_timer_high:    dc.l    0       ; address of TxHI
_cia_timer_cr:      dc.l    0       ; address of CRx
_cia_timer_start:   dc.b    0       ; value to start cia timer
_cia_timer_stop:    dc.b    0       ; value to stop cia timer


_hw_version:        dc.l    0


cia_addrb:          dc.b    0
cia_bddra:          dc.b    0


        END
