; Micro-contrôleur :	16F876
;
; MEMOIRE PROGRAMME UTILISEE 12%
; MEMOIRE RAM UTILISEE       32%
;
W		EQU	H'000'
F		EQU	H'001'
IRP		EQU	H'007'
RP1		EQU	H'006'
RP0		EQU	H'005'
Z		EQU	H'002'
C		EQU	H'000'
INDF		EQU	H'000'
PCL		EQU	H'002'
STATUS		EQU	H'003'
FSR		EQU	H'004'
PORTB		EQU	H'006'
PCLATH		EQU	H'00A'
PIR1		EQU	H'00C'
SSPBUF		EQU	H'013'
SSPCON		EQU	H'014'
ADRESH		EQU	H'01E'
ADCON0		EQU	H'01F'
TRISB		EQU	H'086'
SSPCON2		EQU	H'091'
SSPADD		EQU	H'093'
SSPSTAT		EQU	H'094'
ADRESL		EQU	H'09E'
ADCON1		EQU	H'09F'
TAMPON		EQU H'020'
; setup paquet : 8 octets
SETUPTYPE	EQU	H'028'
SETUPREQ	EQU	H'029'
SETUPVAL_L	EQU	H'02A'
SETUPVAL_H	EQU	H'02B'
SETUPIND_L	EQU	H'02C'
SETUPIND_H	EQU	H'02D'
SETUPLEN_L	EQU	H'02E'
SETUPLEN_H	EQU	H'02F'
INPOINTEUR	EQU	H'030'
OUTPOINTEUR	EQU	H'031'
; att. buff_stat sert de premier octet de buff_head !
BUFF_STAT	EQU	H'032'
BUFF_HEAD	EQU	H'033'
D11_CDE		EQU	H'034'
BTS			EQU	H'035'
FLAGS		EQU	H'036'
ADRESSE		EQU	H'037'
CONFIG		EQU	H'038'
PARA1		EQU	H'039'
PARA2		EQU	H'03A'
PARA3		EQU	H'03B'
PARA4		EQU	H'03C'
TEMPO1		EQU	H'03D'
TEMPO2		EQU	H'03E'
IRQ_L		EQU	H'03F'
IRQ_H		EQU	H'040'
ADR_DATA_L	EQU	H'041'
ADR_DATA_H	EQU	H'042'
CIRC_BUF	EQU H'0A0'
		__CONFIG	H'3D39'	
;	
; Commande du PDIUSB
D11_SET_HUB_AD	EQU	H'D0'
D11_SET_ADD_ENA	EQU	H'D1'
D11_SET_ENDPT_E	EQU	H'D8'
D11_SET_MODE	EQU	H'F3'
D11_READ_INT_RE	EQU	H'F4'
D11_READ_LAST_T	EQU	H'40'
D11_SET_EPT_ST	EQU	H'40'
D11_READ_EPT_ST	EQU	H'80'
D11_READ_BUF	EQU	H'F0'
D11_WRITE_BUF	EQU	H'F0'
D11_CLEAR_BUF	EQU	H'F2'
D11_VAL_BUF	EQU	H'FA'
D11_ACK_SETUP	EQU	H'F1'
;
; Adresses I2C du PDIUSB
D11_DATA_ADR_W	EQU	H'34'
D11_DATA_ADR_R	EQU	H'35'
D11_CMD_ADDR	EQU	H'36'
;
; index des terminaisons du PDIUSB
D11_EPT_EP0_OUT	EQU	2
D11_EPT_EP0_IN	EQU	3
D11_EPT_EP1_OUT	EQU	5
D11_EPT_EP1_IN	EQU	4
D11_EPT_EP2_OUT	EQU	6
D11_EPT_EP2_IN	EQU	7
D11_EPT_EP3_OUT	EQU	8
D11_EPT_EP3_IN	EQU	9
; 
; Types de requêtes USB
STD_DEVICE_REQ	EQU	0
STD_INTER_REQ	EQU	1
STD_ENDPT_REQ	EQU	2
VEND_DEVICE_REQ	EQU	H'40'
VEND_ENDPT_REQ	EQU	H'42'
; 
; requêtes USB
GET_STATUS	EQU	0
CLEAR_FEATURE	EQU	1
SET_FEATURE	EQU	3
SET_ADDRESS	EQU	5
GET_DESCRIPTOR	EQU	6
GET_CONFIG	EQU	8
SET_CONFIG	EQU	9
GET_INTERFACE	EQU	H'0A'
SET_INTERFACE	EQU	H'0B'
VEND_GET_VAL	EQU	1
VEND_SET_NIB	EQU	2
; 
; Types de descripteurs USB
TYPE_DEV_DES 	EQU	1
TYPE_CONF_DES 	EQU	2
TYPE_STR_DES 	EQU	3
TYPE_INT_DES 	EQU	4
TYPE_EPT_DES 	EQU	5
;
; identificateurs de bit
SMP 		EQU	7
SSPEN 		EQU	5
SSPIF 		EQU	3
BF 		EQU	0
RCEN 		EQU	3
ACKDT 		EQU	5
ACKEN 		EQU	4
SEN 		EQU	0
PEN 		EQU	2
D11_INT_BUS_RES EQU	6
D11_INT_EP0_OUT EQU	2
D11_INT_EP0_IN 	EQU	3
D11_INT_EP1_OUT EQU	5
D11_INT_EP1_IN 	EQU	4
D11_INT_EP2_OUT EQU	6
D11_INT_EP2_IN 	EQU	7
D11_INT_EP3_OUT EQU	0
D11_INT_EP3_IN 	EQU	1
PDI_INT 	EQU	0
PDI_RESET 	EQU	2
LED 		EQU	3
POUSSOIR 	EQU	4
F_ADR 		EQU	0
;
; programme reset
		ORG	0
; 
; initialisations
; ---------------
		BCF	STATUS,RP1
		BSF	STATUS,RP0
; bits 0,1 & 4 du port B en entrée
		MOVLW	B'00010011'
		MOVWF	TRISB
; port A en entrées analogiques
		MOVLW	H'80'
		MOVWF	ADCON1
; clock I2C = Fosc / (4*(SSPADD+1))
		CLRF	SSPADD
; réglage I2C
		BSF	SSPSTAT,SMP
		BCF	STATUS,RP1
		BCF	STATUS,RP0
ATTEND		BTFSS	PORTB,POUSSOIR
		GOTO	ATTEND
		BCF	PORTB,PDI_RESET
		BCF	PORTB,LED
		CLRF	INPOINTEUR
		CLRF	OUTPOINTEUR
		CLRF	FLAGS
; réglage I2C
		MOVLW	H'08'
		MOVWF	SSPCON
		BSF	SSPCON,SSPEN
		BSF	PORTB,PDI_RESET
		CALL	INITUSB
;
; boucle principale
; -----------------
BOUCLE		BTFSS	PORTB,PDI_INT
		CALL	GETIRQ
		GOTO	BOUCLE
; 
; sous-programmes
; ---------------
; entrée et sortie de tout sp en page 0
; 
; ENVOI DE DONNEES A UNE TERMINAISON
;
; index de terminaison dans d11_cde
; nombre d'octets à envoyer dans para3
; adresse du tampon dans para4
; utilise : w, tempo1, tempo2
; sélection de la terminaison
WRITETERM	MOVLW	1
		MOVWF	PARA1
		MOVLW	BUFF_STAT
		MOVWF	PARA2
		CALL	D11READ
; envoi de l'en-tête
		CLRF	BUFF_STAT
		MOVF	PARA3,W
		MOVWF	BUFF_HEAD
		MOVLW	D11_WRITE_BUF
		MOVWF	D11_CDE
		MOVLW	2
		MOVWF	PARA1
		MOVLW	BUFF_STAT
		MOVWF	PARA2
		CALL	D11WRITE
; envoi des données
		MOVF	PARA3,W
		BTFSC	STATUS,Z
		GOTO	$+.6
		MOVF	PARA3,W
		MOVWF	PARA1
		MOVF	PARA4,W
		MOVWF	PARA2
		CALL	D11WRITE
; validation de l'envoi
		MOVLW	D11_VAL_BUF
		MOVWF	D11_CDE
		CLRF	PARA1
		CALL	D11WRITE
		RETURN
; 
; LECTURE DES DONNEES SUR UNE TERMINAISON
;
; index de terminaison dans d11_cde
; adresse du tampon dans para4
; valeur de retour dans buff_head : nombre d'octets lus
; utilise : w, tempo1, tempo2
READTERM	CLRF	BUFF_HEAD
; sélection de la terminaison
		MOVLW	1
		MOVWF	PARA1
		CLRF	BUFF_STAT
		MOVLW	BUFF_STAT
		MOVWF	PARA2
		CALL	D11READ
		MOVF	BUFF_STAT,W
		BTFSC	STATUS,Z
		GOTO	LAB261
		CLRF	BUFF_STAT
; lecture de l'en-tête
		MOVLW	D11_READ_BUF
		MOVWF	D11_CDE
		MOVLW	2
		MOVWF	PARA1
; buff_stat est le 1er octet de buff_head
		MOVLW	BUFF_STAT
		MOVWF	PARA2
		CALL	D11READ
; lecture des données
		MOVF	BUFF_HEAD,W
		BTFSC	STATUS,Z
		GOTO	$+.6
		MOVF	BUFF_HEAD,W
		MOVWF	PARA1
		MOVF	PARA4,W
		MOVWF	PARA2
		CALL	D11READ
; reset du buffer
		MOVLW	D11_CLEAR_BUF
		MOVWF	D11_CDE
		CLRF	PARA1
		CALL	D11WRITE
LAB261		RETURN
;
; ENVOI D'UNE COMMANDE D 'ECRITURE AU PDIUSB
;
; instruction dans d11_cde
; nombre d'octets à envoyer dans para1
; adresse du tampon dans para2
; utilise : w, tempo1, tempo2
; envoie de l'instruction
D11WRITE	MOVF	PARA1,W
		MOVWF	TEMPO1
		MOVF	PARA2,W
		MOVWF	TEMPO2
		MOVLW	1
		MOVWF	PARA1
		MOVLW	D11_CDE
		MOVWF	PARA2
		MOVLW	D11_CMD_ADDR
		CALL	I2CWRITE
; envoie des paramètres de l'instruction
		MOVF	TEMPO1,W
		BTFSC	STATUS,Z
		GOTO	$+.7
		MOVF	TEMPO1,W
		MOVWF	PARA1
		MOVF	TEMPO2,W
		MOVWF	PARA2
		MOVLW	D11_DATA_ADR_W
		CALL	I2CWRITE
		RETURN
; 
; ENVOI D'UNE COMMANDE DE LECTURE AU PDIUSB
;
; instruction dans d11_cde
; nombre d'octets à recevoir dans para1
; adresse du tampon dans para2
; utilise : w, tempo1, tempo2
; envoie de l'instruction
D11READ		MOVF	PARA1,W
		MOVWF	TEMPO1
		MOVF	PARA2,W
		MOVWF	TEMPO2
		MOVLW	1
		MOVWF	PARA1
		MOVLW	D11_CDE
		MOVWF	PARA2
		MOVLW	D11_CMD_ADDR
		CALL	I2CWRITE
; reception des paramètres de l'instruction
		MOVF	TEMPO1,W
		BTFSC	STATUS,Z
		GOTO	LAB329
		MOVF	TEMPO1,W
		MOVWF	PARA1
		MOVLW	D11_DATA_ADR_R
		CALL	I2CSTART
; envoi adresse. I2Cstart n'a pas modifié W
		CALL	I2CWRITEBYTE
; remplissage tampon
		MOVF	TEMPO2,W
		MOVWF	FSR
LAB322		MOVF	PARA1,W
		CALL	I2CREADBYTE
		MOVWF	INDF
		INCF	FSR,F
		DECFSZ	PARA1,F
		GOTO	LAB322
		CALL	I2CSTOP
LAB329		RETURN
; 
; ENVOI D'UN PAQUET D'EMISSION I2C AU PDIUSB
;
; adresse I2C dans W
; nombre d'octets à envoyer dans para1
; adresse du tampon dans para2
; utilise : w
I2CWRITE	CALL	I2CSTART
; envoi adresse. I2Cstart n'a pas modifié W
		CALL	I2CWRITEBYTE
; émission des octets du tampon
		MOVF	PARA2,W
		MOVWF	FSR
LAB343		MOVF	INDF,W
		CALL	I2CWRITEBYTE
		INCF	FSR,F
		DECFSZ	PARA1,F
		GOTO	LAB343
		CALL	I2CSTOP
		RETURN
; 
; EMISSION D'UN OCTET SUR BUS I2C
;
; Octet à envoyer dans W
; utilise : rien
I2CWRITEBYTE	BCF	PIR1,SSPIF
		MOVWF	SSPBUF
		BCF		STATUS,RP1
		BSF		STATUS,RP0
		BTFSC	SSPSTAT,BF
		GOTO	$-.1
		BCF		STATUS,RP1
		BCF		STATUS,RP0
		BTFSS	PIR1,SSPIF
		GOTO	$-.1
		RETURN
; 
; RECEPTION D'UN OCTET SUR BUS I2C
;
; décompte du nombre d'octet dans W pour acquittement du dernier
; Octet renvoyé dans W
; utilise : w, tempo1, tempo2
I2CREADBYTE	MOVWF	TEMPO1
		BCF		PIR1,SSPIF
		BCF		STATUS,RP1
		BSF		STATUS,RP0
		BSF		SSPCON2,RCEN
		BCF		STATUS,RP1
		BCF		STATUS,RP0
		BTFSS	PIR1,SSPIF
		GOTO	$-.1
		MOVF	SSPBUF,W
		MOVWF	TEMPO2
; Si décompte = 1 acquitter
		MOVF	TEMPO1,W
		SUBLW	1
		BTFSC	STATUS,C
		GOTO	$+.5
		BCF		STATUS,RP1
		BSF		STATUS,RP0
		BCF		SSPCON2,ACKDT
		GOTO	$+.4
		BCF		STATUS,RP1
		BSF		STATUS,RP0
		BSF		SSPCON2,ACKDT
		BSF		SSPCON2,ACKEN
		BTFSC	SSPCON2,ACKEN
		GOTO	$-.1
		BCF		STATUS,RP1
		BCF		STATUS,RP0
		MOVF	TEMPO2,W
		RETURN
; 
; EMISSION START I2C
;
; utilise : rien
I2CSTART	BCF	STATUS,RP1
		BSF		STATUS,RP0
		BSF		SSPCON2,SEN
		BTFSC	SSPCON2,SEN
		GOTO	$-.1
		BCF		STATUS,RP1
		BCF		STATUS,RP0
		RETURN
; 
; EMISION STOP I2C
;
; utilise : rien
I2CSTOP		BCF		STATUS,RP1
		BSF		STATUS,RP0
		BSF		SSPCON2,PEN
		BTFSC	SSPCON2,PEN
		GOTO	$-.1
		BCF		STATUS,RP1
		BCF		STATUS,RP0
		RETURN
; 
; INITIALISATION DU PORT USB
;
; utilise : W, tempo1, tempo2
; désactive le hub (non documenté)
INITUSB		MOVLW	D11_SET_HUB_AD
		MOVWF	D11_CDE
		MOVLW	1
		MOVWF	PARA1
		MOVLW	TAMPON
		MOVWF	PARA2
		CLRF	TAMPON
		CALL	D11WRITE
; adresse par défaut
		MOVLW	D11_SET_ADD_ENA
		MOVWF	D11_CDE
		MOVLW	1
		MOVWF	PARA1
		MOVLW	H'80'
		MOVWF	TAMPON
		CALL	D11WRITE
; terminaisons génériques
		MOVLW	D11_SET_ENDPT_E
		MOVWF	D11_CDE
		MOVLW	1
		MOVWF	PARA1
		MOVLW	2
		MOVWF	TAMPON
		CALL	D11WRITE
; paramètrage
		MOVLW	D11_SET_MODE
		MOVWF	D11_CDE
		MOVLW	2
		MOVWF	PARA1
		MOVLW	H'97'
		MOVWF	TAMPON
		MOVLW	H'0B'
		MOVWF	TAMPON + 1
		CALL	D11WRITE
		RETURN
; 
; GESTIONNAIRE DES INTERRUPTIONS DU PDIUSB
;
GETIRQ		MOVLW	D11_READ_INT_RE
		MOVWF	D11_CDE
		MOVLW	2
		MOVWF	PARA1
		MOVLW	IRQ_L
		MOVWF	PARA2
; lecture du code interruption
		CALL	D11READ
; reset du bus usb
		BTFSS	IRQ_H,D11_INT_BUS_RES
		GOTO	$+.2
		CALL	INITUSB
; reception sur EP0
		BTFSS	IRQ_L,D11_INT_EP0_OUT
		GOTO	$+.2
		CALL	EP0_REQ
; émission sur EP0
		BTFSS	IRQ_L,D11_INT_EP0_IN
		GOTO	LAB528
; si adressage en cours
		BTFSS	FLAGS,F_ADR
		GOTO	LAB517
		MOVLW	D11_SET_ADD_ENA
		MOVWF	D11_CDE
		MOVLW	1
		MOVWF	PARA1
		MOVLW	ADRESSE
		MOVWF	PARA2
		CALL	D11WRITE
		MOVLW   D11_READ_LAST_T
		MOVWF	D11_CDE
		MOVLW	D11_EPT_EP0_IN
		ADDWF	D11_CDE,F
		MOVLW	1
		MOVWF	PARA1
		MOVLW	TAMPON
		MOVWF	PARA2
		CALL	D11READ
; adressage fini, lever le drapeau
		BCF		FLAGS,F_ADR
		GOTO	LAB528
LAB517		MOVLW	D11_READ_LAST_T
		MOVWF	D11_CDE
		MOVLW	D11_EPT_EP0_IN
		ADDWF	D11_CDE,F
		MOVLW	1
		MOVWF	PARA1
		MOVLW	TAMPON
		MOVWF	PARA2
		CALL	D11READ
		CALL	WRITEDESC
; reception sur EP1
LAB528		BTFSS	IRQ_L,D11_INT_EP1_OUT
		GOTO	LAB576
		MOVLW	D11_READ_LAST_T
		MOVWF	D11_CDE
		MOVLW	D11_EPT_EP1_OUT
		ADDWF	D11_CDE,F
		MOVLW	1
		MOVWF	PARA1
		MOVLW	TAMPON
		MOVWF	PARA2
		CALL	D11READ
		MOVLW	D11_EPT_EP1_OUT
		MOVWF	D11_CDE
		MOVLW	TAMPON
		MOVWF	PARA4
		CALL	READTERM
; buff_head = nb octets reçus
; transfert dans le tampon circulaire
		BCF		STATUS,IRP
		MOVLW	TAMPON
		ADDWF	BUFF_HEAD,F
		MOVLW	TAMPON
		MOVWF	TEMPO2
BOUCLE2		MOVF	BUFF_HEAD,W
		SUBWF	TEMPO2,W
		BTFSC	STATUS,C
		GOTO	SORTIR2
		MOVF	TEMPO2,W
		MOVWF	FSR
		MOVF	INDF,W
		MOVWF	TEMPO1
		MOVLW	CIRC_BUF
		MOVWF	FSR
		MOVF	INPOINTEUR,W
		ADDWF	FSR,F
		MOVF	TEMPO1,W
		MOVWF	INDF
		INCF	INPOINTEUR,F
		MOVLW	H'50'
		SUBWF	INPOINTEUR,W
		BTFSS	STATUS,C
		GOTO	$+.2
		CLRF	INPOINTEUR
		INCF	TEMPO2,F
		GOTO	BOUCLE2
SORTIR2		CALL	LOADCIRC
; émission sur EP1
LAB576		BTFSS	IRQ_L,D11_INT_EP1_IN
		GOTO	LAB589
		MOVLW	D11_READ_LAST_T
		MOVWF	D11_CDE
		MOVLW	D11_EPT_EP1_IN
		ADDWF	D11_CDE,F
		MOVLW	1
		MOVWF	PARA1
		MOVLW	TAMPON
		MOVWF	PARA2
		CALL	D11READ
		CALL	LOADCIRC
; reception sur EP2
LAB589		BTFSS	IRQ_L,D11_INT_EP2_OUT
		GOTO	LAB610
		MOVLW	D11_READ_LAST_T
		MOVWF	D11_CDE
		MOVLW	D11_EPT_EP2_OUT
		ADDWF	D11_CDE,F
		MOVLW	1
		MOVWF	PARA1
		MOVLW	TAMPON
		MOVWF	PARA2
		CALL	D11READ
		MOVLW	D11_SET_EPT_ST
		MOVWF	D11_CDE
		MOVLW	D11_EPT_EP2_OUT
		ADDWF	D11_CDE,F
		MOVLW	1
		MOVWF	PARA1
		MOVLW	1
		MOVWF	TAMPON
		CALL	D11WRITE
; émission sur EP2
LAB610		BTFSS	IRQ_L,D11_INT_EP2_IN
		GOTO	LAB631
		MOVLW	D11_READ_LAST_T
		MOVWF	D11_CDE
		MOVLW	D11_EPT_EP2_IN
		ADDWF	D11_CDE,F
		MOVLW	1
		MOVWF	PARA1
		MOVLW	TAMPON
		MOVWF	PARA2
		CALL	D11READ
		MOVLW	D11_SET_EPT_ST
		MOVWF	D11_CDE
		MOVLW	D11_EPT_EP2_IN
		ADDWF	D11_CDE,F
		MOVLW	1
		MOVWF	PARA1
		MOVLW	1
		MOVWF	TAMPON
		CALL	D11WRITE
; reception sur EP3
LAB631		BTFSS	IRQ_H,D11_INT_EP3_OUT
		GOTO	LAB652
		MOVLW	D11_READ_LAST_T
		MOVWF	D11_CDE
		MOVLW	D11_EPT_EP3_OUT
		ADDWF	D11_CDE,F
		MOVLW	1
		MOVWF	PARA1
		MOVLW	TAMPON
		MOVWF	PARA2
		CALL	D11READ
		MOVLW	D11_SET_EPT_ST
		MOVWF	D11_CDE
		MOVLW	D11_EPT_EP3_OUT
		ADDWF	D11_CDE,F
		MOVLW	1
		MOVWF	PARA1
		MOVLW	1
		MOVWF	TAMPON
		CALL	D11WRITE
; émission sur EP3
LAB652		BTFSS	IRQ_H,D11_INT_EP3_IN
		GOTO	LAB672
		MOVLW	D11_READ_LAST_T
		MOVWF	D11_CDE
		MOVLW	D11_EPT_EP3_IN
		ADDWF	D11_CDE,F
		MOVLW	1
		MOVWF	PARA1
		MOVLW	TAMPON
		MOVWF	PARA2
		CALL	D11READ
		MOVLW	D11_SET_EPT_ST
		MOVWF	D11_CDE
		MOVLW	D11_EPT_EP3_IN
		ADDWF	D11_CDE,F
		MOVLW	1
		MOVWF	PARA1
		MOVLW	1
		MOVWF	TAMPON
		CALL	D11WRITE
LAB672		RETURN
; 
; DESACTIVATION TERMINAISON 0 SUR ERREUR
;
STALLTERM	MOVLW	1
		MOVWF	PARA1
		MOVLW	1
		MOVWF	TAMPON
		MOVLW	TAMPON
		MOVWF	PARA2
		MOVLW	D11_SET_EPT_ST
		MOVWF	D11_CDE
		MOVLW	D11_EPT_EP0_IN
		ADDWF	D11_CDE,F
		CALL	D11WRITE
		MOVLW	1
		MOVWF	PARA1
		MOVLW	D11_SET_EPT_ST
		MOVWF	D11_CDE
		MOVLW	D11_EPT_EP0_OUT
		ADDWF	D11_CDE,F
		RETURN
;
; ENVOI D'UN (MORCEAU DE) DESCRIPTEUR 
;
; utilise bts (bytes to send) et adr_data
; utilise tempo1
WRITEDESC	MOVLW	D11_EPT_EP0_IN
		MOVWF	D11_CDE
; si appelé avec bts=0 : moins de données à transmettre
; que la requête n'en prévoit. Envoi paquet de longueur 0 pour indiquer la fin.
		MOVF	BTS,W
		BTFSS	STATUS,Z
		GOTO	$+.4
		CLRF	PARA3
		CALL	WRITETERM
		GOTO	LAB733
		MOVF	BTS,W
		MOVWF	TEMPO1
		MOVF	BTS,W
		SUBLW	8
		BTFSC	STATUS,C
		GOTO	$+.3
		MOVLW	8
		MOVWF	TEMPO1
		MOVF	TEMPO1,W
		MOVWF	PARA3
		MOVLW	TAMPON
		MOVWF	PARA4
		MOVLW	TAMPON
		MOVWF	FSR
PLUSDATA	CALL	GETDATA
		MOVWF	INDF
		DECF	BTS,F
		INCF	ADR_DATA_L,F
		BTFSC	STATUS,Z
		INCF	ADR_DATA_H,F
		INCF	FSR,F
		DECFSZ	TEMPO1,F
		GOTO	PLUSDATA
		CALL	WRITETERM
LAB733		RETURN
; 
; CHARGEMENT DU TAMPON CIRCULAIRE
;
; utilise : tempo1, tempo2
LOADCIRC	MOVLW	D11_EPT_EP1_IN
		MOVWF	D11_CDE
		MOVLW	1
		MOVWF	PARA1
		MOVLW	TAMPON
		MOVWF	PARA2
; lecture du statut
		CALL	D11READ
		MOVF	TAMPON,W
		BTFSS	STATUS,Z
		GOTO	SORTIR3
; il faut envoyer des octets
		BCF		STATUS,IRP
		CLRF	TEMPO2
BOUCLE3		MOVLW	8
		SUBWF	TEMPO2,W
		BTFSC	STATUS,C
		GOTO	FINB3
		MOVF	OUTPOINTEUR,W
		MOVWF	FSR
		MOVLW	CIRC_BUF
		ADDWF	FSR,F
		MOVF	INDF,W
		MOVWF	TEMPO1
		MOVF	TEMPO2,W
		MOVWF	FSR
		MOVLW	TAMPON
		ADDWF	FSR,F		
		MOVF	TEMPO1,W
		MOVWF	INDF
		INCF	OUTPOINTEUR,F
		MOVLW	H'50'
		SUBWF	OUTPOINTEUR,W
		BTFSS	STATUS,C
		GOTO	$+.2
		CLRF	OUTPOINTEUR
		INCF	TEMPO2,F
		GOTO	BOUCLE3
FINB3		MOVLW	D11_EPT_EP1_IN
		MOVWF	D11_CDE
		MOVF	TEMPO2,W
		MOVWF	PARA3
		MOVLW	TAMPON
		MOVWF	PARA4
		CALL	WRITETERM
SORTIR3	RETURN
; 
; VA CHERCHER UN OCTET EN ROM
; adresse de l'octet dans adr_data
; RETURN par écriture dans PCL
; retour dans W
;
GETDATA		MOVF	ADR_DATA_H,W
		MOVWF	PCLATH
		MOVF	ADR_DATA_L,W
		MOVWF	PCL
; 
; TRAITEMENT REQUETES SUR TERMINAISON 0
;
EP0_REQ		MOVLW	D11_READ_LAST_T
		MOVWF	D11_CDE
		MOVLW	D11_EPT_EP0_OUT
		ADDWF	D11_CDE,F
		MOVLW	1
		MOVWF	PARA1
		MOVLW	TAMPON
		MOVWF	PARA2
		CALL	D11READ
; vérifier s'il s'agit d'un paquet de setup
		BTFSS	TAMPON,5
		GOTO	LAB1276
; lire le paquet de setup
		MOVLW	D11_EPT_EP0_OUT
		MOVWF	D11_CDE
		MOVLW	SETUPTYPE
		MOVWF	PARA4
		CALL	READTERM
; aquittements
		MOVLW	D11_ACK_SETUP
		MOVWF	D11_CDE
		CLRF	PARA1
		CALL	D11WRITE
		MOVLW	D11_CLEAR_BUF
		MOVWF	D11_CDE
		CLRF	PARA1
		CALL	D11WRITE
		MOVLW	D11_EPT_EP0_IN
		MOVWF	D11_CDE
		CLRF	PARA1
		CALL	D11WRITE
		MOVLW	D11_ACK_SETUP
		MOVWF	D11_CDE
		CLRF	PARA1
		CALL	D11WRITE
; masquer bit7 de requesttype
		BCF		SETUPTYPE,7
; selon le type de requête
		MOVF	SETUPTYPE,W
; STD_DEVICE_REQ = 0
		BTFSS	STATUS,Z
		GOTO	LAB996
; quelle requête d'appareil ?
		MOVF	SETUPREQ,W
		BTFSS	STATUS,Z
		GOTO	LAB864
; pas de wakeup et self powered
		MOVLW	D11_EPT_EP0_IN
		MOVWF	D11_CDE
		MOVLW	2
		MOVWF	PARA3
		MOVLW	TAMPON
		MOVWF	PARA4
		MOVLW	1
		MOVWF	TAMPON
		CLRF	TAMPON + 1
		CALL	WRITETERM
		GOTO	FINREQ
LAB864		MOVLW	CLEAR_FEATURE
		SUBWF	SETUPREQ,W
		BTFSS	STATUS,Z
		GOTO	$+.2
		CALL	ERRORREQ
		MOVLW	SET_FEATURE
		SUBWF	SETUPREQ,W
		BTFSS	STATUS,Z
		GOTO	$+.2
		GOTO	ERRORREQ
		MOVLW	SET_ADDRESS
		SUBWF	SETUPREQ,W
		BTFSS	STATUS,Z
		GOTO	LAB887
		MOVF	SETUPVAL_L,W
		MOVWF	ADRESSE
		BSF		ADRESSE,7
		MOVLW	D11_EPT_EP0_IN
		MOVWF	D11_CDE
		CLRF	PARA3
		CALL	WRITETERM
		BSF		FLAGS,F_ADR
		GOTO	FINREQ
LAB887		MOVLW	GET_DESCRIPTOR
		SUBWF	SETUPREQ,W
		BTFSS	STATUS,Z
		GOTO	LAB966
; borner la longueur demandée à 255
		MOVF	SETUPLEN_H,W
		BTFSC	STATUS,Z
		GOTO	$+.3
		MOVLW	H'FF'
		MOVWF	SETUPLEN_L
		MOVLW	TYPE_DEV_DES
		SUBWF	SETUPVAL_H,W
		BTFSS	STATUS,Z
		GOTO	$+.6
		MOVLW 	HIGH devdes
		MOVWF	ADR_DATA_H
		MOVLW 	LOW devdes
		MOVWF	ADR_DATA_L
		GOTO	PLUSLOIN
		MOVLW	TYPE_CONF_DES
		SUBWF	SETUPVAL_H,W
		BTFSS	STATUS,Z
		GOTO	LAB926
		MOVLW 	HIGH confdes
		MOVWF	ADR_DATA_H
		MOVLW 	LOW confdes
		MOVWF	ADR_DATA_L
; Longueur du descripteur de configuration dans le 3ème octet
		MOVLW	2
		ADDWF	ADR_DATA_L,F
		BTFSC	STATUS,C
		INCF	ADR_DATA_H,F
		CALL	GETDATA
		MOVWF	BTS
		MOVLW 	HIGH confdes
		MOVWF	ADR_DATA_H
		MOVLW 	LOW confdes
		MOVWF	ADR_DATA_L
		GOTO	BTSOK
LAB926		MOVLW	TYPE_STR_DES
		SUBWF	SETUPVAL_H,W
		BTFSS	STATUS,Z
		GOTO	LAB965
; quel index de chaine
		MOVF	SETUPVAL_L,W
		BTFSS	STATUS,Z
		GOTO	$+.6
; chaine des langues
		MOVLW 	HIGH langdes
		MOVWF	ADR_DATA_H
		MOVLW 	LOW langdes
		MOVWF	ADR_DATA_L
		GOTO	PLUSLOIN
		MOVLW	1
		SUBWF	SETUPVAL_L,W
		BTFSS	STATUS,Z
		GOTO	$+.6
; chaine 'nom du fabriquant'
		MOVLW 	HIGH venddes
		MOVWF	ADR_DATA_H
		MOVLW 	LOW venddes
		MOVWF	ADR_DATA_L
		GOTO	PLUSLOIN
		CLRF	BTS
		GOTO	FINREQ
; 1er octet du descripteur est sa longueur
PLUSLOIN	CALL	GETDATA
		MOVWF	BTS
; limite la longueur à ce qui est demandé
; maxi 255 octets - A vérifier
BTSOK		MOVF	BTS,W
		SUBWF	SETUPLEN_L,W
		BTFSC	STATUS,C
		GOTO	$+.3
		MOVF	SETUPLEN_L,W
		MOVWF	BTS
		CALL	WRITEDESC
		GOTO	FINREQ
LAB965		GOTO	ERRORREQ
LAB966		MOVLW	GET_CONFIG
		SUBWF	SETUPREQ,W
		BTFSS	STATUS,Z
		GOTO	$+.9
		MOVLW	D11_EPT_EP0_IN
		MOVWF	D11_CDE
		MOVLW	1
		MOVWF	PARA3
		MOVLW	CONFIG
		MOVWF	PARA4
		CALL	WRITETERM
		GOTO	FINREQ
		MOVLW	SET_CONFIG
		SUBWF	SETUPREQ,W
		BTFSS	STATUS,Z
		GOTO	LAB995
		MOVF	SETUPVAL_L,W
		MOVWF	CONFIG
		MOVLW	D11_EPT_EP0_IN
		MOVWF	D11_CDE
		CLRF	PARA3
		CALL	WRITETERM
		MOVF	CONFIG,W
		BTFSC	STATUS,Z
		GOTO	$+.3
		BSF		PORTB,LED
		GOTO	$+.2
		BCF		PORTB,LED
		GOTO	FINREQ
LAB995		GOTO	ERRORREQ
LAB996		MOVLW	STD_INTER_REQ
		SUBWF	SETUPTYPE,W
		BTFSS	STATUS,Z
		GOTO	LAB1059
		MOVF	SETUPREQ,W
; GET_STATUS = 0
		BTFSS	STATUS,Z
		GOTO	LAB1014
		MOVLW	D11_EPT_EP0_IN
		MOVWF	D11_CDE
		MOVLW	2
		MOVWF	PARA3
		MOVLW	TAMPON
		MOVWF	PARA4
		CLRF	TAMPON
		CLRF	TAMPON + 1
		CALL	WRITETERM
		GOTO	FINREQ
LAB1014		MOVLW	SET_INTERFACE
		SUBWF	SETUPREQ,W
		BTFSS	STATUS,Z
		GOTO	LAB1037
		MOVF	SETUPIND_H,W
		BTFSS	STATUS,Z
		GOTO	LAB1035
		MOVF	SETUPIND_L,W
		BTFSS	STATUS,Z
		GOTO	LAB1035
		MOVF	SETUPVAL_H,W
		BTFSS	STATUS,Z
		GOTO	LAB1035
		MOVF	SETUPVAL_L,W
		BTFSS	STATUS,Z
		GOTO	LAB1035
		MOVLW	D11_EPT_EP0_IN
		MOVWF	D11_CDE
		CLRF	PARA3
		CALL	WRITETERM
		GOTO	$+.2
LAB1035		GOTO	ERRORREQ
		GOTO	FINREQ
LAB1037		MOVLW	GET_INTERFACE
		SUBWF	SETUPREQ,W
		BTFSS	STATUS,Z
		GOTO	LAB1058
		MOVF	SETUPIND_H,W
		BTFSS	STATUS,Z
		GOTO	LAB1056
		MOVF	SETUPIND_L,W
		BTFSS	STATUS,Z
		GOTO	LAB1056
		MOVLW	D11_EPT_EP0_IN
		MOVWF	D11_CDE
		MOVLW	1
		MOVWF	PARA3
		MOVLW	TAMPON
		MOVWF	PARA4
		CLRF	TAMPON
		CALL	WRITETERM
		GOTO	$+.2
LAB1056		GOTO	ERRORREQ
		GOTO	FINREQ
LAB1058		GOTO	ERRORREQ
LAB1059		MOVLW	STD_ENDPT_REQ
		SUBWF	SETUPTYPE,W
		BTFSS	STATUS,Z
		GOTO	LAB1207
		MOVLW	CLEAR_FEATURE
		SUBWF	SETUPREQ,W
		BTFSS	STATUS,Z
		GOTO	$+.2
		GOTO	SETFEATURE
		MOVLW	SET_FEATURE
		SUBWF	SETUPREQ,W
		BTFSS	STATUS,Z
		GOTO	Lab1140
SETFEATURE	MOVF	SETUPVAL_H,W
		BTFSS	STATUS,Z
		GOTO	LAB1136
		MOVF	SETUPVAL_L,W
		BTFSS	STATUS,Z
		GOTO	LAB1136
		MOVLW	CLEAR_FEATURE
		SUBWF	SETUPREQ,W
		BTFSS	STATUS,Z
		GOTO	$+.3
		CLRF	TAMPON
		GOTO	$+.3
		MOVLW	1
		MOVWF	TAMPON
		MOVLW	D11_SET_EPT_ST
		MOVWF	D11_CDE
		MOVLW	1
		MOVWF	PARA1
		MOVLW	TAMPON
		MOVWF	PARA2
		MOVLW	1
		SUBWF	SETUPIND_L,W
		BTFSS	STATUS,Z
		GOTO	$+.4
		MOVLW	D11_EPT_EP1_OUT
		ADDWF	D11_CDE,F
		GOTO	GOD11WRITE
		MOVLW	H'81'
		SUBWF	SETUPIND_L,W
		BTFSS	STATUS,Z
		GOTO	$+.4
		MOVLW	D11_EPT_EP1_IN
		ADDWF	D11_CDE,F
		GOTO	GOD11WRITE
		MOVLW	H'02'
		SUBWF	SETUPIND_L,W
		BTFSS	STATUS,Z
		GOTO	$+.4
		MOVLW	D11_EPT_EP2_OUT
		ADDWF	D11_CDE,F
		GOTO	GOD11WRITE
		MOVLW	H'82'
		SUBWF	SETUPIND_L,W
		BTFSS	STATUS,Z
		GOTO	$+.4
		MOVLW	D11_EPT_EP2_IN
		ADDWF	D11_CDE,F
		GOTO	GOD11WRITE
		MOVLW	H'03'
		SUBWF	SETUPIND_L,W
		BTFSS	STATUS,Z
		GOTO	$+.4
		MOVLW	D11_EPT_EP3_OUT
		ADDWF	D11_CDE,F
		GOTO	GOD11WRITE
		MOVLW	H'83'
		SUBWF	SETUPIND_L,W
		BTFSS	STATUS,Z
		GOTO	$+.4
		MOVLW	D11_EPT_EP3_IN
		ADDWF	D11_CDE,F
		GOTO	GOD11WRITE
		GOTO	ERRORREQ
		GOTO	$+.2
LAB1136		GOTO	ERRORREQ
		GOTO	FINREQ
GOD11WRITE	CALL	D11WRITE
		GOTO	FINREQ
LAB1140		MOVF	SETUPREQ,W
; GET_STATUS = 0
		BTFSS	STATUS,Z
		GOTO	LAB1206
		MOVLW	D11_READ_EPT_ST
		MOVWF	D11_CDE
		MOVLW	1
		MOVWF	PARA1
		MOVLW	TAMPON
		MOVWF	PARA2
		MOVLW	1
		SUBWF	SETUPIND_L,W
		BTFSS	STATUS,Z
		GOTO	$+.4
		MOVLW	D11_EPT_EP1_OUT
		ADDWF	D11_CDE,F
		GOTO	GOWRITETERM
		MOVLW	H'81'
		SUBWF	SETUPIND_L,W
		BTFSS	STATUS,Z
		GOTO	$+.4
		MOVLW	D11_EPT_EP1_IN
		ADDWF	D11_CDE,F
		GOTO	GOWRITETERM
		MOVLW	H'02'
		SUBWF	SETUPIND_L,W
		BTFSS	STATUS,Z
		GOTO	$+.4
		MOVLW	D11_EPT_EP2_OUT
		ADDWF	D11_CDE,F
		GOTO	GOWRITETERM
		MOVLW	H'82'
		SUBWF	SETUPIND_L,W
		BTFSS	STATUS,Z
		GOTO	$+.4
		MOVLW	D11_EPT_EP2_IN
		ADDWF	D11_CDE,F
		GOTO	GOWRITETERM
		MOVLW	H'03'
		SUBWF	SETUPIND_L,W
		BTFSS	STATUS,Z
		GOTO	$+.4
		MOVLW	D11_EPT_EP3_OUT
		ADDWF	D11_CDE,F
		GOTO	GOWRITETERM
		MOVLW	H'83'
		SUBWF	SETUPIND_L,W
		BTFSS	STATUS,Z
		GOTO	$+.4
		MOVLW	D11_EPT_EP3_IN
		ADDWF	D11_CDE,F
		GOTO	GOWRITETERM
		GOTO	ERRORREQ
GOWRITETERM	BTFSS	TAMPON,3
		GOTO	$+.4
		MOVLW	1
		MOVWF	TAMPON
		GOTO	$+.2
		CLRF	TAMPON
		CLRF	TAMPON + 1
		MOVLW	D11_EPT_EP0_IN
		MOVWF	D11_CDE
		MOVLW	2
		MOVWF	PARA1
		CALL	WRITETERM
		GOTO	FINREQ
LAB1206		GOTO	ERRORREQ
LAB1207		MOVLW	VEND_DEVICE_REQ
		SUBWF	SETUPTYPE,W
		BTFSS	STATUS,Z
		GOTO	$+.2
		GOTO	ENDPT_REQ
		MOVLW	VEND_ENDPT_REQ
		SUBWF	SETUPTYPE,W
		BTFSS	STATUS,Z
		GOTO	LAB1273
ENDPT_REQ	MOVLW	VEND_GET_VAL
		SUBWF	SETUPREQ,W
		BTFSS	STATUS,Z
		GOTO	LAB1254
		MOVF	SETUPIND_L,W
		MOVWF	TEMPO1
		MOVLW	7
		ANDWF	TEMPO1,F
		RLF		TEMPO1,W
		RLF		TEMPO1,F
		RLF		TEMPO1,W
		RLF		TEMPO1,F
		RLF		TEMPO1,W
		RLF		TEMPO1,F
		MOVLW	H'C1'
		IORWF	TEMPO1,F
		MOVF	TEMPO1,W
		MOVWF	ADCON0
		MOVLW	H'FF'
		MOVWF	TEMPO1
DELAY		DECFSZ	TEMPO1,F
		GOTO	DELAY
		BSF		ADCON0,2
		BTFSC	ADCON0,2
		GOTO	$-.1
		BCF     STATUS,RP1
		BSF     STATUS,RP0
		MOVF	ADRESL,W
		BCF     STATUS,RP1
		BCF     STATUS,RP0
		MOVWF	TAMPON
		MOVF	ADRESH,W
		MOVWF	TAMPON + 1
		MOVLW	D11_EPT_EP0_IN
		MOVWF	D11_CDE
		MOVLW	2
		MOVWF	PARA3
		MOVLW	TAMPON
		MOVWF	PARA4
		CALL	WRITETERM
		GOTO	FINREQ
LAB1254		MOVLW	VEND_SET_NIB
		SUBWF	SETUPREQ,W
		BTFSS	STATUS,Z
		GOTO	LAB1271
		MOVF	PORTB,W
		MOVWF	TEMPO1
		MOVLW	7
		ANDWF	TEMPO1,F
		MOVF	SETUPIND_L,W
		IORWF	TEMPO1,F
		MOVF	TEMPO1,W
		MOVWF	PORTB
		MOVLW	D11_EPT_EP0_IN
		MOVWF	D11_CDE
		CLRF	PARA3
		CALL	WRITETERM
		GOTO	FINREQ
LAB1271		GOTO	ERRORREQ
; type de requête inconnu
LAB1273		GOTO	ERRORREQ
		GOTO	$+.2
; paquet de datas - non supporté
LAB1276		NOP
ERRORREQ	CALL	STALLTERM
FINREQ		RETURN
; 
; DESCRIPTEURS
; descripteur d'appareil
DEVDES		RETLW	H'12'
		RETLW	TYPE_DEV_DES
		RETLW	H'10'
		RETLW	1
		RETLW	0
		RETLW	0
		RETLW	0
		RETLW	H'08'
; VID (octets inversés)
		RETLW	H'33'
		RETLW	H'33'
; PID (octets inversés)
		RETLW	H'01'
		RETLW	H'00'
		RETLW	0
		RETLW	0
		RETLW	1
		RETLW	0
		RETLW	0
		RETLW	1
; 
; descripteur de configuration
CONFDES		RETLW	H'09'
		RETLW	TYPE_CONF_DES
		RETLW	H'20'
		RETLW	0
		RETLW	1
		RETLW	1
		RETLW	0
		RETLW	H'80'
		RETLW	H'32'
; 
; descripteur d'interface
INTDES		RETLW	H'09'
		RETLW	TYPE_INT_DES
		RETLW	0
		RETLW	0
		RETLW	H'02'
		RETLW	H'FF'
		RETLW	H'FF'
		RETLW	H'FF'
		RETLW	0
; 
; descripteur terminaison EP1 OUT
OUTDES		RETLW	H'07'
		RETLW	TYPE_EPT_DES
		RETLW	1
		RETLW	H'02'
		RETLW	H'08'
		RETLW	0
		RETLW	0
; 
; descripteur terminaison EP1 IN
INDES		RETLW	H'07'
		RETLW	TYPE_EPT_DES
		RETLW	H'81'
		RETLW	H'02'
		RETLW	H'08'
		RETLW	0
		RETLW	0
; 
; descripteur fabricant --> Zebu
VENDDES		RETLW	H'0A'
		RETLW	TYPE_STR_DES
		RETLW	H'5A'
		RETLW	0
		RETLW	H'65'
		RETLW	0
		RETLW	H'62'
		RETLW	0
		RETLW	H'75'
		RETLW	0
; 
; descripteur de langues
LANGDES		RETLW	H'04'
		RETLW	TYPE_STR_DES
		RETLW	H'09'
		RETLW	H'04'
		END
