Exemple #1
0
//------------------------------------------------------------------------------
/// Initializes the Spid structure and the corresponding SPI hardware.
/// Always returns 0.
/// \param pSpid  Pointer to a Spid instance.
/// \param pSpiHw  Associated SPI peripheral.
/// \param spiId  SPI peripheral identifier.
//------------------------------------------------------------------------------
unsigned char SPID_Configure(Spid *pSpid, AT91S_SPI *pSpiHw,
							 unsigned char spiId)
{
	// Initialize the SPI structure
	pSpid->pSpiHw = pSpiHw;
	pSpid->spiId  = spiId;
	pSpid->semaphore = 1;
	pSpid->pCurrentCommand = 0;

	// Enable the SPI clock
	WRITE_PMC(AT91C_BASE_PMC, PMC_PCER, (1 << pSpid->spiId));

	// Execute a software reset of the SPI twice
	WRITE_SPI(pSpiHw, SPI_CR, AT91C_SPI_SWRST);
	WRITE_SPI(pSpiHw, SPI_CR, AT91C_SPI_SWRST);

	// Configure SPI in Master Mode with No CS selected !!!
	WRITE_SPI(pSpiHw, SPI_MR, AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | AT91C_SPI_PCS);

	// Disable the PDC transfer
	WRITE_SPI(pSpiHw, SPI_PTCR, AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS);

	// Enable the SPI
	WRITE_SPI(pSpiHw, SPI_CR, AT91C_SPI_SPIEN);

	// Enable the SPI clock
	WRITE_PMC(AT91C_BASE_PMC, PMC_PCDR, (1 << pSpid->spiId));

	return 0;
}
Exemple #2
0
//------------------------------------------------------------------------------
//./ Initializes the Spid structure and the corresponding SPI & DMA hardware.
//./ The driver will uses DMA channel 0 for RX and DMA channel 1 for TX.
//./ The DMA channels are freed automatically when no SPI command processing.
//./ \param pSpid  Pointer to a Spid instance.
//./ \param pSpiHw  Associated SPI peripheral.
//./ \param spiId  SPI peripheral identifier.
//./ \return Always 0.
//------------------------------------------------------------------------------
//unsigned char SPI_D_Configure(SpiD *pSpiD, AT91S_SPI *pSpiHw, unsigned char spiId)
unsigned char SPI_D_Configure(SpiD *pSpiD, AT91S_SPI *pSpiHw, unsigned char spiId)
{
    // Initialize the SPI structure
    pSpiD->pSpiHw = pSpiHw;
    pSpiD->spiId  = spiId;
    pSpiD->semaphore = 1;
    pSpiD->pCurrentCommand = 0;

    // Enable the SPI Peripheral
    PERIPH_ENABLE(pSpiD->spiId);
    
    // Execute a software reset of the SPI twice
    WRITE_SPI(pSpiHw, SPI_CR, AT91C_SPI_SWRST);
    WRITE_SPI(pSpiHw, SPI_CR, AT91C_SPI_SWRST);

    // Configure SPI in Master Mode with No CS selected !!!
    WRITE_SPI(pSpiHw, SPI_MR, AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | AT91C_SPI_PCS);
     
    // Disable the PDC transfer
  #if !defined(at91sam3u)
    WRITE_SPI(pSpiHw, SPI_PTCR, AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS);
  #endif

    // Disable the SPI TX & RX
    WRITE_SPI(pSpiHw, SPI_CR, AT91C_SPI_SPIDIS);

    // Disable the SPI Peripheral
    PERIPH_DISABLE(pSpiD->spiId);

    return 0;
}
Exemple #3
0
//------------------------------------------------------------------------------
/// The SPI_Handler must be called by the SPI Interrupt Service Routine with the
/// corresponding Spi instance.
/// The SPI_Handler will unlock the Spi semaphore and invoke the upper application
/// callback.
/// \param pSpid  Pointer to a Spid instance.
//------------------------------------------------------------------------------
void SPID_Handler(Spid *pSpid)
{
	SpidCmd *pSpidCmd = pSpid->pCurrentCommand;
	AT91S_SPI *pSpiHw = pSpid->pSpiHw;
	volatile unsigned int spiSr;

	// Read the status register
	spiSr = READ_SPI(pSpiHw, SPI_SR);

	if (spiSr & AT91C_SPI_RXBUFF) {
		// Disable transmitter and receiver
		WRITE_SPI(pSpiHw, SPI_PTCR, AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS);

		// Disable the SPI clock
		WRITE_PMC(AT91C_BASE_PMC, PMC_PCDR, (1 << pSpid->spiId));

		// Disable buffer complete interrupt
		WRITE_SPI(pSpiHw, SPI_IDR, AT91C_SPI_RXBUFF);

		// Release the dataflash semaphore
		pSpid->semaphore++;

		// Invoke the callback associated with the current command
		if (pSpidCmd && pSpidCmd->callback)

			pSpidCmd->callback(0, pSpidCmd->pArgument);

		// Nothing must be done after. A new DF operation may have been started
		// in the callback function.
	}
}
Exemple #4
0
//------------------------------------------------------------------------------
/// SPI DMA transfer ISR, Handle RX complete
//------------------------------------------------------------------------------
void SPI_D_Handler(SpiD *pSpiD)
{
    unsigned int dmaStatus;
    SpiDCmd *pSpiDCmd = pSpiD->pCurrentCommand;
    AT91S_SPI *pSpiHw = pSpiD->pSpiHw;

    dmaStatus = DMA_GetStatus();

    if ((dmaStatus & AT91C_CBTC) == 0)
        return;

    if ((dmaStatus & (DMA_CBTC << DMA_CHANNEL_0)) == 0)
        return;

    // Disable the SPI TX & RX
    WRITE_SPI(pSpiHw, SPI_CR, AT91C_SPI_SPIDIS);
    // Disable the SPI Peripheral
    PERIPH_DISABLE(pSpiD->spiId);

    // Disable DMA
    DMA_Disable();
    // Disable DMA Peripheral
    PERIPH_DISABLE(AT91C_ID_HDMA);
    
    // Release the dataflash semaphore
    pSpiD->semaphore++;
        
    // Invoke the callback associated with the current command
    if (pSpiDCmd && pSpiDCmd->callback) {
    
        pSpiDCmd->callback(0, pSpiDCmd->pArgument);
    }
        
}
Exemple #5
0
//------------------------------------------------------------------------------
//./ Starts a SPI master transfer. This is a non blocking function. It will
//./ return as soon as the transfer is started.
//./ Returns 0 if the transfer has been started successfully; otherwise returns
//./ SPID_ERROR_LOCK is the driver is in use, or SPID_ERROR if the command is not
//./ valid.
//./ \param pSpid  Pointer to a Spid instance.
//./ \param pCommand Pointer to the SPI command to execute.
//------------------------------------------------------------------------------
unsigned char SPI_D_SendCommand(SpiD *pSpiD, SpiDCmd *pCommand)
{
    AT91S_SPI *pSpiHw = pSpiD->pSpiHw;
     unsigned int spiMr;
         
     // Try to get the dataflash semaphore
     if (pSpiD->semaphore == 0) {
    
         return SPI_D_ERROR_LOCK;
    }
     pSpiD->semaphore--;

    // Enable the SPI Peripheral
    PERIPH_ENABLE(pSpiD->spiId);
    
    // Disable PDC transmitter and receiver
  #if !defined(at91sam3u)
    WRITE_SPI(pSpiHw, SPI_PTCR, AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS);
  #endif

    // Write to the MR register
    spiMr = READ_SPI(pSpiHw, SPI_MR);
    spiMr |= AT91C_SPI_PCS;
    spiMr &= ~((1 << pCommand->spiCs) << 16);
    WRITE_SPI(pSpiHw, SPI_MR, spiMr);

    // Initialize DMA controller using channel 0 for RX, 1 for TX.
    configureDmaChannels();
    configureLinkList(pSpiHw, pCommand);

    // Initialize the callback
    pSpiD->pCurrentCommand = pCommand;
    
    // Enable the SPI TX & RX
    WRITE_SPI(pSpiHw, SPI_CR, AT91C_SPI_SPIEN);

    // Start DMA 0(RX) && 1(TX)
    DMA_EnableChannels((1 << DMA_CHANNEL_0) | (1 << DMA_CHANNEL_1));

    // Enable DMA Interrupts
    DMA_EnableIt(  (DMA_CBTC << DMA_CHANNEL_0)
                 | (DMA_CBTC << DMA_CHANNEL_1));

    return 0;    
}
Exemple #6
0
//------------------------------------------------------------------------------
//./ Configures the parameters for the device corresponding to the cs.
//./ \param pSpid  Pointer to a Spid instance.
//./ \param cs  number corresponding to the SPI chip select.
//./ \param csr  SPI_CSR value to setup.
//------------------------------------------------------------------------------
void SPI_D_ConfigureCS(SpiD *pSpiD, unsigned char cs, unsigned int csr)
{
    AT91S_SPI *pSpiHw = pSpiD->pSpiHw;

    // Enable the SPI Peripheral
    PERIPH_ENABLE(pSpiD->spiId);

    // Write CS
    WRITE_SPI(pSpiHw, SPI_CSR[cs], csr);

    // Disable the SPI Peripheral
    PERIPH_DISABLE(pSpiD->spiId);
}
Exemple #7
0
//------------------------------------------------------------------------------
/// Configures the parameters for the device corresponding to the cs.
/// \param pSpid  Pointer to a Spid instance.
/// \param cs  number corresponding to the SPI chip select.
/// \param csr  SPI_CSR value to setup.
//------------------------------------------------------------------------------
void SPID_ConfigureCS(Spid *pSpid, unsigned char cs, unsigned int csr)
{
	AT91S_SPI *pSpiHw = pSpid->pSpiHw;
	WRITE_SPI(pSpiHw, SPI_CSR[cs], csr);
}
Exemple #8
0
//------------------------------------------------------------------------------
/// Starts a SPI master transfer. This is a non blocking function. It will
/// return as soon as the transfer is started.
/// Returns 0 if the transfer has been started successfully; otherwise returns
/// SPID_ERROR_LOCK is the driver is in use, or SPID_ERROR if the command is not
/// valid.
/// \param pSpid  Pointer to a Spid instance.
/// \param pCommand Pointer to the SPI command to execute.
//------------------------------------------------------------------------------
unsigned char SPID_SendCommand(Spid *pSpid, SpidCmd *pCommand)
{
	AT91S_SPI *pSpiHw = pSpid->pSpiHw;
	unsigned int spiMr;

	// Try to get the dataflash semaphore
	if (pSpid->semaphore == 0)

		return SPID_ERROR_LOCK;

	pSpid->semaphore--;

	// Enable the SPI clock
	WRITE_PMC(AT91C_BASE_PMC, PMC_PCER, (1 << pSpid->spiId));

	// Disable transmitter and receiver
	WRITE_SPI(pSpiHw, SPI_PTCR, AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS);

	// Write to the MR register
	spiMr = READ_SPI(pSpiHw, SPI_MR);
	spiMr |= AT91C_SPI_PCS;
	spiMr &= ~((1 << pCommand->spiCs) << 16);
	WRITE_SPI(pSpiHw, SPI_MR, spiMr);

	// Initialize the two SPI PDC buffer
	WRITE_SPI(pSpiHw, SPI_RPR, (int) pCommand->pCmd);
	WRITE_SPI(pSpiHw, SPI_RCR, pCommand->cmdSize);
	WRITE_SPI(pSpiHw, SPI_TPR, (int) pCommand->pCmd);
	WRITE_SPI(pSpiHw, SPI_TCR, pCommand->cmdSize);

	WRITE_SPI(pSpiHw, SPI_RNPR, (int) pCommand->pData);
	WRITE_SPI(pSpiHw, SPI_RNCR, pCommand->dataSize);
	WRITE_SPI(pSpiHw, SPI_TNPR, (int) pCommand->pData);
	WRITE_SPI(pSpiHw, SPI_TNCR, pCommand->dataSize);

	// Initialize the callback
	pSpid->pCurrentCommand = pCommand;

	// Enable transmitter and receiver
	WRITE_SPI(pSpiHw, SPI_PTCR, AT91C_PDC_RXTEN | AT91C_PDC_TXTEN);

	// Enable buffer complete interrupt
	WRITE_SPI(pSpiHw, SPI_IER, AT91C_SPI_RXBUFF);

	return 0;
}
/***************************************************************************
Declaration : void get_audio_packet(void)

Description : 
***************************************************************************/
void get_audio_packet(void)
{
int audio_sample;
volatile char status;
char audio_byte;
int i;

	ENABLE_RF_SPI;
	read_rf_byte(R_RX_PAYLOAD);
	signal_in[0] = read_rf_byte(R_RX_PAYLOAD);
	signal_in[1] = read_rf_byte(R_RX_PAYLOAD);
	WRITE_SPI(R_RX_PAYLOAD);
	WAIT_SPI_READY;

	for(i=0; i< AUDIO_SAMPLES; i++)
	{
		// Get audio byte in nRF24L01 FIFO
		READ_SPI(audio_byte);
		WRITE_SPI(R_RX_PAYLOAD);
		
		// Expand audio to 16-bit
		audio_sample = expand_audio(audio_byte);
		
		*output_write_ptr++ = (char)(audio_sample >> 8);
		*output_write_ptr++ = (char)(audio_sample);
		#ifndef USB
		*output_write_ptr++ = 0;
		*output_write_ptr++ = 0;
		#endif
		if(output_write_ptr >= &output[AUDIO_BUFFER_LENGTH])
			output_write_ptr = &output[0];
	}
	
	if(!(protocol_flags & FLAG_BUFFER_SYNC2))
	{
		output_write_ptr = (char *)((unsigned int)output_read_ptr + 0xFFFC);
		output_write_ptr -= 40;
		if(output_write_ptr < &output[0])
			output_write_ptr += AUDIO_BUFFER_LENGTH;
		protocol_flags |= FLAG_BUFFER_SYNC2;
	}
	
	#ifdef HEADSET
	// Handle slip due to clock differences
	i = (int)output_read_ptr - (int)output_write_ptr;
	if(i < 0)
		i += AUDIO_BUFFER_LENGTH;
	if(i < 20)
	{
		#ifdef USB
		output_write_ptr -= 2;
		#else
		output_write_ptr -= 4;
		#endif
		if(output_write_ptr < &output[0])
			output_write_ptr = &output[AUDIO_BUFFER_LENGTH-1];
	}
	if(i > 60)
	{
		#ifdef USB
		output_write_ptr -= 2;
		#else
		output_write_ptr -= 4;
		#endif
		if(output_write_ptr >= &output[AUDIO_BUFFER_LENGTH])
			output_write_ptr = &output[0];
	}
	#endif
		
	READ_SPI_STATUS(status);
	READ_SPI(audio_byte);
	DISABLE_RF_SPI;
}
/***************************************************************************
Declaration : void put_audio_packet(void)

Description : 
***************************************************************************/
void put_audio_packet(void)
{
int audio_sample,abs_audio;
volatile char status;
char audio_byte;
int i;
	
	// Put RF Payload
	ENABLE_RF_SPI;
	write_rf_byte(W_TX_PAYLOAD);
	
	// Put Signalling bytes
	write_rf_byte(signal_out[0]);
	write_rf_byte(signal_out[1]);
	
	// Put audio bytes
	for(i=0; i< AUDIO_SAMPLES; i++)
	{
		// Read 16bit audio sample from input buffer
		audio_sample = (unsigned int)(*input_read_ptr++) << 8;
		audio_sample += (unsigned int)*input_read_ptr++;
		#ifndef USB
		input_read_ptr += 2;
		#endif
		if(input_read_ptr >= &input[AUDIO_BUFFER_LENGTH])
			input_read_ptr = &input[0];
		
		// Compress 16bit --> 12bit --> 8bit
		if(audio_sample < 0)
			abs_audio = -audio_sample;
		else
			abs_audio = audio_sample;
		audio_byte = pgm_read_byte(&Alaw_compress[(abs_audio >> 4) & 0x7FF]);
		if(audio_sample < 0)
			audio_byte |= 0x80;
		
		// Put audio byte in nRF24L01 FIFO
		READ_SPI_STATUS(status);
		WRITE_SPI(audio_byte);
	}
	
	if(!(protocol_flags & FLAG_BUFFER_SYNC1))
	{
		input_read_ptr = (char *)((unsigned int)input_write_ptr & 0xFFFC);
		input_read_ptr -= 40;
		if(input_read_ptr < &input[0])
			input_read_ptr += AUDIO_BUFFER_LENGTH;
		protocol_flags |= FLAG_BUFFER_SYNC1;
	}
	
	#ifdef HEADSET
	// Handle slip due to clock differences
	i = (int)input_write_ptr - (int)input_read_ptr;
	if(i < 0)
		i += AUDIO_BUFFER_LENGTH;
	if(i < 20)
	{
		#ifdef USB
		input_read_ptr -= 2;
		#else
		input_read_ptr -= 4;
		#endif
		if(input_read_ptr < &input[0])
			input_read_ptr = &input[AUDIO_BUFFER_LENGTH-1];
	}
	if(i > 60)
	{
		#ifdef USB
		input_read_ptr -= 2;
		#else
		input_read_ptr -= 4;
		#endif
		if(input_read_ptr >= &input[AUDIO_BUFFER_LENGTH])
			input_read_ptr = &input[0];
	}
	#endif

	WAIT_SPI_READY;
	DISABLE_RF_SPI;
}