• Non ci sono risultati.

- 1 - A.1 Firmware del microcontrollore Di seguito sono riportati il firmware del microcontrollore e il software per l’interfaccia utente in VisualC++. Appendice A

N/A
N/A
Protected

Academic year: 2021

Condividi "- 1 - A.1 Firmware del microcontrollore Di seguito sono riportati il firmware del microcontrollore e il software per l’interfaccia utente in VisualC++. Appendice A"

Copied!
66
0
0

Testo completo

(1)

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

(2)

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

(3)

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

(4)

;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 ;---

(5)

; 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 ;---

(6)

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

(7)

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

;--- ;---

(8)

;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

(9)

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)

(10)

; 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

(11)

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

(12)

;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 ;--- ;****************************************************************************************** ********************************** ;****************************************************************************************** **********************************

(13)

;--- ; 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'

(14)

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

(15)

;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

(16)

;--- ; 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)

(17)

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

(18)

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

(19)

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

(20)

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

(21)

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

(22)

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

(23)

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

(24)

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

(25)

;---

;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

(26)

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

(27)

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

(28)

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

(29)

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

(30)

; 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

(31)

; 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

(32)

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

(33)

; 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

(34)

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

(35)

;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

(36)

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

(37)

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

(38)

;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

(39)

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

(40)

;--- ; 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

(41)

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

(42)

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

(43)

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

(44)

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

(45)

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

(46)

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

(47)

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

(48)

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

(49)

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

(50)

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

(51)

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

(52)

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

(53)

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

(54)

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

(55)

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 ;---

(56)

;--- 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

(57)

; 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

(58)

; 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

(59)

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)

(60)

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

(61)

// 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)

(62)

//}}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);

(63)

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.

(64)

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); }

(65)

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]);

(66)

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");

Riferimenti

Documenti correlati

1) Una unità di elaborazione U contiene un componente logico memoria M di capacità N = 16K interi non negativi di 32 bit. Spiegare chiaramente come si è ragionato per definire

Abbiamo diviso il questionario studenti in quattro sezioni principali, per l’analisi delle quali procediamo innanzitutto a una descrizione e a un commento del questionario

Nella parte introduttiva vengono descritti i principi della prospettiva di investimento sociale e i programmi politici che propongono di implementare azioni

- Che cosa significa immaginare?.. - Differenza tra pensare ed immaginare- l’immaginazione come strumento per studiare la realtà. - La filosofia come scoperta: Talete

Precursore,*un*agnello*che*è*figura*della*grazia*e*che*sotto*la*Legge*ci*ha*prefigurato*

4 Date indéterminée elle aussi, mais qui remonte au moins au années 1760 comme nous 1 avons dit; Mazzoni fait venir de Gênes au premiers temps de la fabrication des

Le forze di polizia, incaricate di far rispettare la legge, incontrarono forti resistenze da parte delle comunità – come nel caso della rivolta di Pirano avvenuta nel 1814, durante

Mercati, L’imposta di soggiorno: i gestori delle strutture ricettive come agenti contabili “di fatto” Giornale di Diritto amministrativo 2/2017 “[…] tenendo