/********************************************************************* * * Microchip USB C18 Firmware Version 1.0 * ********************************************************************* * FileName: user.c * Dependencies: See INCLUDES section below * Processor: PIC18 * Compiler: C18 2.30.01+ * Company: Microchip Technology, Inc. * * Software License Agreement * * * Author Date Comment ; Author: Dario Greggio (based upon Dan Butler's & Rawin Rojvanit's work from Microchip) ; Company: ADPM Synthesis sas *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Dario Greggio 27/02/05 Original. * Rawin Rojvanit 19/11/04 Original. ********************************************************************/ /****************************************************************************** * Peluche USB 2.00 * 10/1/2006: inizio * 25/1/2006: test ok da Strama ****************************************************************************** * Note: usando variabili statiche si riduce la dimensione del programma... * ovviamente occupando l'area di RAM! (v. quindi OVERLAY) * facendo confronti tra BYTE e costanti numeriche, usare HEX e non DEC, * perchÿé queste ultime vengono trattate come int16 e non int8 * *****************************************************************************/ /** I N C L U D E S **********************************************************/ #include #include #include #include #include #include #include #include "system\usb\usb.h" #include "io_cfg.h" // I/O pin mapping #include "user\user.h" #include "user\pelucheusb18.h" #pragma config WDT = ON, WDTPS = 1024, MCLRE=ON, STVREN=ON, LVP=OFF #pragma config PLLDIV=5, CPUDIV=OSC1_PLL2, USBDIV=2, FOSC=HSPLL_HS, FCMEM=OFF, IESO=OFF, PWRT=ON, BOR=ON, BORV=2 #pragma config VREGEN=ON, LPT1OSC=OFF, PBADEN=OFF, CCP2MX=ON, XINST=OFF, DEBUG=OFF /** V A R I A B L E S ********************************************************/ //static rom const char SKYUSB_C[]= {"PIC18F2550 Full-Speed USB - Peluche musicale USB\r\n\r\n"}; static rom const char CopyrString[]= {'P','e','l','u','c','h','e',' ','m','u','s','i','c','a','l','e',' ','U','S','B',' ','(','A','D','P','M',' ','S','y','n','t','h','e','s','i','s',')',' ', VERNUMH+'0','.',VERNUML/10+'0',(VERNUML % 10)+'0', ' ','1','7','/','1','0','/','0','6', 0 }; #pragma udata byte InitOK; byte CounterL; byte oldPB,oldPC; byte Options_Mode1=0; // b0: 1=USB, 0=stand-alone // b2: 1=sta suonando // b3: mettere a 1 per interrompere brano // b7: 1=loop // byte Options_Mode2=0; // b4:b7 brano default (in modalitÿà >1 brani) // b0:b3 numbrani word Tmr0Base=TMR0BASE,Tmr0BaseSuona=TMR0BASE_SUONA; char inSuona=0; // altrimenti NON e' inizializzata... e IRQ troppo pesanti IMPEDISCONO ENUMERAZIONE! byte TimerBuzz; #pragma udata access ACCESSBANK near union LONG_4BYTE SPIAddr,SPIAddr2; near byte SPIBufferPtr; #pragma udata byte USBPCBuffI[HID_INT_OUT_EP_SIZE /*BUF_SIZE_USB*/]; // usato per ricevere i dati (endpoint/report) dal PC byte USBPCBuffO[HID_INT_IN_EP_SIZE ]; // usato per preparare i pacchetti (endpoint) per il PC #pragma udata gpr1 byte SPIBuffer[SIZEOF_SPIBUFFER]; // il max e' 80... meglio 2^n, per check (v.sotto...) const rom byte sinusTable[16]={ // 16 campioni di una sinusoide 128, 176, 218, 246, 255, 246, 218, 176, 128, 79, 37, 9, 0, 9, 37, 79}; #pragma udata /** P R I V A T E P R O T O T Y P E S ***************************************/ void clearOutBuffer(void); void impostaBranoDaIndice(byte ); void impostaDurataBrano(byte ); char suonaBrano(void); void fineSuonaBrano(void); char Beep(void); /** D E C L A R A T I O N S **************************************************/ #pragma code void UserInit(void) { byte i; InitOK=RCON; // RCONbits.NOT_BOR=1; // RCONbits.NOT_POR=1; StatusReset(); OpenTimer0(TIMER_INT_ON & T0_16BIT & T0_SOURCE_INT & T0_PS_1_8); // (la frequenza di TMR0 e' 24/4MHz, divido per 8 ) // il timer 2 ÿè usato per il beep... // il timer 0 puÿò essere usato T1CON=0x30; //00110000b; // spengo Timer1 CCP1CON=0x0c; //00001100b; // TMR2: PWM mode CCPR1L=BEEP_STD_FREQ/2; // movlw BEEP_STD_FREQ/2 // in PWM questo e' READ-ONLY // movwf CCPR1H T2CON=0x03; //00000011b; // set prescaler T2 // OpenPWM1(); USARE?? PR2=BEEP_STD_FREQ; EnablePullups(); TRISA = 0b00010000; // TUTTE output - 1 TRISB = 0b11010011; // 1=input TRISC = 0b00000011; // 1=input e cmq. per RS232!, 0=output per PWM! LATA=0b00100000; // led spenti e CS/HOLD alti; LATB=0b00001100; // led spenti e CS/HOLD alti; LATC=0b10000000; if(!(InitOK & (1 << 3 /*NOT_TO*/))) { // se era watchdog... // ...faccio soft-detach per ri-avere l'enumerazione da PC USBSoftDetach(); } warm_reset: INTCONbits.GIE = 1; // attiva interrupt globali Tmr0Base=TMR0BASE; Tmr0BaseSuona=TMR0BASE_SUONA; inSuona=0; SPIBufferPtr=0; CounterL=0; EEcopiaARAM(&Options_Mode1); EEcopiaARAM(&Options_Mode2); // EEcopiaARAM(&sampleDelay); // if(sampleDelay) // sampleDelay=(1000000/22050)-DELAY_CORREZ; // NO! lo faccio scrivere al PC a ogni avvio del programma, se ÿè "0"! USBPCBuffI[0]=0; USBPCBuffI[1]=0; m_Led1Bit=0; // led attivo alto... m_Led2Bit=0; // led attivo alto... m_Led3Bit=0; // led attivo alto... SPITXDAC(0x80); // preset DAC (anti-bump) oldPB=PORTB; oldPC=PORTC; prepOutBuffer(1); // indicatore if(!mHIDTxIsBusy()) // boot packet?? HIDTxReport(USBPCBuffO,HID_INT_IN_EP_SIZE); } //end UserInit /****************************************************************************** * Function: void ProcessIO(void) * * PreCondition: None * * Input: None * * Output: None * * Side Effects: None * * Overview: This function is a place holder for other user routines. * It is a mixture of both USB and non-USB tasks. * * Note: None *****************************************************************************/ void ProcessIO(void) { byte i; // User Application USB tasks if((usb_device_state < CONFIGURED_STATE) || (UCONbits.SUSPND==1)) goto no_USB; ClrWdt(); // Clear the WDT /* while(1) { // test timing Delays Delay_uS(100); m_Led2Bit ^= 1; }*/ // m_Led2Bit ^= 1; // test ProcessIO Delays => circa 20uS, may 2005 if(Options_Mode1 & 1) { // se NON sono in stand-alone, leggo da PC... if(HIDRxReport(USBPCBuffI,HID_INT_OUT_EP_SIZE)) { // ricevuto pacchetto... // ---------------- leggo pacchetto scritto da PC --------------------------------------- switch(USBPCBuffI[1]) { // leggo il codice comando ricevuto // USBPCBuffI[0] contiene 2 = OUTPUT_REPORT case 0: break; case 1: // restituisce ID ASCII (per questi codici vedere anche PICMODEM-lampade a led) i=0; // puntatore alla stringa Copyright do { prepOutBuffer(1); // indicatore memcpypgm2ram((void *)(USBPCBuffO+2),(void *)(((char *)CopyrString)+i),HID_INT_IN_EP_SIZE-2); while(mHIDTxIsBusy()) { USBDriverService(); } HIDTxReport(USBPCBuffO,HID_INT_IN_EP_SIZE); i+=HID_INT_IN_EP_SIZE-2; } while(!memchr((void *)(USBPCBuffO+2),0,HID_INT_IN_EP_SIZE-2)); break; case 2: // restituisce config. CmdIn2: prepOutBuffer(2); // indicatore USBPCBuffO[2]=VERNUMH; USBPCBuffO[3]=VERNUML; if(inSuona) fineSuonaBrano(); // *((word *)(&USBPCBuffO[4]))=config; SPISTART_B(CSMemVal); SPITXByte(0xAB); // legge Electronic Signature su M25P80 SPITXByte(0); // 3 dummy SPITXByte(0); // 3 dummy SPITXByte(0); // 3 dummy USBPCBuffO[8]=SPIRXByte(); SPISTOP_B(CSMemVal); switch(USBPCBuffO[8]) { case 0x10: // M25P05 // questa parte dovrebbe variare a seconda della signature... USBPCBuffO[4]=(65536/1024) % 256; USBPCBuffO[5]=(65536/1024) / 256; break; case 0x12: // M25P40 USBPCBuffO[4]=(1048576/2/1024) % 256; USBPCBuffO[5]=(1048576/2/1024) / 256; break; case 0x13: // M25P80 USBPCBuffO[4]=(1048576/1024) % 256; USBPCBuffO[5]=(1048576/1024) / 256; break; // altre default: USBPCBuffO[4]=0; USBPCBuffO[5]=0; break; } CmdIn2_M: SPISTART_B(CSMemVal); SPITXByte(5); // legge STATUS su M25P80 USBPCBuffO[9]=SPIRXByte(); SPISTOP_B(CSMemVal); USBPCBuffO[6]=Options_Mode1; USBPCBuffO[7]=Options_Mode2; USBPCBuffO[8]=65536-Tmr0BaseSuona; while(mHIDTxIsBusy()) { USBDriverService(); } HIDTxReport(USBPCBuffO,HID_INT_IN_EP_SIZE); break; case 3: // SetCfg if(inSuona) fineSuonaBrano(); clearOutBuffer(); INTCONbits.GIE=0; Options_Mode1=USBPCBuffI[2]; // nuovo byte conf. EEcopiaAEEPROM(&Options_Mode1); //; call EEscrivi ; NON SI PUo'/poteva usare: cancellerebbe tutto un settore! Options_Mode2=USBPCBuffI[3]; // nuovo byte conf. EEcopiaAEEPROM(&Options_Mode2); Tmr0BaseSuona=USBPCBuffI[4]; // idem EEcopiaAEEPROM(&Tmr0BaseSuona); Tmr0BaseSuona=65536-Tmr0BaseSuona; // consentire scrittura a STATUS di Flash?? // movfw USBPCBuffI+4 INTCONbits.GIE = 1; goto CmdIn2; // per conferma... break; case 4: // programmazione Flash: indirizzo a 24 bit (max=16MB) if(inSuona) fineSuonaBrano(); memcpy((void *)SPIBuffer+SPIBufferPtr,(void *)(USBPCBuffI+2),32); SPIBufferPtr+=32; SPIBufferPtr &= (SIZEOF_SPIBUFFER-1); // evita sforamenti...! break; case 5: // programmazione Flash: 2ÿ° parte (indirizzo a 24 bit (max=16MB)) if(inSuona) fineSuonaBrano(); m_Led2Bit=1; SPIAddr.b[0]=USBPCBuffI[2]; //salvo l'indirizzo (24bit cmq) e il flag Erase SPIAddr.b[1]=USBPCBuffI[3]; //salvo l'indirizzo (24bit cmq) e il flag Erase SPIAddr.b[2]=USBPCBuffI[4]; //salvo l'indirizzo (24bit cmq) e il flag Erase if(USBPCBuffI[5]) { SPIMemoryWriteWREN(); // prima di OGNI scrittura! SPIMemoryErasePage(); SPIMemoryWriteWRDI(); } if(USBPCBuffI[6]) { // lunghezza settore 64/128 byte... fare! } SPIMemoryWriteWREN(); // prima di OGNI scrittura! SPIWritePage24(); // gestire ev. errore? SPIMemoryWriteWRDI(); SPIBufferPtr=0; // pronto per nuova scrittura! m_Led2Bit=0; goto CmdIn2; // restituisco Status //; goto endCmd break; case 6: // lettura EEprom: 3 byte addr. if(inSuona) fineSuonaBrano(); SPIAddr.b[0]=USBPCBuffI[2]; // salvo l'indirizzo (24bit cmq) SPIAddr.b[1]=USBPCBuffI[3]; SPIAddr.b[2]=USBPCBuffI[4]; SPIReadPage24(); // legge 64 byte SPIBufferPtr=0; #define READ_CHUNK_SIZE 32 for(i=0; i<64; i+=READ_CHUNK_SIZE) { prepOutBuffer(34); // indicatore (prima parte) memcpy((void *)(USBPCBuffO+2),(void *)(SPIBuffer+SPIBufferPtr),READ_CHUNK_SIZE); while(mHIDTxIsBusy()) { USBDriverService(); } HIDTxReport(USBPCBuffO,HID_INT_IN_EP_SIZE); SPIBufferPtr+=READ_CHUNK_SIZE; // mando fuori tutti i 64 byte a blocchi di 32 } break; case 7: // nop break; case 8: // suona un brano scelto (dato indirizzo oppure #) if(inSuona) fineSuonaBrano(); if(!(USBPCBuffI[2] & 0x80)) { // se #brano>127, uso l'indirizzo impostaBranoDaIndice(USBPCBuffI[2]); // #brano... } else { SPIAddr.b[0]=USBPCBuffI[2] & 0x7f; // indirizzo brano... SPIAddr.b[1]=USBPCBuffI[3]; SPIAddr.b[2]=USBPCBuffI[4]; } impostaDurataBrano(USBPCBuffI[5]); // durata brano (in 64K) // movfw USBPCBuffI+8 ; sample rate? // movwf sampleDelay suonaBrano(); prepOutBuffer(3); USBPCBuffO[2]=SPIAddr.b[0]; USBPCBuffO[3]=SPIAddr.b[1]; USBPCBuffO[4]=SPIAddr.b[2]; USBPCBuffO[5]=SPIAddr2.b[0]; USBPCBuffO[6]=SPIAddr2.b[1]; USBPCBuffO[7]=SPIAddr2.b[2]; USBPCBuffO[8]=inSuona; while(mHIDTxIsBusy()) { USBDriverService(); } HIDTxReport(USBPCBuffO,HID_INT_IN_EP_SIZE); break; case 11: // beep Beep(); break; case 12: // test_audio(USBPCBuffI[2]); // frequenza [0..255] break; case 13: // test: accendo/spengo TX/RX in base a BYTE1:b0, e il led in base a BYTE1:b1 CounterL=0; // per testare m_Led2Bit=USBPCBuffI[2] & 1 ? 0 : 1; // led attivo basso... m_Led3Bit=USBPCBuffI[2] & 2 ? 0 : 1; // led attivo basso... break; case 14: // RESET (occhio a Enum. USB) Reset(); break; case 15: // ECHO prepOutBuffer(31); memcpy((void *)(USBPCBuffO+2),(void *)(USBPCBuffI+2), // min(HID_INT_IN_EP_SIZE,HID_INT_OUT_EP_SIZE)-2); HID_INT_OUT_EP_SIZE-2); while(mHIDTxIsBusy()) { USBDriverService(); } HIDTxReport(USBPCBuffO,HID_INT_IN_EP_SIZE); break; default: break; } } // if HidRXReport } // if Options_Mode1 USBPCBuffI[0]=0; USBPCBuffI[1]=0; no_USB: ; if(!(Options_Mode1 & 1)) { // se sono in stand-alone, mi spengo... // sleep // movlw CSMemVal // call SPISTART // movlw 0b9h ; Enter PowerDown // call SPITXByte // movlw CSMemVal // call SPISTOP } } //end ProcessIO /****************************************************************************** * Function: void HandleControlOutReport(void) * * PreCondition: None * * Input: None * * Output: None * * Side Effects: None * * Overview: Checks to see if an Output or Feature report has arrived * on the control pipe. If yes, extracts and uses the data. * * Note: serve per HidD_SetOutputReport da C!! *****************************************************************************/ void HandleControlOutReport() { byte count; // Find out if an Output or Feature report has arrived on the control pipe. // Get the report type from the Setup packet. switch(MSB(SetupPkt.W_Value)) { case 0x02: // Output report // Get the report ID from the Setup packet. switch(LSB(SetupPkt.W_Value)) { case 0: // Report ID 0 // This example application copies the Output report data // to hid_report_in. // (Assumes Input and Output reports are the same length.) // A "real" application would do something more useful with the data. // wCount holds the number of bytes read in the Data stage. // This example assumes the report fits in one transaction. for(count = 1; count <= HID_OUTPUT_REPORT_BYTES; count++) { hid_report_in[count-1] = hid_report_out[count-1]; } // The number of bytes in the report (from usbcfg.h). break; } // end switch(LSB(SetupPkt.W_Value)) break; case 0x03: // Feature report // Get the report ID from the Setup packet. switch(LSB(SetupPkt.W_Value)) { case 0: // Report ID 0 // The Feature report data is in hid_report_feature. // This example application just sends the data back in the next // Get_Report request for a Feature report. // wCount holds the number of bytes read in the Data stage. // This example assumes the report fits in one transaction. break; } // end switch(LSB(SetupPkt.W_Value)) break; } // end switch(MSB(SetupPkt.W_Value)) } /****************************************************************************** * Function: void GetInputReport0(void) * * PreCondition: None * * Input: None * * Output: None * * Side Effects: None * * Overview: Prepares to send the data in hid_report_out in the Data * stage of the current Get_Report transfer. * * Note: serve per HidD_SetOutputReport da C!! *****************************************************************************/ void GetInputReport0(void) { byte count; // Set pSrc.bRam to point to the report. // pSrc.bRam = (byte*)&hid_report_in; // The number of bytes in the report (from usbcfg.h). LSB(wCount) = HID_INPUT_REPORT_BYTES; } /****************************************************************************** * Function: void GetFeatureReport0(void) * * PreCondition: None * * Input: None * * Output: None * * Side Effects: None * * Overview: Prepares to send the data in hid_report_feature in the Data * stage of the current Get_Report transfer. * * Note: serve per HidD_SetOutputReport da C!! *****************************************************************************/ void GetFeatureReport0(void) { byte count; // Set pSrc.bRam to point to the report. pSrc.bRam = (byte*)&hid_report_feature; // The number of bytes in the report (from usbcfg.h). LSB(wCount) = HID_FEATURE_REPORT_BYTES; } void ResCnt(void) { byte i; CounterL++; m_Led1Bit ^= 1; if(usb_device_state != CONFIGURED_STATE /*(USWSTAT & 0x3) != CONFIG_STATE*/) { // compare lower 2 bits of USWSTAT // with configured state // are we configured? Options_Mode1 &= ~0x1; } else { Options_Mode1 |= 0x1; } test_1: //TEST1: invio pacch. al PC if(!m_Puls1Bit) { prepOutBuffer(16); // indicatore test USBPCBuffO[2]=PORTA; // stato porta A USBPCBuffO[3]=PORTB; // stato porta B USBPCBuffO[4]=PORTC; // stato porta C while(mHIDTxIsBusy()) { USBDriverService(); } HIDTxReport(USBPCBuffO,HID_INT_IN_EP_SIZE); } else { // un test esclude l'altro!! test_2: ; //TEST2: suona?? /* if(!m_Puls2Bit) { if(!m_Led1Bit) //solo quando il led ÿè acceso... test_audio(64-DELAY_CORREZ); // per avere 1KHz con 16 campioni = 64 uS ritardo. La trasmissione di 16 bit impiega 16uS }*/ /*test_1: //TEST1: invio pacch. al PC if(!m_Puls1Bit) { prepOutBuffer(16); // indicatore test while(mHIDTxIsBusy()) { USBDriverService(); } HIDTxReport(USBPCBuffO,HID_INT_IN_EP_SIZE); }*/ } // USARE WAKE-UP portB #ifdef STRAMA_2006 if(!m_SuonaBit) { // il bit 0 ÿè attivazione (cordicella, microfono, sensore IR) if(Options_Mode2 & 15) { // se sono in modalitÿà Singolo Brano... impostaBranoDaIndice(0); impostaDurataBrano(15); // fisso 50 sec. circa (1MB @ 22050) } else { if(!m_AddrTipoBit) { // oppure, se devo usare indirizzo hardware... i=PORTB & 0b01000000; // prendo i bit 6 ?? di PORTB i = i ? 4 : 0; impostaBranoDaIndice(i & 0x0c); impostaDurataBrano(7); // fisso 23 sec. circa = 8*64K @ 22050 } else { i=Options_Mode2 >> 4; // se devo usare BranoDefault da Options_Mode2... impostaBranoDaIndice(i); i=Options_Mode2 & 15; impostaDurataBrano(i == 1 ? 15 : (16/i)-1); // (era fisso 11.888 sec. circa = 4*64K @ 22050) } } doPlay: suonaBrano(); } #else i=PORTC & 0b00000011; // prendo i bit 6 PORTC if(i != (oldPC & 0b00000011)) { if(i != 3) { if(inSuona) fineSuonaBrano(); if(!(i & 1)) impostaBranoDaIndice(0); else if(!(i & 2)) impostaBranoDaIndice(8); impostaDurataBrano(7); // fisso 23 sec. circa = 8*64K @ 22050 // while((PORTC & 3) != 3) // aspetto che risalga // ClrWdt(); suonaBrano(); // } // else { // if(i != 3) { // fineSuonaBrano(); // Options_Mode1 &= 0x7f; // } // } } } if(inSuona) { if(!m_SuonaStopBit) { // se devo terminare... fineSuonaBrano(); Options_Mode1 &= 0x7f; } if(Options_Mode1 & 0x8) // se devo terminare... fineSuonaBrano(); } #endif // gestione del buzzer ------------------------------------------------------------------- if(TimerBuzz) { TimerBuzz--; if(!TimerBuzz) T2CONbits.TMR2ON=0; } oldPB=PORTB; oldPC=PORTC; } // ---------------------------------------------------------------------------------------- #ifdef OLD char test_audio(byte n) { byte temp2; Tmr0BaseSuona=65536-n; temp2=0; CounterL=1; do { SPITXDAC(sinusTable[temp2 & 15]); // byte basso DAC // movlw CSDAVal // call SPISTART // movlw 00110000b ; 4 control bit + nibble alto DAC // call SPITXByteFast // movfw temp2 // pagesel getSinusTable // call getSinusTable ; byte basso DAC // pagesel SPITXByte // call SPITXByteFast // movlw CSDAVal // call SPISTOP // movlw 64-DELAY_CORREZ ; per avere 1KHz con 16 campioni = 64 uS ritardo. La trasmissione di 16 bit impiega 16uS Delay_uS(sampleDelay); temp2++; } while(CounterL); // ...finchÿé un ciclo-resCnt non si conclude... return 1; } #endif char Beep(void) { byte temp2,temp3; temp3=16; INTCONbits.T0IE=0; do { temp2=0; do { SPITXDAC(sinusTable[temp2 & 15]); // byte basso DAC Delay_uS(2); // per avere 4KHz con 16 campioni = 16 uS ritardo. (v. anche Test sopra) } while(--temp2); } while(--temp3); // lunghezza di un beep... ! INTCONbits.T0IE=1; return 1; } // ---------------------------------------------------------------------------------------- void impostaBranoDaIndice(byte n) { // entra W=indice (0..16) SPIAddr.b[2]=n & 0xf; // moltiplico per 65536 (ogni step=3sec @ 22050) SPIAddr.b[0]=0; SPIAddr.b[1]=0; SPIAddr.b[3]=0; } void impostaDurataBrano(byte n) { // entra W=durata in blocchi da 64K (0..16) SPIAddr2.b[2]= SPIAddr.b[2] + (n & 0xf); // moltiplico per 65536 (ogni step=3sec @ 22050) SPIAddr2.b[0]=0xff; SPIAddr2.b[1]=0xff; SPIAddr2.b[3]=0; } char suonaBrano(void) { static /*overlay*/ byte n; m_Led3Bit=1; // if(!SPIAddr[2] && !SPIAddr[1]) { // se siamo all'indirizzo 000000... // SPIAddr.l+=64; // ...skippo (inoltre) i 64 di Config... SPIAddr.l+=128; // ...e poi: skip header ID3_TAG (o simile...) Options_Mode1 |= 4; // sto suonando... Options_Mode1 &= ~8; // pulisco flag di Termina m_HoldMemBit=1; SPISTART_B(CSMemVal); // prepare start SPITXByte(3); // comando ReadBytes (ST-M25P80) SPITXByte(SPIAddr.b[2]); // MSB first SPITXByte(SPIAddr.b[1]); SPITXByte(SPIAddr.b[0]); // call SPIRXByte ; serve una prima lettura ??? m_HoldMemBit=0; // metto in HOLD... Tmr0Base=TMR0BASE_SUONA; inSuona=1; return 1; #ifdef OLD do { m_HoldMemBit=1; // esco da HOLD... n=SPIRXByteFast(); // read 1 byte from Flash m_HoldMemBit=0; // metto in HOLD... SPITXDAC(n); Delay_uS(sampleDelay); SPIAddr.l++; #ifdef STRAMA_2006 if(Options_Mode1 & 0x8) // se devo terminare... goto rifo_suonaBrano3; #endif // x Strama 2006 if(!m_SuonaStopBit) // se devo terminare... goto rifo_suonaBrano3; if((PORTC & 0b00000011) != 0b00000011) goto rifo_suonaBrano3; } while (SPIAddr.l < SPIAddr2.l); if(Options_Mode1 & 0x80) { // se sono in modalitÿà Loop... Delay_S(); // ritardino?? // con quale condizione esco dal loop?? la stessa di Termina (v.sopra) ? SPIAddr.l=0; // ricomincio da capo, o Salvare partenza giusta?? goto rifo_suonaBrano2; } rifo_suonaBrano3: m_HoldMemBit=1; // esco da HOLD... SPISTOP_B(CSMemVal); // chiudo memoria Flash Options_Mode1 &= ~4; // fine suonata... Options_Mode1 &= ~0x8; // pulisco flag di Termina // Options_Mode1 &= ~0x80; // pulisco flag di Loop ... ? NO! m_Led3Bit=0; return 1; #endif } void fineSuonaBrano(void) { Tmr0Base=TMR0BASE; SPITXDAC(0x80); // preset DAC (anti-bump) m_HoldMemBit=1; // esco da HOLD... SPISTOP_B(CSMemVal); // chiudo memoria Flash Options_Mode1 &= ~4; // fine suonata... Options_Mode1 &= ~0x8; // pulisco flag di Termina m_Led3Bit=0; inSuona=0; if(Options_Mode1 & 1) { prepOutBuffer(3); USBPCBuffO[2]=SPIAddr.b[0]; USBPCBuffO[3]=SPIAddr.b[1]; USBPCBuffO[4]=SPIAddr.b[2]; USBPCBuffO[5]=SPIAddr2.b[0]; USBPCBuffO[6]=SPIAddr2.b[1]; USBPCBuffO[7]=SPIAddr2.b[2]; USBPCBuffO[8]=inSuona; while(mHIDTxIsBusy()) { USBDriverService(); } HIDTxReport(USBPCBuffO,HID_INT_IN_EP_SIZE); } } void prepOutBuffer(byte t) { // entra W=IDENTificatore clearOutBuffer(); USBPCBuffO[0]=1; // dev'essere per forza 1! (ossia ID report di input) USBPCBuffO[1]=t; } void clearOutBuffer(void) { memset(USBPCBuffO,0,HID_INT_IN_EP_SIZE); } void StdBeep() { CCPR1L=BEEP_STD_FREQ/2; CCPR1H=BEEP_STD_FREQ/2; PR2=BEEP_STD_FREQ; T2CONbits.TMR2ON=1; Delay_S(); T2CONbits.TMR2ON=0; } void ErrorBeep() { CCPR1L=BEEP_STD_FREQ/2+30; CCPR1H=BEEP_STD_FREQ/2+30; PR2=BEEP_STD_FREQ+60; T2CONbits.TMR2ON=1; Delay_S(); T2CONbits.TMR2ON=0; } // ------------------------------------------------------------------------- //Delays W microseconds (includes movlw, call, and return) @ 48MHz void Delay_uS(byte uSec) { do { Delay1TCY(); // TARARE!! @48MHz?? Delay1TCY(); Delay1TCY(); Delay1TCY(); ClrWdt(); // Clear the WDT } while(--uSec); //return ; 1 } void Delay_S_(byte n) { // circa n*100mSec do { Delay_mS(100); } while(--n); } void Delay_mS(byte n) { // circa n ms do { Delay_uS(250); Delay_uS(250); Delay_uS(250); Delay_uS(250); } while(--n); } // ------------------------------------------------------------------------------------- void EEscrivi_(SHORTPTR addr,byte n) { EEADR = (byte)addr; EEDATA=n; EECON1bits.EEPGD=0; // Point to Data Memory EECON1bits.CFGS=0; // Access EEPROM EECON1bits.WREN=1; // INTCONbits.GIE = 0; // disattiva interrupt globali... e USB? EECON2=0x55; // Write 55h EECON2=0xAA; // Write AAh EECON1bits.WR=1; // abilita write. do { ClrWdt(); } while(EECON1bits.WR); // occupato ? // INTCONbits.GIE = 1; // attiva interrupt globali EECON1bits.WREN=0; // disabilita write. } byte EEleggi(SHORTPTR addr) { byte n; EEADR=(byte)addr; // Address to read EECON1bits.EEPGD=0; // Point to Data Memory EECON1bits.CFGS=0; // Access EEPROM EECON1bits.RD=1; // EE Read return EEDATA; // W = EEDATA } /****************************************************************************** * Function: void * * PreCondition: None * * Input: None * * Output: None * * Side Effects: None * * Overview: * * * Note: * * *****************************************************************************/ /** EOF user.c ***************************************************************/