ECE3849/sampling.c
Andy Killorin 6b16664b22 switched to ccs12
implemented pwm and adc to ringbuffer on tirtos
2025-04-10 11:33:10 -04:00

91 lines
3.2 KiB
C

#include <stdint.h>
#include <stdbool.h>
#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 <math.h>
#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);
}