Hi all,
I am trying to use the TM4C123G LaunchPad as an oscilloscope which communicates with an application on host-side. To be able to measure different voltage ranges we developed a BoosterPack which allows us this. Before sending the measured data via USB I need to prepare them, as there are some communication regulations on the host-side.
My goal is to reach a samplerate of at least 500kHz of one channel using ADC0. I configured a DMA-Channel in Ping-Pong-Mode to sample continously ADC-data. The time needed to prepare the data is about one 1/4 of the time elapsed between two ADC interrupts. The time left should (theoretically) be big enough to get rid of the prepared data (based on a transmission rate of 12bit*500000kHz).
I created a custom USB-bulk-device based on some parts of the TivaWare usb bulk driver (usbdbulk.c/.h). The USB_EP_AUTO_SET bit is not enabled for the endpoint which I am sending the prepared data over. So I am putting the data with USBEndpointDataPut to the specified FIFO and then sending it with USBEndpointDataSend to the Host. My problem is that I am not able to reach a samplerate which is enough for my needs. I am getting pleasing results if I set the ADC-samplerate down to 31,25kHz by enabling 32 times hardware oversampling. With samplerates above this the errorcounter in the send_packet function is increasing rapidly. So my question is if there is a better way to send data than the way I am doing it right now (see code example below)?
Thanks a lot in advance for your help! If you need more information please let me know.
Regards,
Felix
void
ADC0IntHandler(void)
{
//
// Clear the ADC interrupt
//
MAP_ADCIntClear(ADC0_BASE, 0);
if(g_OsziRun)
{
if(!MAP_uDMAChannelSizeGet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT))
{
// g_ulAdcBuf_ping is ready for processing
// rewrite channel configuration for next transfer
// toggle Pin PA4
g_ulBadPeriphIsr1++;
ui8Oszi_state = PING_DONE;
MAP_GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_4, GPIO_PIN_4); // debug purposes
MAP_uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT,
UDMA_MODE_PINGPONG,
(void *)(ADC0_BASE + ADC_O_SSFIFO0 + (0x20 * 0)),
g_ulAdc0Buf_ping, ADC0_DSTBUF_SIZE);
MAP_uDMAChannelEnable(UDMA_CHANNEL_ADC0);
MAP_GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_7, GPIO_PIN_7); // debug purposes
create_oszi_packet(g_ui8ADCModules, PING_DONE);
MAP_GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_7, 0); // debug purposes
MAP_GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0, GPIO_PIN_0);
send_packet(PING_DONE);
MAP_GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0, 0);
}
else if(!MAP_uDMAChannelSizeGet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT))
{
// g_ulAdcBuf_pong is ready for processing
// rewrite channel configuration for next transfer
// toggle Pin PA4
g_ulBadPeriphIsr2++;
ui8Oszi_state = PONG_DONE;
MAP_GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_4, 0); // debug purposes
MAP_uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT,
UDMA_MODE_PINGPONG,
(void *)(ADC0_BASE + ADC_O_SSFIFO0 + (0x20 * 0)),
g_ulAdc0Buf_pong, ADC0_DSTBUF_SIZE);
MAP_uDMAChannelEnable(UDMA_CHANNEL_ADC0);
//MAP_GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_7, GPIO_PIN_7); // debug purposes
create_oszi_packet(g_ui8ADCModules, PONG_DONE);
send_packet(PONG_DONE);
//MAP_GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_7, 0);
}
else
{
// normal ADC interrupt, not uDMA interrupt / what???
g_ulIntOsziCount++;
}
}
}
void send_packet(uint8_t ui8PingPong)
{
static uint32_t routine_count, packet_sent, errorcounter;
uint8_t buffer_mode = ui8PingPong;
uint8_t *pData;
int32_t i32Retcode;
uint32_t ui32EPStatus;
routine_count++;
pData = (uint8_t *)&packet_one;
i32Retcode = MAP_USBEndpointDataPut(USB0_BASE, USB_EP_4, pData, 63);
ui32EPStatus = MAP_USBEndpointStatus(USB0_BASE, USB_EP_4);
if(i32Retcode != -1)
{
i32Retcode = MAP_USBEndpointDataSend(USB0_BASE, USB_EP_4, USB_TRANS_IN);
packet_sent++;
}
else
{
errorcounter++;
}
}
