Appendice A
Di seguito sono riportati il firmware del microcontrollore e il software per l’interfaccia
utente in VisualC++.
A.1 Firmware del microcontrollore
;*********************************************************** ;Scheda per acquisizione Cappuccio
;*********************************************************** LIST P=16F877 include <p16f877.inc> radix dec ; errorlevel -302 ; errorlevel -306
__CONFIG _PWRTE_ON & _WDT_ON & _XT_OSC & _BODEN_ON & _CP_OFF
; DICHIARAZIONE DELLE VARIABILI UTILIZZATE
;Variabili del banco 0
cblock 0x21 ms1 ms2 ms3 passapotenz dato aux cont mem j convH convL offset acquisito servizio appoggio stato_tast taboff
satur endc
;Variabili del banco 1
cblock 0xAA ricevuto H_ResConv0 L_ResConv0 H_ResConv1 L_ResConv1 H_ResConv2 L_ResConv2 H_ResConv3 L_ResConv3 H_ResConv4 L_ResConv4 H_ResConv5 L_ResConv5 H_ResConv6 L_ResConv6 H_ResConv7 L_ResConv7 endc
;Variabili del banco 2
cblock 0x0121
endc
;Variabili del banco 3
cblock 0x01A1 USB_data byte_to_read byte_to_write descrittore EP step_descrittore lunghezza_descrittore appoggio_USB prova prova_IN prova_set
prova_stallo device_configured header puntatore puntatore_EP1 prova_EP prova_prova prova_errore indirizzo_partenza_L indirizzo_partenza_H ADDRESS byte_to_write_EP1 appoggio_EP mul_USB messaggio FLAG_USB byte_mandati tentativi FLAG_START prova_EP0 ;SET UP PACKET buffer_USB0 buffer_USB1 buffer_USB2 buffer_USB3 buffer_USB4 buffer_USB5 buffer_USB6 buffer_USB7 endc ;Definizione #define L1 PORTB,6 #define L2 PORTB,5 #define L3 PORTB,4 #define J1 PORTB,3 #define SDI_R PORTD,0
#define SDI_G PORTC,3
#define CLK PORTA,3 #define CS_R PORTC,0
#define CS_G PORTA,1
#define Tg PORTC,1
#define Tr PORTC,2 #define INDIRIZZO PORTE
;Costanti A0 equ 7 WR_N equ 7 RD_N equ 6 ;***************************************************** ; MACRO ;***************************************************** banco0 MACRO bcf STATUS,RP0 bcf STATUS,RP1 ENDM banco1 MACRO bcf STATUS,RP1 bsf STATUS,RP0 ENDM banco2 MACRO bsf STATUS,RP1 bcf STATUS,RP0 ENDM banco3 MACRO bsf STATUS,RP1 bsf STATUS,RP0 ENDM usb_out MACRO banco1 movlw b'00000110' movwf TRISC movlw b'00000000' movwf TRISD banco0 ENDM usb_in MACRO banco1 movlw b'00110110' movwf TRISC movlw b'11111100' movwf TRISD banco0 ENDM ;---
; Le macro ROM_PAGE servono nel caso in cui il programma sia troppo grande per essere memorizzato in una sola page della memoria di programma (vedi). Se interagiscono porzioni di programma in pages diverse si deve stare attenti a cambiare page, analogamente a quanto avviene con i banchi dei registri
ROM_PAGE0 MACRO bcf PCLATH,4 bcf PCLATH,3 ENDM ROM_PAGE1 MACRO bcf PCLATH,4 bsf PCLATH,3 ENDM ROM_PAGE2 MACRO bsf PCLATH,4 bcf PCLATH,3 ENDM ROM_PAGE3 MACRO bsf PCLATH,4 bsf PCLATH,3 ENDM ;---
potenziometroR MACRO ;abilita il potenziometro Ref banco0
bcf CS_R ;RC0 prende 0, CS_=0 ENDM
potenziometroG MACRO ;abilita il potenziometro del Guadagno banco0 bcf CS_G ;RA1 prende 0, CS_=0 ENDM org 0 ; ROM_PAGE0 goto start ;*********************************************** ;*********************************************** ;*********************************************** ;--- ; INTERRUPT ;---
org 4 retfie ;****************************************************************************************** ***************************************** ; SUBROUTINE ;****************************************************************************************** ***************************************** ;---
;ROUTINE DI RITARDO BREVE: passo da fuori ms1 tramite w ;---
;il ritardo é (3*ms3)*ms2 + (7*ms2)*ms1 + 12*ms1 + 2 (cicli da 200nsec). Con ms2=2 ms3=2 ms1=1 il ritardo è 8usec msecB clrwdt movwf ms1 msecB0 movlw 2 ;fattore 2 movwf ms2 msecB1 movlw 2 ;fattore 3 movwf ms3 msecB2 clrwdt decfsz ms3,F goto msecB2 decfsz ms2,F goto msecB1 decfsz ms1,F goto msecB0 return ;--- ;---
;ROUTINE DI RITARDO LUNGO: passo da fuori ms1 tramite w ;---
;il ritardo é (3*ms3)*ms2 + (7*ms2)*ms1 + 12*ms1 + 2 (cicli da 200nsec). Con ms2=100 ms3=150 ms1=1 il ritardo è 9msec (12msec almeno per me)
msec clrwdt movwf ms1 msec0 movlw 100 ;fattore 2 movwf ms2 msec1 movlw 150 ;fattore 3 movwf ms3 msec2
clrwdt decfsz ms3,F goto msec2 decfsz ms2,F goto msec1 decfsz ms1,F goto msec0 return ;--- ;---
;CONTROLLA SE IL TASTO GIALLO è STATO PREMUTO: mi mette w=0 se non è premuto o w=1 ;se invece è stato premuto
;--- tasto_giallo
waitg btfsc Tg
goto zer
movlw 2 ;attendo 20msec call msec ;chiamando msec btfss Tg
retlw .1 goto waitg
zer movlw 2 ;attendo 20msec call msec ;chiamando msec
btfsc Tg retlw .0
goto waitg
;--- ;---
;CONTROLLA SE IL TASTO ROSSO è STATO PREMUTO: mi mette w=0 se non è premuto o w=1 ;se invece è stato premuto
;--- tasto_rosso
waitr btfsc Tr
goto zer1
movlw 2 ;attendo 20msec call msec ;chiamando msec btfss Tr
retlw .1 goto waitr
zer1 movlw 2 ;attendo 20msec call msec ;chiamando msec
btfsc Tr retlw .0
goto waitr
;--- ;---
;ACQUISIZIONE: restituisce il risultato della conversione in convL e convH
;--- acquisizione
banco0 clrwdt
movlw 3 ;aspetto che la capacità di camp. del A/D sia carica (nella sub msecB attendo 20usec circa (10usec circa per me)
call msecB
bsf ADCON0,2
acq btfsc ADCON0,2 ;verifico se la conversione è finita
goto acq movf ADRESH,0 movwf convH banco1 movf ADRESL,0 banco0 movwf convL
bcf PIR1,ADIF ;vedi datasheet cap. 11
return ;ho l'acquisizione in convH (ADRESH) e convL (ADRESL)
;--- ;---
;settapotenz IMPOSTA POTENZIOMENTRO deve essere passato dall'esterno la variabile 'passapotenz' in w prima di chiamare
; settapotenz che imposta
il pot. secondo le formule da vedere sul datasheet
;--- settapotenz
;si potrebbe mettere sdi_R=SDI_G=SDI!!!!!!!!!!!!!!!!! banco0
clrwdt
;trasmetto i due bit A0 e A1 per io pot. movwf passapotenz
movlw 8
movwf cont
bcf SDI_R ;RD0 prede 0, A1=0 bcf SDI_G
bsf CLK ;CLK di Pot Ref a 1 bcf CLK ;CLK di Pot Ref a 0 bcf SDI_R ;A0=0
bsf CLK ;CLK di Pot Ref a 1 bcf CLK ;CLK di Pot Ref a 0
;trasmetto i bit di codice D7_D0 per il pot. rruota rlf passapotenz btfsc STATUS,C goto ruota1 bcf SDI_R bcf SDI_G goto ruota0 ruota1 bsf SDI_R bsf SDI_G ruota0 bsf CLK ;CLK di Pot Ref a 1 bcf CLK ;CLK di Pot Ref a 0 decfsz cont goto rruota ;disabilito i potenziomentri bsf CS_R bsf CS_G return ;--- ;--- ;regola_ref SCELTA DEI VALORI DI RIFERIMENTO PER ANNULLARE L'OFFSET ;---
;Funziona insieme ad 'Alloca'. Si deve completare il ciclo di regolazione inizializzando 'mem' nel main, una
;sola volta per ciclo di regolazione dei canali previsti, inserendogli il valore della locazione da dove si ;intende iniziare ad allocare. Poi, sempre nel main, si cambia canale e si richiama 'regola_ref', senza ;reinizializzare 'mem'. Vedi note in 'Alloca'
regola_ref
clrwdt
banco1
bcf ADCON1,7 ;il risultato della conversione è giustificato a sx, i bit più significativi sono in ADRESH
banco0
call acquisizione ;ho il risultato in convL (ADRESL) e convH (ADRESH)
; banco2 ;non ci vuole perchè indirizzamento indiretto
bsf STATUS,7 ;metto IRP a 1 per indirizzamento indiretto nel banco 2
movlw 0x0F ;inizializzo il registro del puntatore con il registro immediatamente precendente al primo
;valore della tabella di comparazione degli offset di tensione. La tabella per il confronto
;è nel banco 2 movwf FSR banco0 movlw .63 movwf satur confronta clrwdt decf satur btfsc STATUS,Z goto sat
incf FSR,F ;incremento il puntatore a step(n+1) movf convH,W
subwf INDF,0 ;sottraggo(risultato in w) offset-step(n) della tabella degli offset generata all'avvio
btfss STATUS,C ;se C=1 vuol dire che offset>step(n) e mi fermo, altrimenti carico uno step maggiore e
;confronto di nuovo goto confronta
movf INDF,W
movwf dato ;ho il valore da mettere nel potenziometro per regolare l'offset che per ora metterò
;in una tabella nel banco3 con alloca.
call alloca
banco1
bsf ADCON1,7 ;imposto nuovamente il risultato della conversione giustificato a dx, i bit più significativi
;sono in ADRESL banco0
return
sat movlw .128 ;condizione di offset troppo alto (più di 2,5V)
movwf dato call alloca banco1
bsf ADCON1,7 ;imposto nuovamente il risultato della conversione giustificato a dx, i bit più significativi
banco0 return ;--- ;--- ;alloca ;--- ;Si deve inizializzare 'mem' dall'esterno per stabilire dove inizia ad allocare, e poi si richiama il numero di volte voluto,
;ma senza reinizializzare 'mem'. Per utilizzare 'ALLOCA' correttamente è necessario inizializzare la variabile 'mem' con
;l'indirizzo del registro da cui si intende iniziare a memorizzare. L'inizializzazione di 'mem' attualmente è in 'Start'
;per l'allocazione degli offset di tensione Bisogna caricare dall'esterno la variabile 'dato', che sarà usata per
;l'allocazione alloca alloca
banco0 clrwdt
bcf STATUS,7 ;metto IRP a 0 per indirizzamento indiretto nel banco 1
movf mem,W ;punto alla tabella degli offset da memorizzare movwf FSR
movf dato,W ;memorizzo l'offset di tensione attuale movwf INDF
incf mem ;incremento per puntare alla locazione successiva dove memorizzare l'offset di tensione successivo
return ;--- ;--- ;allocaacq ;--- allocaacq banco0 clrwdt
bcf STATUS,7 ;metto IRP a 1 per indirizzamento indiretto nel banco 1
movf mem,W ;punto alla tabella degli offset da memorizzare movwf FSR
movf dato,W ;memorizzo l'offset di tensione attuale movwf INDF
incf mem ;incremento per puntare alla locazione successiva dove memorizzare l'offset di tensione successivo
return
;--- ;--- ;run acquisito tutti e 8 i canali e le acquisizioni le ho messe nella tabella nel banco 3
;pronte per essere mandate al PC tramite usb
;da qua inizio a fare un'aquisizione sugli otto canali e mettere i risultati nella tabella al banco1 dopo la tabella degli offset
run clrf INDIRIZZO
movlw 0xAB ;carico la locazione (banco 1) da cui iniziare a memorizzare le acquisizioni
movwf mem
movlw .8 ;numero di canali usati movwf cont
bcf STATUS,7 ;metto IRP a 0 per indirizzamento indiretto nel banco 1 (devo prendere gli offset)
movlw 0x9F ;carico la locazione dove sono stati precedentemente memorizzati gli offset (banco1)
movwf taboff ;da qua imposto l'offset e acquisisco il dato
run1 bcf STATUS,7 ;metto IRP a 0 per indirizzamento indiretto nel banco 1 per gli offset memorizzati
incf taboff movf taboff,0
movwf FSR
potenziometroR ;impostazione del potenziomentro da regolare movf INDF,W ;passo il valore da mettere nel potenziometro call settapotenz ;richiamo la sub di impostazione del potenziometro
;se sono qua ho settato il potenziometro con il valore corretto e posso fare l'acquisizione call acquisizione ;ho la tensione acquisita in convL e convH
movf convH,W ;alloco l'acquisizione dei bit più significativi movwf dato
call allocaacq
movf convL,W ;alloco l'acquisizione dei bit meno significativi movwf dato
call allocaacq
incf INDIRIZZO ;incremento l'indirizzo dei mux decfsz cont
goto run1
;quando sono qua ho acquisito tutti e 8 i canali e le acquisizioni le ho messe nella tabella nel ;banco 3 pronte per essere mandate al PC tramite usb
clrf INDIRIZZO return ;--- ;****************************************************************************************** ********************************** ;****************************************************************************************** **********************************
;--- ; START ;--- start clrwdt ; banco0
; movlw 56 ;Inizializza il timer in tempo reale
; movwf RTCC banco0
movlw b'10000001' ;Scelgo il tempo di conversione movwf ADCON0 ;La porta da convertire RA0
banco1
movlw b'10001110' ;RA0 come porta analogica movwf ADCON1 ;bit 1 e 0 di ADRESH sono MSB, gli altri 8 della conversione a 10bit sono in ADRESL
banco0
movlw b'00000000' ;Disabilito il modulo comparatore/capture/PWM ?
movwf CCP1CON
movlw b'00000000' ;Disabilito il modulo comparatore/capture/PWM ?
movwf CCP2CON banco1
movlw b'11000111' ;setto il timer0 con prescaler 1:256 movwf OPTION_REG movlw b'00000001' movwf TRISA movlw b'00001001' movwf TRISB movlw b'00000110' movwf TRISC movlw b'00000000' movwf TRISD movlw b'00000000'
movwf TRISE clrwdt banco0 clrf PORTA clrf PORTB clrf PORTC clrf PORTD clrf PORTE bsf CS_R ;disabilito i potenziometri bsf CS_G
;genero la tabella di comparazione della tensione di riferimento
bsf STATUS,7 ;metto IRP a 1 per indirizzamento indiretto nel banco 2
movlw 0x10 ;inizializzo il puntatore al secondo registro utile del banco2
movwf FSR
movlw 0 ;inizializzo il contatore
movwf j
genera btfsc j,7 ;in pratica la tabella sarà terminata quando j arriva a 127
goto generata
movf j,W
movwf INDF
incf j ;incremento di 2 per passo (dal valore 0 a 127 in 63 passi)
incf j incf FSR,F goto genera generata nop
;inizializzo la locazione (nel banco 1) dove memorizzare i valori ottenuti dal confronto con gli offset di tensione dei vari
;canali e la tabella di confronto generata (vedi sopra) e allocata nel banco 2 banco0
movlw 0xA0
movwf mem ;in mem ho questa informazione ;INIZIALIZZAZIONE DEI REGISTRI E DEI FLAG
;--- ; INIZIO PROGRAMMA PRINCIPALE
;--- main
;TEST LED E TASTI--- banco0
bsf L1 bcf L2 bcf L3 red call tasto_rosso movwf stato_tast btfss stato_tast,0 goto red
bsf L2 jell call tasto_giallo
movwf stato_tast btfss stato_tast,0 goto jell
bsf L3 red1 call tasto_rosso
movwf stato_tast btfss stato_tast,0 goto red1 bcf L1 bcf L2 bcf L3 ;---
potenziometroG ;imposto il potenziometro del guadagno per avere guadagno 2
movlw 255 call settapotenz
;--- ;ACQUISIZIONE E CONFRONTO PER RIDURRE GLI OFFSET DI TENSIONE DEI SENSORI
movlw .8 ;numero di canali usati (max 79 perchè si lavora con i registri che sono limitati, in perticolare
;gli offset di tensione sono memorizzati nel banco 1 dal registro 0xA1 fino, eventualmente, al
;registro 0xEF) movwf cont
regola call regola_ref ;avvio la sub di regolazione
incf INDIRIZZO,F ;cambio il canale dei mux decfsz cont
goto regola
clrf INDIRIZZO ;imposto il canale 0 nei mux ;se sono qua ho la tabella con gli offset dei vari canali, che userò per ogni acquisizione, nel banco1
;---
ROM_PAGE3
goto prova_USB ;in pratica vado in ascolto sull'usb aspettando un comando
;--- ; Banco di ROM 3 ;--- UUSSBB org 0x1800 tabella_enumerazione clrwdt movf descrittore,W addwf PCL,F
;Da descrittore da 0 DEVICE DESCRIPTOR
retlw 18 ;lunghezza descrittore retlw 0x01 ;Tipo descrittore
retlw 0x10 ;Specifica USB L retlw 0x01 ;Specifica USB H retlw 0 ;B device class retlw 0 ;B device subclass retlw 0 ;B device protocol
retlw 8 ;Dimensione massima del pacchetto EP0 retlw 0x10 ;VID L retlw 0x02 ;VID H retlw 0x20 ;PID L retlw 0x02 ;PID H retlw 0x42 ;VER L retlw 0 ;VER H
retlw 1 ;Manufactured string ID retlw 2 ;Product ID
retlw 0 ;Serial number retlw 1 ;Number configuration ;Da descrittore da 18 REPORT DESCRIPTOR
retlw 0x06 retlw 0x00 retlw 0xff retlw 0x09 retlw 0x01 retlw 0xa1 retlw 0x01 retlw 0x19 retlw 0x01 ; USAGE_MINIMUM(1) retlw 0x29 retlw 0x08 ; USAGE_MAXIMUM(8)
retlw 0x15 retlw 0x00 ; LOGICAL_MINIMUM(0) retlw 0x26 retlw 0xff retlw 0x00 ; LOGICAL_MAXIMUM(255) retlw 0x95 retlw 42 ;INPUT_REPORT_SIZE, REPORT_COUNT(INFO_SIZE*INFO_PER_REPORT) retlw 0x75 retlw 0x08 ; REPORT_SIZE(8) retlw 0x81 retlw 0x02 ; INPUT(Data,Var,Abs) retlw 0x19 retlw 0x01 ; USAGE_MINIMUM(1) retlw 0x29 retlw 0x08 ; USAGE_MAXIMUM(8) retlw 0x15 retlw 0x00 ; LOGICAL_MINIMUM(0) retlw 0x26 retlw 0xff retlw 0x00 ; LOGICAL_MAXIMUM(255) retlw 0x95 retlw 5 ;OUTPUT_REPORT_SIZE, REPORT_COUNT(5) retlw 0x75 retlw 0x08 ; REPORT_SIZE(8) retlw 0x91 retlw 0x02 ; OUTPUT(Const,Var,Abs) retlw 0xc0
;Descrittore da 56 USB_CONFIG_DATA (è un insieme di descrittori, vedi .c e .h) ; configuration descriptor retlw 9 ; bLength retlw 2 ; bDescriptorType retlw 41 ; wtotallength
retlw 0 ; wtotallenght DA METTERE GIUSTO
retlw 1 ; bNumInterfaces retlw 1 ; bConfigurationValue retlw 0 ; iConfiguration String Index
retlw 0x80 ; bmAttributes Bus Powered, No Remote Wakeup retlw 0x32 ; bMaxPower, 100mA
; interface descriptor
retlw 9 ; bLength
retlw 0 ; bInterface Number retlw 0 ; bAlternateSetting retlw 2 ; bNumEndpoints
retlw 0x03 ; bInterfaceClass (Vendor specific) retlw 0x00 ; bInterfaceSubClass
retlw 0x00 ; bInterfaceProtocol retlw 0 ; iInterface String Index ; hid descriptor retlw 9 ; bLength retlw 0x21 ; bDescriptorType retlw 0x00 ; wHIDClassSpecCompL retlw 0x01 ; wHIDClassSpecCompH retlw 0x00 ; bCountry retlw 0x01 ; bNumDescriptors retlw 0x22 ; b1stDescType retlw 38 ; w1stDescLengthL retlw 0 ; w1stDescLengthH ; endpoint descriptor retlw 7 ; bLength retlw 5 ; bDescriptorType
retlw 0x81 ; bEndpoint Address EP1 OUT, vedi STANDARD_ENDPOINT_REQUEST
retlw 0x03 ; bmAttributes - Interrupt
retlw 8 ; wMaxPacketSizeL retlw 0 ; wMaxPacketSizeH retlw 0x80 ; b interval ; endpoint descriptor retlw 7 ; bLength retlw 5 ; bDescriptorType
retlw 0x01 ; bEndpoint Address EP1 IN, vedi STANDARD_ENDPOINT_REQUEST
retlw 0x03 ; bmAttributes - Interrupt
retlw 8 ; wMaxPacketSizeL retlw 0 ; wMaxPacketSizeH retlw 0x80 ; b interval ;Descrittore 97 LANGID_DESCRIPTOR retlw 4 ; bLength retlw 3 ; bDescriptorType retlw 0x09
retlw 0x04 ; LANGID US English
;Descrittore 101 MANUFACTURER_DESCRIPTOR
retlw 8 ; bLenght DA METTERE GIUSTO retlw 0x03 ; bDescriptorType
retlw 'E' ; ManufacturerString in UNICODE retlw 0 retlw 'B' retlw 0 retlw 'B' retlw 0 ;Descrittore 109 PRODUCT_DESCRIPTOR retlw 20 ; bLengh DA METTERE GIUSTO retlw 0x03 ; bDescriptorType
retlw 'T' ; ManufacturerString in UNICODE retlw 0 retlw 'e' retlw 0 retlw 'l' retlw 0 retlw 'e' retlw 0 retlw 'v' retlw 0 retlw 'o' retlw 0 retlw 't' retlw 0 retlw 'e' retlw 0 retlw 'r' retlw 0 ;****************************************************************************************** *************************************
;PROCEDURE PER USB
;****************************************************************************************** *************************************
;--- ;delta_USB RITARDO USB (vista)
;--- delta_USB
banco0
movwf appoggio goto loop_delta_USB delta_USB_write banco0 movlw 100 movwf appoggio loop_delta_USB clrwdt decfsz appoggio,F goto loop_delta_USB return ;---
;leggi_pdi Routine che legge dalle porte di I/O del pdi e mette quello letto in W (vista) ;--- leggi_pdi banco0 btfsc PORTD,7 goto oone goto ozero oone bsf servizio,0 goto ogo ozero bcf servizio,0 goto ogo ogo btfsc PORTD,6 goto oone1 goto ozero1 oone1 bsf servizio,1 goto ogo1 ozero1 bcf servizio,1 goto ogo1 ogo1 btfsc PORTD,5 goto oone2 goto ozero2 oone2 bsf servizio,2 goto ogo2 ozero2 bcf servizio,2 goto ogo2 ogo2 btfsc PORTD,4 goto oone3 goto ozero3 oone3 bsf servizio,3 goto ogo3 ozero3 bcf servizio,3
goto ogo3 ogo3 btfsc PORTC,5 goto oone4 goto ozero4 oone4 bsf servizio,4 goto ogo4 ozero4 bcf servizio,4 goto ogo4 ogo4 btfsc PORTC,4 goto oone5 goto ozero5 oone5 bsf servizio,5 goto ogo5 ozero5 bcf servizio,5 goto ogo5 ogo5 btfsc PORTC,3 goto oone6 goto ozero6 oone6 bsf servizio,6 goto ogo6 ozero6 bcf servizio,6 goto ogo6 ogo6 btfsc PORTC,2 goto oone7 goto ozero7 oone7 bsf servizio,7 goto ogo7 ozero7 bcf servizio,7 goto ogo7
ogo7 movf servizio,W return
;---
;scrivi_pdi ROUTINE PER METTERE CIO CHE C'E' IN W NELLE PORTE I/O DEL PDIUSBD12 (vista) ;--- scrivi_pdi banco0 movwf servizio btfsc servizio,0 goto one goto zero one bsf PORTD,7 goto go zero bcf PORTD,7 goto go go
btfsc servizio,1 goto one1 goto zero1 one1 bsf PORTD,6 goto go1 zero1 bcf PORTD,6 goto go1 go1 btfsc servizio,2 goto one2 goto zero2 one2 bsf PORTD,5 goto go2 zero2 bcf PORTD,5 goto go2 go2 btfsc servizio,3 goto one3 goto zero3 one3 bsf PORTD,4 goto go3 zero3 bcf PORTD,4 goto go3 go3 btfsc servizio,4 goto one4 goto zero4 one4 bsf PORTC,5 goto go4 zero4 bcf PORTC,5 goto go4 go4 btfsc servizio,5 goto one5 goto zero5 one5 bsf PORTC,4 goto go5 zero5 bcf PORTC,4 goto go5 go5 btfsc servizio,6 goto one6 goto zero6 one6 bsf PORTC,3 goto go6 zero6 bcf PORTC,3 goto go6 go6 btfsc servizio,7 goto one7
goto zero7 one7 bsf PORTC,2 goto go7 zero7 bcf PORTC,2 goto go7 go7 return ;---
;USB_INIT ROUTINE DI INIZIALIZZAZIONE DEL PDIUSBD12 (vista) ;---
USB_INIT
clrwdt ;Set Address/Enable
bsf PORTC,A0 ;devo mandare un comando al PDI movlw 0xD0 ;invio il comando di set address
call WRITE_USB
bcf PORTC,A0 ;devo mandare il settaggio quindi A0 a 0 movlw b'10000000' ;invio byte di settaggio
call WRITE_USB
;set endpoints enables
bsf PORTC,A0
movlw 0xD8 ;invio il comando di set endpoints enables call WRITE_USB
bcf PORTC,A0
movlw b'00000001' ;invio byte di settaggio call WRITE_USB
;Set DMA off
bsf PORTC,A0 movlw 0xFB call WRITE_USB bcf PORTC,A0 movlw b'00000000' call WRITE_USB
bsf PORTC,A0 movlw 0xF3 call WRITE_USB bcf PORTC,A0 movlw b'00010110' call WRITE_USB movlw b'11000011' call WRITE_USB banco3 clrf step_descrittore clrf descrittore clrf puntatore_EP1 clrf ADDRESS banco0 return ;--- ;READ_USB ROUTINE DI LETTURA DAL PDIUSBD12 (vista) ;--- READ_USB clrwdt usb_in nop nop bcf PORTC,RD_N nop nop
call leggi_pdi ;per leggere quello che mi arriva dal pdi che poi lascio in W
nop nop banco3
movwf USB_data ;ho i dati letti in USB_data banco0
nop
bsf PORTC,RD_N return
;---
;WRITE_USB ROUTINE DI SCRITTURA SUL PDIUSBD12 preleva da W il dato da scrivere (vista) ;---
WRITE_USB
clrwdt
banco3
movwf USB_data ;ci metto ciò che ho passato tramite W
usb_out ;metto le porte I/O assegnate all'usb come uscita
nop nop nop nop
movf USB_data,W ;ho in W cio che devo scrivere nel PDI e lo devo mettere nelle porte di uscita assegnate a lui;
call scrivi_pdi ;lo faccio con una procedura nop nop bcf PORTB,WR_N nop nop nop bsf PORTB,WR_N nop usb_in return ;--- ;leggi_IRQ Routine di lettura del tipo di interruzione che è arrivato (vista) ;---
leggi_IRQ
clrwdt
bsf PORTC,A0 ;devo mandare un comando al PDI movlw 0xF4 ;codifica del comando 'read interruop register call WRITE_USB ;mando il comando
bcf PORTA,A0 ;devo ricevere il dato dal PDI call READ_USB
movf USB_data,W movwf buffer_USB0 banco0 call READ_USB banco3 movf USB_data,W movwf buffer_USB1 banco0 return ;--- ; ;--- WRITE_BUFFER_EP1 clrwdt banco3 ; incf prova_prova,F ; movlw 6 ; xorwf prova_prova,W ; btfsc STATUS,Z ; nop movlw 255 movwf tentativi riv_EP1 clrwdt decf tentativi,F btfsc STATUS,Z goto buffer_non_valido ;Se sono qui devo scrivere sull'EP1
banco0
bsf PORTC,A0
movlw 0x03 ;Seleziono l'EP1_IN call WRITE_USB
bcf PORTC,A0
banco3
btfsc USB_data,0 ;Verifico che il buffer sia vuoto
goto riv_EP1
movf byte_to_write_EP1,W btfsc STATUS,Z
goto scrivi_ancora
;Inizializzazione del puntatore
bcf STATUS,IRP ;per indirizzare banco1
movlw ricevuto ;c'era array movwf FSR bsf FSR,7 movf puntatore_EP1,W addwf FSR,F movlw 8 subwf byte_to_write_EP1,W btfss STATUS,C goto ultimi_byte ;Scrivo 8 byte banco0 bsf PORTC,A0 movlw 0xF0 call WRITE_USB bcf PORTC,A0 movlw 0 call WRITE_USB movlw 8 call WRITE_USB banco3 movlw 8 movwf appoggio_EP loop_send_8
clrwdt movf INDF,W call WRITE_USB banco3 incf FSR,F decfsz appoggio_EP,F goto loop_send_8 movlw 8 addwf puntatore_EP1,F subwf byte_to_write_EP1,F goto esci_write_EP1 ultimi_byte banco0 bsf PORTC,A0 movlw 0xF0 call WRITE_USB bcf PORTC,A0 movlw 0 call WRITE_USB banco3 movf byte_to_write_EP1,W banco0 call WRITE_USB banco3 loop_send_x clrwdt movf INDF,W call WRITE_USB banco3 incf FSR,F decfsz byte_to_write_EP1,F goto loop_send_x
clrf puntatore_EP1 esci_write_EP1 banco0 bsf PORTC,A0 movlw 0xFA call WRITE_USB ; banco3
;Verifico se i byte inviati sono la conferma del set new question
; btfss FLAG_USB,NEW_QUEST ; goto scrivi_ancora ; incf byte_mandati,F ; movlw 6 ; xorwf byte_mandati,W ; btfss STATUS,Z ; goto scrivi_ancora ; movlw 0x22 ; movwf messaggio scrivi_ancora banco0 return ;prepara_dati_USB ; clrwdt ;Deselezioniamo il PDI ; banco0 ; bsf PORTE,2 ; clrf indirizzo_H ; movlw 59 ; movwf indirizzo_L ; banco3 ; movlw 3 ; movwf mul_USB ;loop_mul_USB
; clrwdt ; banco3 ; movf buffer_USB1,W ; banco0 ; addwf indirizzo_L,F ; btfsc STATUS,C ; incf indirizzo_H,F ; banco3 ; movf buffer_USB2,W ; banco0 ; addwf indirizzo_H,F ; banco3 ; decfsz mul_USB,F ; goto loop_mul_USB
;In indirizzo_H, indirizzo_L abbiamo l'indirizzo di partenza da cui prelevare i dati in RAM
; bcf STATUS,IRP ; movlw array ; movwf FSR ; bsf FSR,7 ;loop_lettura_RAM ; banco0 ; clrwdt ; ROM_PAGE0 ; call leggi_RAM ; ROM_PAGE3 ; banco0 ; movf dato,W ; banco3 ; movwf INDF ; incf FSR,F ; banco0 ; incfsz indirizzo_L,F ; goto salta_sotto ; incf indirizzo_H,F ;salta_sotto ; banco3 ; decfsz buffer_USB3,F ; goto loop_lettura_RAM banco1 ; movlw b'11111111' ; movwf TRISD
; banco0
; bcf PORTE,2 ;riabilito il PDI ; ; return ;****************************************************************************************** ********************** ;enumerazione ;****************************************************************************************** ********************** enumerazione clrwdt
call leggi_IRQ ;si va a vedere che tipo di interruzione è arrivata
banco3
btfss buffer_USB0,6 ;Se questo bit è settato => è arrivato un comando di bus reset
goto no_bus_reset banco0
call USB_INIT ;reinizzializzo il PDIUSBD12 no_bus_reset
banco3
btfsc buffer_USB0,0 ;Verifico L'EP0OUT goto controlla_EP0_OUT
ritorno1
banco3
btfsc buffer_USB0,1 ;Verifico L'EP0_IN goto controlla_EP0_IN
ritorno2
banco3
btfsc buffer_USB0,2 ;Verifico L'EP1 OUT goto controlla_EP1_OUT
ritorno3
banco3
btfsc buffer_USB0,3 ;Verifico l'EP1_IN goto controlla_EP1_IN
ritorno4
return ;esco se non c'era nessun tipo di interrupt da parte
;dell'host ;--- controlla_EP1_IN clrwdt banco3 movlw 255
movwf tentativi ;numero massimo di tentativi in questo loop
rip2
decf tentativi,F btfsc STATUS,Z
goto buffer_non_valido ;pulisce il buffer banco0 bsf PORTC,A0 movlw 0x43 call WRITE_USB bcf PORTC,A0 call READ_USB banco3 btfss USB_data,0
goto rip2 ;esci_EP1_IN
call WRITE_BUFFER_EP1 clrwdt goto ritorno4 esci_EP1_IN clrwdt banco0 goto ritorno4 ;--- controlla_EP1_OUT clrwdt banco3 ; incf prova_EP,F ; movlw 2 ; xorwf prova_EP,W ; btfsc STATUS,Z
; nop movlw 255 movwf tentativi rip1 decf tentativi,F btfsc STATUS,Z
goto esci_EP1_OUT ;esce svuotando il buffer banco0 bsf PORTC,A0 movlw 0x42 call WRITE_USB bcf PORTC,A0 call READ_USB banco3
btfss USB_data,0 ;dati ricevuti correttamente si o no
; goto esci_EP1
goto rip1
;Processamento EP1_OUT
;I° Seleziono l'END POINT banco0 bsf PORTC,A0 movlw 0x02 call WRITE_USB bcf PORTC,A0 call READ_USB ;II° Verifico che il buffer del PDI sia pieno
banco3
btfss USB_data,0 goto esci_EP1 ;III° Leggo il buffer del PDI
banco0
bsf PORTC,A0 movlw 0xF0
call WRITE_USB bcf PORTC,A0
call READ_USB banco3 movf USB_data,W movwf buffer_USB0 banco0 call READ_USB banco3 movf USB_data,W movwf byte_to_read movlw 5 xorwf byte_to_read,W btfss STATUS,Z goto buffer_non_valido banco0 call leggi_buffer banco3 ;******* movlw 0x21 ;ACQUISISCI xorwf buffer_USB0,W btfsc STATUS,Z goto ACQUISISCI ;*******
buffer_non_valido ;Ho ricevuto sull'EP1 un numero di byte non corrispondente al nostro standard
banco0 ;Pulisco il buffer ed esco bsf PORTC,A0 movlw 0xF2 call WRITE_USB bcf PORTC,A0 return ;goto ritorno3 esci_EP1_OUT clrwdt goto ritorno3 ACQUISISCI clrwdt call run
;a questo punto ho le acquisizioni nel buffer cioè nel banco1 da AB banco1
movlw .202
movwf ricevuto ;carico il byte di corretta ricezione in AA del banco1 banco3 clrf puntatore_EP1 movlw 17 movwf byte_to_write_EP1 clrf byte_mandati clrwdt call WRITE_BUFFER_EP1 goto esci_EP1 esci_EP1 clrwdt goto ritorno3 ;--- controlla_EP0_IN clrwdt banco3 movlw 255 movwf tentativi riv0 decf tentativi,F btfsc STATUS,Z goto ritorno2 banco0 bsf PORTC,A0 movlw 0x41 call WRITE_USB bcf PORTC,A0 call READ_USB banco3 clrwdt btfss USB_data,0 goto riv0 ;Transizione OK
banco0
bsf PORTC,A0
movlw 0x01 ;Seleziono l'EP0_IN call WRITE_USB
bcf PORTC,A0
call READ_USB ;Non faccio il controllo di bus vuoto banco3
clrwdt
;indirizzo da cui parte il descrittore
movf lunghezza_descrittore,W ;indica quanti byte ho già inviato al PC
movwf appoggio_USB movf step_descrittore,W
subwf appoggio_USB,F ;verifico se sono arrivato alla fine btfss STATUS,C
goto errore_USB ;Teoricamente non deve succedere => ho trasmesso più byte del dovuto
movlw 8
subwf appoggio_USB,W btfss STATUS,C goto fine_EP0
;Arrivo qui se la lunghezza del descrittore è maggiore dello step_descrittore di almeno 8
movlw 8 movwf byte_to_write addwf step_descrittore,F call write_EP goto ritorno2 fine_EP0 movf appoggio_USB,W btfsc STATUS,Z goto ultimo_EP0 movwf byte_to_write movf lunghezza_descrittore,W movwf step_descrittore
call write_EP goto ritorno2 ultimo_EP0 clrf byte_to_write clrf descrittore clrf step_descrittore call write_EP goto ritorno2 ;--- controlla_EP0_OUT
;Arrivo qui se è arrivata una interruzione da EP0_OUT banco3 incf prova_EP0,F movlw 255 xorwf prova_EP0,W btfsc STATUS,Z nop banco0
;Verifico se l'ultima transazione è andata OK
bsf PORTC,A0 movlw 0x40 call WRITE_USB bcf PORTC,A0 call READ_USB banco3
btfss USB_data,0 ;Verifico se l'ultima transazione è andata OK
goto ritorno1 ;se non è andata bene controllo per l'EP0IN (cioè esco dall'EP0_OUT)
;Arrivo qui se l'ultima transizione è corretta
btfss USB_data,5 ;Verifico se è arrivato il packet setup goto stallo ;se non è un setup packet
;Devo prelevare il packet ;I° Seleziono l'ENDPOINT banco0 bsf PORTC,A0 movlw 0x00 call WRITE_USB bcf PORTC,A0 call READ_USB ;II° Verifico che il buffer del PDI sia pieno
banco3
btfss USB_data,0
goto ritorno1 ;nel caso non sia pieno esco dall'EP0OUT e vado a controllare per l'EP0IN
;III° Leggo il buffer del PDI banco0 bsf PORTC,A0 movlw 0xF0 call WRITE_USB bcf PORTC,A0 call READ_USB banco3 movf USB_data,W movwf buffer_USB0 banco0 call READ_USB banco3 movf USB_data,W
movwf byte_to_read ;ci sono scritti i byte da leggere dal buffer del PDI banco0
call leggi_buffer
;avrò in buffet_usb0,... il buffer che avevo da leggere
;Do il comando di ACK
bsf PORTC,A0 movlw 0xF1
call WRITE_USB ;Clear buffer movlw 0xF2 call WRITE_USB ;Seleziono l'EP0IN movlw 0x01 call WRITE_USB ;Do il comando di ACK
movlw 0xF1
call WRITE_USB ;Verifico il tipo di comando ricevuto
banco3 movlw b'01111111' andwf buffer_USB0,F btfsc STATUS,Z goto STANDARD_DEVICE_REQUEST movlw 0x01 xorwf buffer_USB0,W btfsc STATUS,Z goto STANDARD_INTERFACE_REQUEST movlw 0x02 xorwf buffer_USB0,W btfsc STATUS,Z goto STANDARD_ENDPOINT_REQUEST ; movlw 0x40 ; xorwf buffer_USB0,W ; btfsc STATUS,Z ; goto VENDOR_REQUEST ; movlw 0x42 ; xorwf buffer_USB0,W ; btfsc STATUS,Z ; goto VENDOR_REQUEST goto stallo
;--- ; DEVICE REQUEST ;--- STANDARD_DEVICE_REQUEST clrwdt
movlw 0x00 ;GET STATUS xorwf buffer_USB1,W
btfsc STATUS,Z
goto GET_STATUS_DEVICE
movlw 0x01 ;CLEAR FEATURE xorwf buffer_USB1,W
btfsc STATUS,Z goto stallo
movlw 0x03 ;SET FEATURE xorwf buffer_USB1,W
btfsc STATUS,Z goto stallo
movlw 0x05 ;SET ADDRESS xorwf buffer_USB1,W
btfsc STATUS,Z
goto SET_ADDRESS_DEVICE
movlw 0x06 ;GET DESCRIPTOR xorwf buffer_USB1,W btfsc STATUS,Z goto GET_DESCRIPTOR_DEVICE movlw 0x08 ;GET CONFIGURATION xorwf buffer_USB1,W btfsc STATUS,Z goto GET_CONFIGURATION_DEVICE movlw 0x09 ;SET CONFIGURATION xorwf buffer_USB1,W btfsc STATUS,Z goto SET_CONFIGURATION_DEVICE movlw 0x07 xorwf buffer_USB1,W btfsc STATUS,Z
goto stallo ;SET DESCRIPTOR_DEVICE
goto stallo
GET_STATUS_DEVICE ;Richiesta da parte dell'HOST se il dispositivo è autoalimentato e se supporta il remote wake_up
clrwdt ;Selezione L'EP0_IN banco0 bsf PORTA,A0 movlw 0x01 call WRITE_USB bcf PORTA,A0 call READ_USB
;Verifico se il buffer è vuoto banco0 bsf PORTA,A0 movlw 0xF0 call WRITE_USB bcf PORTA,A0 movlw 0 call WRITE_USB movlw 2 call WRITE_USB movlw 0x01 call WRITE_USB movlw 0x00 call WRITE_USB bsf PORTA,A0 movlw 0xFA call WRITE_USB goto ritorno1 SET_ADDRESS_DEVICE clrwdt banco0
;Imposto l'indirizzo che mi ha assegnato l'host
bsf PORTA,A0 movlw 0xD0
call WRITE_USB bcf PORTA,A0 banco3 bsf buffer_USB2,7 movf buffer_USB2,W movwf ADDRESS call WRITE_USB banco0 bsf PORTA,A0 movlw 0x41 call WRITE_USB bcf PORTA,A0 call READ_USB bsf PORTA,A0
movlw 0x01 ;EVENTUALE VERIFICA DELLA POSSIBILITA' DI SCRIVERE verifica del buffer vuoto
call WRITE_USB bcf PORTA,A0 call READ_USB bsf PORTA,A0 movlw 0xF0 call WRITE_USB bcf PORTA,A0 movlw 0 call WRITE_USB movlw 0 call WRITE_USB bsf PORTA,A0 movlw 0xFA call WRITE_USB bcf PORTA,A0 goto ritorno1 GET_DESCRIPTOR_DEVICE clrwdt banco3
;Devo verificare quale sottorischiesta mi è arrivata. movlw 0x01 xorwf buffer_USB3,W btfsc STATUS,Z goto device_descriptor movlw 0x02 xorwf buffer_USB3,W btfsc STATUS,Z goto configuaration_descriptor
movlw 0x03 xorwf buffer_USB3,W btfsc STATUS,Z goto string_descriptor goto stallo nop device_descriptor
;indirizzo da cui parte il descrittore banco3 clrf descrittore clrf step_descrittore movf buffer_USB6,W movwf lunghezza_descrittore goto procedi configuaration_descriptor movlw 56 movwf descrittore clrf step_descrittore
banco3 ;Prelevo la lunghezza dei byte richiesti movf buffer_USB6,W
movwf lunghezza_descrittore
movlw 41 ;lunghezza massima del descrittore subwf lunghezza_descrittore,W btfss STATUS,C goto procedi movlw 41 movwf lunghezza_descrittore goto procedi string_descriptor clrwdt
movlw 0 xorwf buffer_USB2,W btfsc STATUS,Z goto LANDID movlw 1 xorwf buffer_USB2,W btfsc STATUS,Z goto MANUFACTUR movlw 2 xorwf buffer_USB2,W btfsc STATUS,Z goto PRODUCT clrf descrittore clrf lunghezza_descrittore clrf byte_to_write clrf step_descrittore goto procedi LANDID movlw 97 movwf descrittore clrf step_descrittore movlw 4 movwf lunghezza_descrittore goto procedi MANUFACTUR movlw 101 movwf descrittore clrf step_descrittore movlw 8 movwf lunghezza_descrittore goto procedi PRODUCT movlw 109 movwf descrittore clrf step_descrittore movlw 20 movwf lunghezza_descrittore goto procedi procedi
movf lunghezza_descrittore,W ;indica quanti byte ho già inviato al PC movwf appoggio_USB movlw 8 subwf appoggio_USB,W btfss STATUS,C goto fine_GET_DESCRIPTOR
;Arrivo qui se la lunghezza del descrittore è maggiore dello step_descrittore di almeno 8
movlw 8 movwf byte_to_write addwf step_descrittore,F call write_EP goto ritorno1 fine_GET_DESCRIPTOR movf appoggio_USB,W btfsc STATUS,Z goto ultimo_GET_DESCRIPTOR movwf byte_to_write movf step_descrittore,W movf lunghezza_descrittore,W movwf step_descrittore call write_EP goto ritorno1 ultimo_GET_DESCRIPTOR clrf byte_to_write clrf descrittore clrf step_descrittore call write_EP goto ritorno1
GET_CONFIGURATION_DEVICE clrwdt goto ritorno1 SET_CONFIGURATION_DEVICE clrwdt banco3 movf buffer_USB2,W movwf device_configured banco0 bsf PORTA,A0 movlw 0x01 call WRITE_USB bcf PORTA,A0 call READ_USB bsf PORTA,A0 movlw 0xF0 call WRITE_USB bcf PORTA,A0 movlw 0 call WRITE_USB movlw 0 call WRITE_USB bsf PORTA,A0 movlw 0xFA call WRITE_USB bcf PORTA,A0 goto ritorno1 ;--- ; INTERFACE REQUEST ;--- STANDARD_INTERFACE_REQUEST clrwdt
movlw 0x06 ;GET DESCRIPTOR xorwf buffer_USB1,W btfsc STATUS,Z goto GET_DESCRIPTOR_INTERFACE movlw 0x00 ;GET INTERFACE xorwf buffer_USB1,W btfsc STATUS,Z goto GET_STATUS_INTERFACE movlw 0x0B ;SET INTERFACE xorwf buffer_USB1,W btfsc STATUS,Z goto SET_INTERFACE
movlw 0x0A ;GET
INTERFACE xorwf buffer_USB1,W btfsc STATUS,Z goto GET_INTERFACE goto stallo GET_DESCRIPTOR_INTERFACE movlw 18 movwf descrittore clrf step_descrittore movlw 38 movwf lunghezza_descrittore
movf lunghezza_descrittore,W ;indica quanti byte ho già inviato al PC movwf appoggio_USB movlw 8 subwf appoggio_USB,W btfss STATUS,C goto fine_GET_DESCRIPTOR_INTERFACE ;Arrivo qui se la lunghezza del descrittore è maggiore dello step_descrittore di almeno 8
movlw 8
movwf byte_to_write addwf step_descrittore,F
call write_EP goto ritorno1 fine_GET_DESCRIPTOR_INTERFACE movf appoggio_USB,W btfsc STATUS,Z goto ultimo_GET_DESCRIPTOR_INTERFACE movwf byte_to_write movf step_descrittore,W movf lunghezza_descrittore,W movwf step_descrittore call write_EP goto ritorno1 ultimo_GET_DESCRIPTOR_INTERFACE clrf byte_to_write clrf descrittore clrf step_descrittore call write_EP goto ritorno1 GET_STATUS_INTERFACE clrwdt goto ritorno1 SET_INTERFACE clrwdt goto ritorno1 GET_INTERFACE
clrwdt goto ritorno1 ;--- ; ENDPOINT REQUEST ;--- STANDARD_ENDPOINT_REQUEST clrwdt movlw 0x01 ;CLEAR FEATURE xorwf buffer_USB1,W btfsc STATUS,Z goto CLEAR_FEATURE_ENDPOINT movlw 0x03 ;SET FEATURE xorwf buffer_USB1,W btfsc STATUS,Z goto CLEAR_FEATURE_ENDPOINT
movlw 0x00 ;GET STATUS
xorwf buffer_USB1,W btfsc STATUS,Z goto GET_STATUS_ENDPOINT goto stallo CLEAR_FEATURE_ENDPOINT clrwdt banco3 movf buffer_USB2,W btfss STATUS,Z goto stallo movf buffer_USB3,W btfss STATUS,Z goto stallo movlw 0x01 xorwf buffer_USB1,W movlw 1 btfsc STATUS,Z
movlw 0 movwf header movlw 0x01 xorwf buffer_USB4,W btfsc STATUS,Z goto comando01 movlw 0x81 xorwf buffer_USB4,W btfsc STATUS,Z goto comando81 movlw 0x82 xorwf buffer_USB4,W btfsc STATUS,Z goto comando82 movlw 0x02 xorwf buffer_USB4,W btfsc STATUS,Z goto comando02 ;Condizione di stallo clrwdt banco0 bsf PORTA,A0 movlw 0x41 call WRITE_USB bcf PORTA,A0 movlw 0x41 call WRITE_USB bsf PORTA,A0 movlw 0x40 call WRITE_USB bcf PORTA,A0 movlw 0x40 call WRITE_USB goto esci_set_clear_feature comando01 clrwdt banco0 bsf PORTA,A0 movlw 0x42 call WRITE_USB bcf PORTA,A0
movf header,W call WRITE_USB goto esci_set_clear_feature comando81 clrwdt banco0 bsf PORTA,A0 movlw 0x43 call WRITE_USB bcf PORTA,A0 movf header,W call WRITE_USB goto esci_set_clear_feature comando02 clrwdt banco0 bsf PORTA,A0 movlw 0x44 call WRITE_USB bcf PORTA,A0 movf header,W call WRITE_USB goto esci_set_clear_feature comando82 clrwdt banco0 bsf PORTA,A0 movlw 0x45 call WRITE_USB bcf PORTA,A0 movf header,W call WRITE_USB goto esci_set_clear_feature esci_set_clear_feature banco3 clrf lunghezza_descrittore clrf descrittore clrf byte_to_write call write_EP goto ritorno1
GET_STATUS_ENDPOINT clrwdt goto ritorno1 ;--- ;STALLO stallo banco3 incf prova_stallo,F clrwdt banco0 bsf PORTA,A0 movlw 0x41 call WRITE_USB bcf PORTA,A0 movlw 0x41 ;era 41 call WRITE_USB bsf PORTA,A0 movlw 0x40 call WRITE_USB bcf PORTA,A0 movlw 0x40 call WRITE_USB ; goto ritorno1 banco0 return errore_transizione banco0 return esci_USB banco0 return errore_USB banco0
return
;---
; ROUTINE che si occupa di leggere byte_to_read byte dal buffer del PDI (vista) ;---
leggi_buffer
clrwdt
bsf STATUS,IRP banco3
movlw 0xC0;buffer_USB0 ;metto l'indirizzo del buffer su cui andrò a memorizzare i byte prelevati dal PDI
movwf FSR
bsf FSR,7 ;dipende da dove voglio scrivere nei banchi (chi non ci crede veda i data sheet)
loop_lettura_USB clrwdt banco0 call READ_USB banco3 movf USB_data,W movwf INDF incf FSR,F decfsz byte_to_read,F goto loop_lettura_USB banco0
;Pulisco il buffer alla fine della lettura
bsf PORTC,A0 movlw 0xF2
call WRITE_USB return
;---
; ROUTINE CHE RICEVE IN INGRESSO l'indirizzo da cui cominciare ad inviare i dati ; l'endpoint su cui inviarli e quanti inviarne
;--- write_EP
clrwdt nop nop nop nop nop nop nop nop nop nop ; banco3 ; movlw 255 ; movwf tentativi ;riv1 ; decf tentativi,F ; btfsc STATUS,Z ; goto esci_EP0 ; clrwdt
;Se sono qui devo scrivere sull'EP0 banco0
bsf PORTC,A0
movlw 0x01 ;Seleziono l'EP0_IN call WRITE_USB
bcf PORTC,A0
call READ_USB ; banco3
; btfsc USB_data,0 ;Verifico che il buffer sia vuoto
; goto riv1 banco0 bsf PORTC,A0 movlw 0xF0 call WRITE_USB bcf PORTC,A0
movlw 0 call WRITE_USB banco3 movf byte_to_write,W banco0 call WRITE_USB ;Da qui comincia ad inviare i dati del descrittore
banco3 movf byte_to_write,F btfsc STATUS,Z goto nessun_byte altro_descrittore call tabella_enumerazione ;torna con in W il valore del dato da scrivere
call WRITE_USB banco3
incf descrittore,F ;incremento il puntatore alla lista di dati da inviare
decfsz byte_to_write,F ;ho inviato il primo byte goto altro_descrittore
nessun_byte
banco0
bsf PORTC,A0
movlw 0xFA ;Comando di validate buffer call WRITE_USB bcf PORTC,A0 return ;esci_EP0 ; banco0 ; return ;---
;--- buffer_EP0_non_valido clrwdt banco0 bsf PORTA,A0 movlw 0xF2 call WRITE_USB bcf PORTA,A0 return ;--- USB ; banco1 ; movlw b'11111111' ; movwf TRISD ; banco0 ; clrf T1CON ; ROM_PAGE1 ; call rilascio_tasto ; ROM_PAGE3 ; bcf PORTE,CS_N ; ROM_PAGE1 ; call deltaRX ; call deltaRX ; call deltaRX ; ROM_PAGE3
;Pulisco il buffer del PDI banco0
bsf PORTA,A0
movlw 0x02 ;Seleziono l'EP1_OUT call WRITE_USB
movlw 0xF2
call WRITE_USB bcf PORTA,A0
; bsf PORTA,A0
; movlw 0x00 ;Seleziono l'EP0_OUT ; call WRITE_USB
; movlw 0xF2 ; call WRITE_USB ; bcf PORTA,A0 ; bsf PORTA,A0 ; movlw 0xD0 ; call WRITE_USB ; bcf PORTA,A0 ; banco3 ; movf ADDRESS,W ; banco0 ; call WRITE_USB ; bsf PORTA,A0 ; movlw 0xF6 ; call WRITE_USB ; bcf PORTA,A0 goto ll ;****************************************************************************************** *************************
;prova_USB è il ciclo principale che viene chiamato dopo i settaggi iniziali e le tarature ; degli offset ;****************************************************************************************** ************************* prova_USB ; banco0 ; clrf T1CON
usb_in ;setto le porte del PDIUSBD12 come ingresso
bcf USB_EN ;Abilito il PDIUSBD12 call USB_INIT ;settaggi iniziali PDIUSBD12
ll
banco0 clrwdt
bcf USB_EN ;abilito il chip PDIUSBD12
; banco3 ;ci ho messo le variabili che uso per l'USB
;aggiungengerci qualcosa da fare per uscire dasl ciclo...
goto ll
;esci_prova_USB
; banco0
; bsf PORTE,2 ;disabilito il Chip PDI ; banco1 ; clrf TRISD ; banco0 ; return ;REMOTE ; banco3 ; clrf messaggio ; clrf messaggio_start_remote_scan ; banco1 ; clrf TRISD ; banco0 ; bsf PORTE,2 ; return end
A.2 Programma in VisualC++ per l’interfaccia grafica
// HoodDlgDlg.h : header file
// #if !defined(AFX_HOODDLGDLG_H__D498629F_2F03_46CE_98AC_CD766152CA7D__INCLUDED_) #define AFX_HOODDLGDLG_H__D498629F_2F03_46CE_98AC_CD766152CA7D__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 ///////////////////////////////////////////////////////////////////////////// // CHoodDlgDlg dialog #include "UsbDaqOcx.h" #include <MatleyUtils.h> #include <TabData.h>
#define UDO (*((CUsbDaqOcx*)WND(IDC_USBDAQOCX))) class CHoodDlgDlg : public CDialog
{
// Construction public:
CHoodDlgDlg(CWnd* pParent = NULL); // standard constructor // Dialog Data
//{{AFX_DATA(CHoodDlgDlg) enum { IDD = IDD_HOODDLG_DIALOG };
// NOTE: the ClassWizard will add data members here //}}AFX_DATA
// ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CHoodDlgDlg) protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL
// Implementation private:
double _ratedCapacity[8], _channels[8]; TabData _data;
DWORD _startTick,_lastTick; protected:
HICON m_hIcon;
// Generated message map functions //{{AFX_MSG(CHoodDlgDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam); afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon(); virtual void OnOK();
virtual void OnCancel();
afx_msg void OnConnect(); afx_msg void OnDisconnect(); afx_msg void OnStart();
afx_msg void OnTimer(UINT nIDEvent); afx_msg void OnStop();
afx_msg void OnExport(); //}}AFX_MSG
DECLARE_MESSAGE_MAP() };
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif //
!defined(AFX_HOODDLGDLG_H__D498629F_2F03_46CE_98AC_CD766152CA7D__INCLUDED_)
// HoodDlgDlg.cpp : implementation file
//
#include "stdafx.h" #include "HoodDlg.h" #include "HoodDlgDlg.h" #ifdef _DEBUG
#define new DEBUG_NEW #undef THIS_FILE
static char THIS_FILE[] = __FILE__; #endif
///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App About
class CAboutDlg : public CDialog {
public:
CAboutDlg(); // Dialog Data
//{{AFX_DATA(CAboutDlg) enum { IDD = IDD_ABOUTBOX }; //}}AFX_DATA
// ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: //{{AFX_MSG(CAboutDlg) //}}AFX_MSG DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { //{{AFX_DATA_INIT(CAboutDlg) //}}AFX_DATA_INIT } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CAboutDlg) //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) //{{AFX_MSG_MAP(CAboutDlg) // No message handlers //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CHoodDlgDlg dialog
CHoodDlgDlg::CHoodDlgDlg(CWnd* pParent /*=NULL*/) : CDialog(CHoodDlgDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CHoodDlgDlg)
// NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CHoodDlgDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CHoodDlgDlg)
//}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CHoodDlgDlg, CDialog) //{{AFX_MSG_MAP(CHoodDlgDlg) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDB_CONNECT, OnConnect) ON_BN_CLICKED(IDB_DISCONNECT, OnDisconnect) ON_BN_CLICKED(IDB_START, OnStart) ON_WM_TIMER() ON_BN_CLICKED(IDB_STOP, OnStop) ON_BN_CLICKED(IDB_EXPORT, OnExport) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CHoodDlgDlg message handlers
BOOL CHoodDlgDlg::OnInitDialog() {
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); }
}
// Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here
WEN(IDB_CONNECT,1); WEN(IDB_DISCONNECT,0);
WEN(IDB_START,0); WEN(IDB_STOP,0); WEN(IDB_EXPORT,0);
return TRUE; // return TRUE unless you set the focus to a control }
void CHoodDlgDlg::OnSysCommand(UINT nID, LPARAM lParam) {
if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } }
// If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework.
void CHoodDlgDlg::OnPaint() {
if (IsIconic()) {
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect;
GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon
dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } }
// The system calls this to obtain the cursor to display while the user drags // the minimized window.
HCURSOR CHoodDlgDlg::OnQueryDragIcon() {
return (HCURSOR) m_hIcon; }
void CHoodDlgDlg::OnOK() {
// TODO: Add extra validation here CDialog::OnOK();
}
void CHoodDlgDlg::OnCancel() {
// TODO: Add extra cleanup here CDialog::OnCancel(); }
void CHoodDlgDlg::OnConnect() {
// TODO: Add your control notification handler code here long vid,pid; CString svid,spid; WGT(IDE_VID,svid); WGT(IDE_PID,spid); vid = atoi(svid); pid = atoi(spid);
BOOL ans = UDO.Connect(vid,pid); if(ans) { WEN(IDB_CONNECT,0); WEN(IDB_DISCONNECT,1); WEN(IDB_START,1); WEN(IDB_STOP,0); WEN(IDB_EXPORT,0); } } void CHoodDlgDlg::OnDisconnect() {
// TODO: Add your control notification handler code here UDO.Disconnect(); WEN(IDB_CONNECT,1); WEN(IDB_DISCONNECT,0); WEN(IDB_START,0); WEN(IDB_STOP,0); WEN(IDB_EXPORT,0); }
void CHoodDlgDlg::OnStart() {
// TODO: Add your control notification handler code here _data.Reset(9); _startTick = GetTickCount(); _lastTick = _startTick; DWORD rsi; CString srsi; WGT(IDE_DESIRED_SAMPLE_INTERVAL,srsi); rsi=atoi(srsi); double rc; CString src; WGT(IDE_RATED_CAPACITY,src); rc = atof(src); for(int ch=0; ch<8; ch++) { _ratedCapacity[ch] = rc; _channels[ch] = 0.0; } SetTimer(1,rsi,NULL); WEN(IDB_CONNECT,0); WEN(IDB_DISCONNECT,0); WEN(IDB_START,0); WEN(IDB_STOP,1); WEN(IDB_EXPORT,0); }
void CHoodDlgDlg::OnTimer(UINT nIDEvent) {
// TODO: Add your message handler code here and/or call default BOOL ans = UDO.ReadChannels(_ratedCapacity, _channels); if(!ans)
OnStop();
DWORD tick = GetTickCount(); DWORD deltaTick = tick - _lastTick; _lastTick = tick; CString sdt; sdt.Format("%u",deltaTick); WST(IDE_REAL_SAMPLE_INTERVAL,sdt); _data.PushInt(tick - _startTick); for(int ch=0; ch<8; ch++) _data.PushFloat(_channels[ch]);
CDialog::OnTimer(nIDEvent); }
void CHoodDlgDlg::OnStop() {
// TODO: Add your control notification handler code here KillTimer(1); WEN(IDB_CONNECT,0); WEN(IDB_DISCONNECT,1); WEN(IDB_START,1); WEN(IDB_STOP,0); WEN(IDB_EXPORT,1); } void CHoodDlgDlg::OnExport() {
// TODO: Add your control notification handler code here _data.ToFile(".\\data.txt");