;
; Nunchuck Driver para porta Joystick MSX
;
; danjovic@hotmail.com
; http://hotbit.blogspot.com
;
; Licenca de uso: GNU GPL
;
; Versao 0.1 24/12/2011
;
; #########################
;
; PSG Reg 15 Bits
;

CPU MSX 

ASDA: EQU 0
ASCL: EQU 1
BSDA: EQU 2
BSCL: EQU 3
APWR: EQU 4
BPWR: EQU 5
ABSEL: EQU 6
;
MSDA: EQU 10H ; (SDA In = TRGA)
;
; PSG Regs
;
PSGAD:    EQU 0A0H
PSGWR:    EQU 0A1H
PSGRD:    EQU 0A2H
;
TIMEOUT:  EQU 2000
T1MS3MHZ: EQU 109
T1MS7MHZ: EQU 220
NC_ADR:   EQU 10100100B
ENOCHIP:  EQU 01
EOK:      EQU 0
CHPUT:    EQU 0A2H
;
;
; #############################
;
ORG 0A000H
;
;AND A  ; Seleciona porta JOY 1
SCF    ; Seleciona porta JOY 2
CALL J2CINIT

; Initialize Nunchuck
LD A,NC_ADR
AND 0FEH ; Bit R/!W=0
LD C,A
LD HL,0400H
CALL J2CP16ADR
JR C,ERRO
;
CALL WAIT1MS
CALL WAIT1MS
RET

REQUEST:
; Request Data
LD A,NC_ADR
AND 0FEH ; Bit R/!W=0
LD C,A
LD L,00H
CALL J2CP8ADR
JR C,ERRO
;
; Send Request
;LD A,NC_ADR
;AND 0FEH ; Bit R/!W=0
;LD C,A
;CALL J2CLOGON
;JR C,ERRO
;LD C,0
;CALL J2CPB
;JR C,ERRO
;
CALL WAIT1MS
CALL WAIT1MS

; Get Nunchuck Data
LD A,NC_ADR
OR 01    ; Bit R/!W=1
LD C,A
CALL J2CLOGON
JR C,ERRO
;
LD IY,0B100H
LD HL,6 
;
LOOP:
CALL J2CGBYTE
LD (IY),C
INC IY
AND A ;CY=0 Gera ACK
CALL J2CPAK
DEC HL
LD A,H
OR L
JR NZ,LOOP
;
CALL J2CGBYTE ; Ultimo byte
LD (IY),C     ; nao gera ACK
SCF
CALL J2CPAK
CALL J2CSTOP

; Decodifica dados
LD L,6
DECOD1:
LD A,(IY)
XOR 017H
ADD A,017H
LD (IY),A
DEC IY
DEC L
JR NZ, DECOD1

;
AND A ; clear carry
LD A,'+'
JR ERR1
;
ERRO: LD A,'-'
ERR1:
CALL CHPUT
RET

; #############################
; ##        Driver J2C       ##
; #############################
;
J2CINIT:
DI
LD A,15
OUT (PSGAD),A
IN A,(PSGRD)
LD (PSGSAV),A
JR C,BINIT
;
AINIT:
RES ABSEL,A ; JOY A
SET APWR,A  ; Energiza HUB
OUT (PSGWR),A
CALL WAIT1MS ; Aguarda 1ms
SET ASDA,A ; SDA=1
OUT (PSGWR),A
RES ASCL,A  ; SCL=0
OUT (PSGWR),A
LD B,A
;
CALL J2CSTOP
CALL J2CSTOP
CALL J2CSTOP
RET
;
BINIT:
SET ABSEL,A ; JOY B
SET BPWR,A  ; Energiza HUB
OUT (PSGWR),A
CALL WAIT1MS ; Aguarda 1ms
SET BSDA,A ; SDA=1
OUT (PSGWR),A
RES BSCL,A  ; SCL=0
OUT (PSGWR),A
LD B,A
;
CALL J2CSTOP
CALL J2CSTOP
CALL J2CSTOP
RET
;
J2CSTOP:
LD A,B
BIT ABSEL,A ; Qual porta?
JR NZ,BSTOP
;
ASTOP:
RES ASDA,A ; SDA=0
OUT (PSGWR),A
SET ASCL,A ; SCL=1
OUT (PSGWR),A
SET ASDA,A ; SDA=1
OUT (PSGWR),A
LD B,A ; Atualiza B
RET
;
BSTOP:
RES BSDA,A ; SDA=0
OUT (PSGWR),A
SET BSCL,A ; SCL=1
OUT (PSGWR),A
SET BSDA,A ; SDA=1
OUT (PSGWR),A
LD B,A ; Atualiza B
RET
;
J2CSTART:  ; START
LD A,B
BIT ABSEL,A
JR NZ,BSTART
;
ASTART:
SET ASCL,A ; SCL=1
OUT (PSGWR),A
SET ASDA,A ; SDA=1
OUT (PSGWR),A
RES ASDA,A ; SDA=0
OUT (PSGWR),A
RES ASCL,A ; SCL=0
OUT (PSGWR),A
SET ASDA,A ; SDA=1
OUT (PSGWR),A
LD B,A
RET
;
BSTART:
SET BSCL,A ; SCL=1
OUT (PSGWR),A
SET BSDA,A ; SDA=1
OUT (PSGWR),A
RES BSDA,A ; SDA=0
OUT (PSGWR),A
RES BSCL,A ; SCL=0
OUT (PSGWR),A
SET BSDA,A ; SDA=1
OUT (PSGWR),A
LD B,A
RET
;
J2CPB:  ; PUT BYTE
LD A,B
BIT ABSEL,A
JR NZ,BPBYTE
;
APBYTE:
LD B,8
;
APBY1:
SLA C
RES ASDA,A
JR NC,APBY2 ; SDA=CY
SET ASDA,A
APBY2:
OUT (PSGWR),A
SET ASCL,A ; SCL=1
OUT (PSGWR),A
RES ASCL,A ; SCL=0
OUT (PSGWR),A
DJNZ APBY1
;
SET ASDA,A ; SDA=1
OUT (PSGWR),A
LD B,A
RET
;
BPBYTE:
LD B,8
;
BPBY1:
SLA C
RES BSDA,A
JR NC,BPBY2 ; SDA=CY
SET BSDA,A
BPBY2:
OUT (PSGWR),A
SET BSCL,A ; SCL=1
OUT (PSGWR),A
RES BSCL,A ; SCL=0
OUT (PSGWR),A
DJNZ BPBY1
;
SET BSDA,A ; SDA=1
OUT (PSGWR),A
LD B,A
RET
;
J2CGBYTE:
LD A,B
BIT ABSEL,A
JR NZ,BGBYTE
;
AGBYTE:
SET ASDA,A ; SDA=1
OUT (PSGWR),A
LD BC,0800H ; B=8, C=0
;
AGBY1:
SET ASCL,A ; SCL=1
OUT (PSGWR),A
LD E,A     ; Salva A
LD A,14
OUT (PSGAD),A ; Selec REG 14
IN A,(PSGRD)
AND MSDA   ; Mascara bit TRIGGER
NEG ; CY=(A==0)
RL C
;
LD A,15
OUT (PSGAD),A
LD A,E ; Recupera est reg 15
RES ASCL,A ; SCL=0
OUT (PSGWR),A
DJNZ AGBY1
;
LD B,A
RET
;
BGBYTE:
SET BSDA,A ; SDA=1
OUT (PSGWR),A
LD BC,0800H ; B=8, C=0
;
BGBY1:
SET BSCL,A ; SCL=1
OUT (PSGWR),A
LD E,A     ; Salva A
LD A,14
OUT (PSGAD),A ; Selec REG 14
IN A,(PSGRD)
AND MSDA   ; Mascara bit TRIGGER
NEG ; CY=(A==0)
RL C
;
LD A,15
OUT (PSGAD),A
LD A,E ; Recupera est reg 15
RES BSCL,A ; SCL=0
OUT (PSGWR),A
DJNZ BGBY1
;
LD B,A
RET
;
J2CPAK: ; PUT ACK
LD A,B
BIT ABSEL,A
JR NZ,BPAK
;
APAK:
RES ASDA,A
OUT (PSGWR),A
JR NC,APAK1 ; SDA=CY
SET ASDA,A
;
APAK1:
OUT (PSGWR),A
SET ASCL,A ; SCL=1
OUT (PSGWR),A
RES ASCL,A ; SCL=0
OUT (PSGWR),A
SET ASDA,A ; SDA=1
OUT (PSGWR),A
LD B,A
RET
;
BPAK:
RES BSDA,A
OUT (PSGWR),A
JR NC,BPAK1 ; SDA=CY
SET BSDA,A
;
BPAK1:
OUT (PSGWR),A
SET BSCL,A ; SCL=1
OUT (PSGWR),A
RES BSCL,A ; SCL=0
OUT (PSGWR),A
SET BSDA,A ; SDA=1
OUT (PSGWR),A
LD B,A
RET
;
J2CGAK: ; GET ACK
LD A,B
BIT ABSEL,A
JR NZ,BGAK
;
AGAK:
SET ASDA,A ; SDA=1
OUT (PSGWR),A
SET ASCL,A ; SCL=1
OUT (PSGWR),A
PUSH HL
LD HL,TIMEOUT
LD B,A  ; Salva est reg 15
;
LD A,14
OUT (PSGAD),A; Sel REG 14
AGAK1:
IN A,(PSGRD)
AND MSDA ; checa e tbem clear CY
JR Z,AGAK2 ; Sai ao receber ACK
;
DEC HL
LD A,H
OR L
JR NZ,AGAK1
;
SCF ; Indica TIMEOUT
;
AGAK2:
LD A,15
OUT (PSGAD),A ; Sel Reg 15
LD A,B
RES ASCL,A
OUT (PSGWR),A
LD B,A
POP HL
RET
;
BGAK:
SET BSDA,A ; SDA=1
OUT (PSGWR),A
SET BSCL,A ; SCL=1
OUT (PSGWR),A
PUSH HL
LD HL,TIMEOUT
LD B,A  ; Salva est reg 15
;
LD A,14
OUT (PSGAD),A; Sel REG 14
BGAK1:
IN A,(PSGRD)
AND MSDA ; checa e tbem clear CY
JR Z,BGAK2 ; Sai ao receber ACK
;
DEC HL
LD A,H
OR L
JR NZ,BGAK1
;
SCF ; Indica TIMEOUT
;
BGAK2:
LD A,15
OUT (PSGAD),A ; Sel Reg 15
LD A,B
RES BSCL,A
OUT (PSGWR),A
LD B,A
POP HL
RET
;
;
J2CLOGON:
CALL J2CSTART
CALL J2CPB
CALL J2CGAK
RET
;
J2CP16ADR:
CALL J2CLOGON
RET C
PADR2:
LD C,H
CALL J2CPB
CALL J2CGAK
RET C
LD C,L
CALL J2CPB
CALL J2CGAK
RET
;
J2CP8ADR:
CALL J2CLOGON
RET C
P8ADR2:
LD C,L
CALL J2CPB
CALL J2CGAK
RET
;
WAIT1MS:
PUSH HL
PUSH AF
LD HL,T1MS3MHZ
WAIT1: DEC HL
LD A,H
OR L
JR NZ,WAIT1
POP AF
POP HL
RET
;
ZEND:
;
ORG 0B000H
PSGSAV: DB 1
VERBOSE: DB 1
RTCBUF:  DS 7
;
