/** \brief End of Conversion interrupt handler. * * This function starts an SPI transfer with the ADC in order to retrieve the * conversion result, using the SPI driver library's * SPI_MasterInterruptTransceivePacket(). * * \note This function should be called from the ISR registered to trigger on * the falling edge of EOC, using INT0 of the port associated with the ADC, as * described in this file's documentation. * * \note Due to an unknown bug, care must be taken that this function is * <em>never</em> called while there is an ongoing SPI communication with the * ADC. * * \param[in] adc The ADC which has signalled EOC */ void ADC_EOC_interrupt_handler(ADC_ext_t *adc) { uint8_t status; /* due to an unknown bug, this is not being set properly by the SPI library. * This fix is a hack, and relies on the fact that this function will only be * called while there is not an ongoing transfer. */ adc->SPI_master->dataPacket->complete = true; /* initiate a data transfer to get the conversion result */ do { status = SPI_MasterInterruptTransceivePacket(adc->SPI_master, adc->data_packet); } while (status != SPI_OK); }
/*! \brief Test function. * * This function tests the SPI master and slave drivers in interrupt-driven * operation, with a master (on port C) communicating with a slave (on port D). * * Hardware setup: * * - Connect PC4 to PD4 (SS) * - Connect PC5 to PD5 (MOSI) * - Connect PC6 to PD6 (MISO) * - Connect PC7 to PD7 (SCK) * * The driver is tested by transmitting data from the master to the slave. * The slave increments the received data and sends it back. The master reads * the data from the slave and verifies that it equals the data sent + 1. * * The first data transaction is initiated by the main routine. When a * transaction has finished, an interrupt will be triggered which will start * new transactions until all bytes have been transceived. * * The variable, 'success', will be non-zero when the function reaches the * infinite for-loop if the test was successful. * * \note This example uses multilevel interrupts. For more information on how * to use the interrupt controller, refer to application note AVR1305. */ int main( void ) { /* Init SS pin as output with wired AND and pull-up. */ PORTC.DIRSET = PIN4_bm; PORTC.PIN4CTRL = PORT_OPC_WIREDANDPULL_gc; /* Set SS output to high. (No slave addressed). */ PORTC.OUTSET = PIN4_bm; /* Initialize SPI master on port C. */ SPI_MasterInit(&spiMasterC, &SPIC, &PORTC, false, SPI_MODE_0_gc, SPI_INTLVL_LO_gc, false, SPI_PRESCALER_DIV4_gc); /* Initialize SPI slave on port D. */ SPI_SlaveInit(&spiSlaveD, &SPID, &PORTD, false, SPI_MODE_0_gc, SPI_INTLVL_MED_gc); /* Enable low and medium level interrupts in the interrupt controller. */ PMIC.CTRL |= PMIC_MEDLVLEN_bm | PMIC_LOLVLEN_bm; sei(); /* Create data packet (SS to slave by PC4) */ SPI_MasterCreateDataPacket(&dataPacket, sendData, receivedData, NUM_BYTES + 1, &PORTC, PIN4_bm); /* Transmit and receive first data byte. */ uint8_t status; do { status = SPI_MasterInterruptTransceivePacket(&spiMasterC, &dataPacket); } while (status != SPI_OK); /* Wait for transmission to complete. */ while (dataPacket.complete == false) { } /* Check that correct data was received. Assume success at first. */ success = true; for (uint8_t i = 0; i < NUM_BYTES; i++) { if (receivedData[i + 1] != (uint8_t)(sendData[i] + 1)) { success = false; } } while(true) { nop(); } }