#include #include #include "pelucheusb18.h" #include "io_cfg.h" //#include "spi.h" /************************************************************** ; Start Bit Subroutine - SPI mode 0 ; this routine activates CS ; Entra W=valore (CS) di PortA da abbassare ;**************************************************************/ void SPISTART_B(byte a) { m_SPIClkBit=0; // make sure clock is low LATB &= ~a; SPI_DELAY(); } void SPISTART_C(byte a) { m_SPIClkBit=0; // make sure clock is low LATC &= ~a; SPI_DELAY(); } /************************************************************ ; Stop Bit Subroutine ; This routine deactivates CS ; Entra W=valore (CS) di PortA da alzare ;************************************************************/ void SPISTOP_B(byte a) { m_SPIClkBit=0; // make sure clock is low LATB |= a; SPI_DELAY(); } void SPISTOP_C(byte a) { m_SPIClkBit=0; // make sure clock is low LATC |= a; SPI_DELAY(); } /************************************************************* ; BITOUT routine takes the bit of data in C and ; transmits it to the serial EE device ;*************************************************************/ void SPIBITOUT(char b) { // check for state of data bit to xmit m_SPIDataOBit=b ? 1 : 0; // output a low bit // high? set data line high SPI_DELAY(); m_SPIClkBit=1; // set clock line high SPI_DELAY(); m_SPIClkBit=0; // return clock line low } /************************************************************** ; idem ma come MACRO (per velocità) ;**************************************************************/ #define SPI_BITOUT(b) \ {\ m_SPIDataOBit= b ? 1 : 0; \ SPI_DELAY() \ m_SPIClkBit=1; \ SPI_DELAY() \ m_SPIClkBit=0; \ } /************************************************************** ; BITIN routine reads one bit of data from the ; serial EE device and stores it in C ;**************************************************************/ char SPIBITIN(void) { static /*overlay*/ char n; SPI_DELAY(); m_SPIClkBit=1; // set clock line high SPI_DELAY(); // just sit here a sec n= m_SPIDataIBit ? 1 : 0; // read the data bit // input bit was low, set C accordingly // input bit was high, set C accordingly m_SPIClkBit=0; // set clock line low return n; } /**************************************************************** ; Transmit Data Subroutine ; This routine takes the byte of data stored in the ; 'temp' register and transmits it to the serial EE device. ;****************************************************************/ char SPITXByte(byte SPIData) { static /*overlay*/ byte SPICnt; for(SPICnt=0x80; SPICnt; SPICnt>>=1) { // set the #bits to 8 SPI_BITOUT(SPIData & SPICnt); // rotate SPIData/txbuf left, bit in CARRY // call SPIBITOUT ; send the bit to serial EE } return 1; // 1=OK (e C=0) } /**************************************************************** ; Transmit Data Subroutine FAST ; idem, ma senza loop ;****************************************************************/ char SPITXByteFast(byte n) { if(n & 0x80) m_SPIDataOBit=1; else m_SPIDataOBit=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); m_SPIClkBit=0; if(n & 0x40) m_SPIDataOBit=1; else m_SPIDataOBit=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); m_SPIClkBit=0; if(n & 0x20) m_SPIDataOBit=1; else m_SPIDataOBit=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); m_SPIClkBit=0; if(n & 0x10) m_SPIDataOBit=1; else m_SPIDataOBit=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); m_SPIClkBit=0; if(n & 0x8) m_SPIDataOBit=1; else m_SPIDataOBit=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); m_SPIClkBit=0; if(n & 0x4) m_SPIDataOBit=1; else m_SPIDataOBit=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); m_SPIClkBit=0; if(n & 0x2) m_SPIDataOBit=1; else m_SPIDataOBit=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); m_SPIClkBit=0; if(n & 0x1) m_SPIDataOBit=1; else m_SPIDataOBit=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); m_SPIClkBit=0; return 1; // 1=OK (e C=0) } /**************************************************************** ; Receive data routine ; This routine reads one byte of data from the part ; into the 'SPIData' register. ;****************************************************************/ byte SPIRXByte(void) { static /*overlay*/ byte SPIData; // fa 8 giri, non serve pulirla static /*overlay*/ byte SPICnt; for(SPICnt=0x80; SPICnt; SPICnt>>=1) { // set the #bits to 8 SPIData <<= 1; // rotate SPIData 1 bit left if(SPIBITIN()) // read a bit // SPI_BITIN ; MACRO read a bit SPIData |= 1; // else // SPIData |= 0; } return SPIData; } /**************************************************************** ; Receive data routine FAST ; idem ma senza loop ;****************************************************************/ byte SPIRXByteFast(void) { static /*overlay*/ byte SPIData; SPIData=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); if(m_SPIDataIBit) SPIData |= 0x80; m_SPIClkBit=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); if(m_SPIDataIBit) SPIData |= 0x40; m_SPIClkBit=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); if(m_SPIDataIBit) SPIData |= 0x20; m_SPIClkBit=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); if(m_SPIDataIBit) SPIData |= 0x10; m_SPIClkBit=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); if(m_SPIDataIBit) SPIData |= 0x8; m_SPIClkBit=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); if(m_SPIDataIBit) SPIData |= 0x4; m_SPIClkBit=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); if(m_SPIDataIBit) SPIData |= 0x2; m_SPIClkBit=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); if(m_SPIDataIBit) SPIData |= 0x1; m_SPIClkBit=0; return SPIData; // ritorna valore in W } /**************************************************************** ; Transmit Data Subroutine a DAC ; scrive (in modalità FAST) 16 bit al DAC, moltiplicando W*4 e aggiungendo status-bits ;****************************************************************/ void SPITXDAC(byte SPIData) { SPISTART_C(CSDAVal); // 0011 = status m_SPIDataOBit=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); m_SPIClkBit=0; // m_SPIDataOBit=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); m_SPIClkBit=0; m_SPIDataOBit=1; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); m_SPIClkBit=0; // m_SPIDataOBit=1; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); m_SPIClkBit=0; #ifndef AUDIO_BOOST_4 // XXXXXXXX0000 m_SPIDataOBit=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); m_SPIClkBit=0; #endif #ifndef AUDIO_BOOST_2 // 0XXXXXXXX000 m_SPIDataOBit=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); m_SPIClkBit=0; #endif if(SPIData & 0x80) m_SPIDataOBit=1; else m_SPIDataOBit=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); m_SPIClkBit=0; if(SPIData & 0x40) m_SPIDataOBit=1; else m_SPIDataOBit=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); m_SPIClkBit=0; if(SPIData & 0x20) m_SPIDataOBit=1; else m_SPIDataOBit=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); m_SPIClkBit=0; if(SPIData & 0x10) m_SPIDataOBit=1; else m_SPIDataOBit=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); m_SPIClkBit=0; if(SPIData & 8) m_SPIDataOBit=1; else m_SPIDataOBit=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); m_SPIClkBit=0; if(SPIData & 4) m_SPIDataOBit=1; else m_SPIDataOBit=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); m_SPIClkBit=0; if(SPIData & 2) m_SPIDataOBit=1; else m_SPIDataOBit=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); m_SPIClkBit=0; if(SPIData & 1) m_SPIDataOBit=1; else m_SPIDataOBit=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); m_SPIClkBit=0; #ifdef AUDIO_BOOST_4 // 0XXXXXXXX000 m_SPIDataOBit=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); m_SPIClkBit=0; #endif #if defined(AUDIO_BOOST_2) || defined(AUDIO_BOOST4) m_SPIDataOBit=0; SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); m_SPIClkBit=0; #endif m_SPIDataOBit=0; // x risparmiare tempo... SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); m_SPIClkBit=0; // m_SPIDataOBit=0; ; x risparmiare tempo... SPI_DELAY(); m_SPIClkBit=1; SPI_DELAY(); m_SPIClkBit=0; SPISTOP_C(CSDAVal); // !=0 => OK } /************************************************************** ; READ BYTE (read 1 byte routine) ; ; This routine reads 1 byte of the ; serial EE device starting at given 24bit address in the ; sequential read mode. ;***************************************************************/ /*SPIReadByte_W: ; dato W=l'indirizzo nel range 000000..0000ff movwf SPIAddr clrf SPIAddr+1 clrf SPIAddr+2*/ byte SPIReadByte(void) { static /*overlay*/ byte SPIData; SPISTART_B(CSMemVal); // prepare start SPITXByte(3); // comando ReadBytes (ST-M25P05) SPITXByte(SPIAddr.b[2]); // MSB first SPITXByte(SPIAddr.b[1]); SPITXByte(SPIAddr.b[0]); SPIData=SPIRXByte(); // read 1 byte from device SPISTOP_B(CSMemVal); return SPIData; } /************************************************************** ; READ PAGE 24 (sequential read routine) ; ; This routine reads 64 consecutive addresses of the ; serial EE device starting at given 24bit address in the ; sequential read mode. Reading in this mode is more ; efficient than the random read mode as the control byte ; and address have to be sent only once at the beginning ; of the sequence. ;***************************************************************/ void SPIReadPage24(void) { // FSR punta al buffer static /*overlay*/ byte *p; static /*overlay*/ byte SPICntB; SPISTART_B(CSMemVal); // prepare start SPITXByte(3); // comando ReadBytes (ST-M25P05) SPITXByte(SPIAddr.b[2]); // MSB first SPITXByte(SPIAddr.b[1]); SPITXByte(SPIAddr.b[0]); p=SPIBuffer; for(SPICntB=0; SPICntB<64; SPICntB++) { // set number of bytes to read as 64 *p++=SPIRXByte(); // read 1 byte from device } // are all 64 bytes read? SPISTOP_B(CSMemVal); } /**************************************************************** ; Page Write 24 Routine (64 bytes, address a 24 bit) ; ; This routine uses page mode to write the data in SPIBuffer to ; 64 consecutive bytes in the serial EE device starting ; at SPIAddress . This routine waits 5mS after every ; page to give the device time to do the write. ;*****************************************************************/ void SPIWritePage24(void) { // (FSR usato per buffer) static /*overlay*/ byte SPICntB; byte *p; // SPIWriteWREN ; dev'essere stato eseguito prima! SPISTART_B(CSMemVal); // prepare start SPITXByte(2); // comando PageProgram (ST-M25P05) SPITXByte(SPIAddr.b[2]); // MSB first SPITXByte(SPIAddr.b[1]); SPITXByte(SPIAddr.b[0]); p=SPIBuffer; for(SPICntB=0; SPICntB<64; SPICntB++) { // set number of bytes to read as 64 SPITXByte(*p++); // and transmit it } SPISTOP_B(CSMemVal); // do stop SPIWritePoll(); // movlw 5 // call Delay_mS ; 5mS // return } void SPIWritePoll(void) { /*static*/ /*overlay*/ byte SPIpollcnt; SPIpollcnt=30; // set max number of times to poll as 30 SPISTART_B(CSMemVal); SPITXByte(0x5); // read STATUS su ST-M25P05 do { if(!(SPIRXByte() & 1)) // read STATUS continously break; // was the WIP (WriteInProgress) bit high? Delay_1mS(); // 5mS } while(--SPIpollcnt); // is poll counter down to zero? // no, poll again. Otherwise the part is done SPISTOP_B(CSMemVal); // restituire errore?? } /**************************************************************** ; Byte Write Routine (1 byte, address a 24 bit) ; ; This routine uses page mode to write the data in W to ; the serial EE device starting ; at SPIAddress . This routine waits 5mS after every ; page to give the device time to do the write. ;*****************************************************************/ void SPIWriteByte(byte n) { // SPIWriteWREN ; dev'essere stato eseguito prima! SPISTART_B(CSMemVal); // prepare start SPITXByte(2); // comando PageProgram (ST-M25P05) SPITXByte(SPIAddr.b[2]); // MSB first SPITXByte(SPIAddr.b[1]); SPITXByte(SPIAddr.b[0]); SPITXByte(n); // and transmit it SPISTOP_B(CSMemVal); // do stop SPIWritePoll(); } /**************************************************************** ; Erase Page 24 Routine (64 bytes, address a 24 bit) ; ; This routine cancella un settore di memoria (65536 byte), ; iniziando all'indirizzo a 24 bit dato. ;*****************************************************************/ void SPIMemoryErasePage(void) { SPISTART_B(CSMemVal); // prepare start SPITXByte(0xd8); // Sector Erase su ST-M25P05 SPITXByte(SPIAddr.b[2]); // MSB first SPITXByte(SPIAddr.b[1]); SPITXByte(SPIAddr.b[0]); // si potrebbe mettere 0... SPISTOP_B(CSMemVal); // do stop SPIErasePoll(); } void SPIErasePoll(void) { /*static*/ /*overlay*/ byte SPIpollcnt; SPIpollcnt=250; // set max number of times to poll as 250 (7.5 sec) SPISTART_B(CSMemVal); SPITXByte(0x5); // read STATUS su ST-M25P05 do { if(!(SPIRXByte() & 1)) // read STATUS continously break; // was the WIP (WriteInProgress) bit high? // yes, do another loop Delay_mS(30); // 30mS } while(--SPIpollcnt); // is poll counter down to zero? // no, poll again. Otherwise the part is done SPISTOP_B(CSMemVal); // restituire errore?? } void SPIMemoryWriteWREN(void) { // attiva scrittura (su memoria Flash ST-M25P05) SPISTART_B(CSMemVal); SPITXByte(0x6); SPISTOP_B(CSMemVal); } void SPIMemoryWriteWRDI(void) { // disattiva scrittura (su memoria Flash ST-M25P05) SPISTART_B(CSMemVal); SPITXByte(0x4); SPISTOP_B(CSMemVal); }