#include #include #include "inc/tm4c1294ncpdt.h" #include "driverlib/adc.h" #include "driverlib/pin_map.h" #include "driverlib/gpio.h" #include "driverlib/sysctl.h" #include "driverlib/interrupt.h" #include "driverlib/timer.h" #include "sysctl_pll.h" #include "inc/hw_types.h" #include "inc/hw_memmap.h" #include #include "buttons.h" #include "sampling.h" extern uint32_t gSystemClock; // [Hz] system clock frequency // latest sample index void ADC_ISR(void) { // clear ADC1 sequence0 interrupt flag in the ADCISC register //HWREGBITW(ADC1_ISC_R, 1) = 1; ADC1_ISC_R |= 1; // check for ADC FIFO overflow if(ADC1_OSTAT_R & ADC_OSTAT_OV0) { gADCErrors++; // count errors ADC1_OSTAT_R = ADC_OSTAT_OV0; // clear overflow condition } gADCBufferIndex = ADC_BUFFER_WRAP(gADCBufferIndex + 1); // read sample from the ADC1 sequence 0 FIFO gADCBuffer[gADCBufferIndex] = (ADC1_SSFIFO0_R & ADC_SSFIFO0_DATA_M); } void start_sampler() { gADCBufferIndex = ADC_BUFFER_SIZE - 1; gADCErrors = 0; SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_0); // GPIO setup for analog input AIN3 // initialize ADC peripherals SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC1); // timer for low-speed SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2); // ADC clock uint32_t pll_frequency = SysCtlFrequencyGet(CRYSTAL_FREQUENCY); uint32_t pll_divisor = (pll_frequency - 1) / (16 * ADC_SAMPLING_RATE) + 1; // round up ADCClockConfigSet(ADC0_BASE, ADC_CLOCK_SRC_PLL | ADC_CLOCK_RATE_FULL, pll_divisor); ADCClockConfigSet(ADC1_BASE, ADC_CLOCK_SRC_PLL | ADC_CLOCK_RATE_FULL, pll_divisor); // choose ADC1 sequence 0; disable before configuring ADCSequenceDisable(ADC1_BASE, 0); ADCSequenceConfigure(ADC1_BASE, 0, ADC_TRIGGER_ALWAYS, 0); // specify the "Always" trigger // in the 0th step, sample channel 3 (AIN3) // enable interrupt, and make it the end of sequence ADCSequenceStepConfigure(ADC1_BASE, 0, 0, ADC_CTL_CH3 | ADC_CTL_END | ADC_CTL_IE); // enable the sequence. it is now sampling ADCSequenceEnable(ADC1_BASE, 0); // enable sequence 0 interrupt in the ADC1 peripheral ADCIntEnable(ADC1_BASE, 0); // INT_ADC1SS0 } void set_frequency(uint64_t microseconds) { if (microseconds == 1) { ADCSequenceDisable(ADC1_BASE, 0); // don't use a timer for high speed ADCSequenceConfigure(ADC1_BASE, 0, ADC_TRIGGER_ALWAYS, 0); ADCSequenceEnable(ADC1_BASE, 0); return; } // initialize timer 2 in periodic mode TimerDisable(TIMER2_BASE, TIMER_BOTH); TimerConfigure(TIMER2_BASE, TIMER_CFG_PERIODIC); #define MICROSECONDS_PER_SECOND 1000000 TimerLoadSet(TIMER2_BASE, TIMER_A, (uint32_t) ((uint64_t) gSystemClock * microseconds / MICROSECONDS_PER_SECOND) - 1); TimerControlTrigger(TIMER2_BASE, TIMER_A, true); TimerEnable(TIMER2_BASE, TIMER_A); ADCSequenceDisable(ADC1_BASE, 0); ADCSequenceConfigure(ADC1_BASE, 0, ADC_TRIGGER_TIMER, 0); ADCSequenceEnable(ADC1_BASE, 0); }