/* * main.c * * Created on: Oct 13, 2017 * Author: Taylor */ #include #include #include "xparameters.h" #include "xil_cache.h" #include "xtmrctr.h" #include "xgpio.h" #include "xadcps.h" #include "xil_io.h" XGpio gpio_in; /* XGpio driver instance */ XTmrCtr lfo_timer; /* XTmrCtr driver instance */ XTmrCtr_Config *TimerConPtr; #define PWM_CONFIG ((1<<9) | (1<<2) | (1<<1)) static XAdcPs xadc; /* XADC driver instance */ XAdcPs_Config *ConfigPtr; #define ADC_MAX 65535 #define ADC_VAUX0_OFFSET 0 #define ADC_VAUX1_OFFSET 1 #define ADC_VAUX8_OFFSET 8 #define ADC_VAUX9_OFFSET 9 #define AXI_REG_BASEADDR XPAR_MY_AXI_REG_0_S00_AXI_BASEADDR #define CLOCKS_PER_SEC 100000000 int main() { int Status; u8 gpio_reg; u32 steps_adc_result; u32 rate_adc_result; float rate_calc; float step_calc; s8 direction; u8 mode; u8 steps; u32 rate; u32 timer_reg; u32 control_reg; // Initialize GPIO Status = XGpio_Initialize(&gpio_in, XPAR_AXI_GPIO_0_DEVICE_ID); if (Status != XST_SUCCESS) { return XST_FAILURE; } // Initialize LFO Timers TimerConPtr = XTmrCtr_LookupConfig(XPAR_AXI_TIMER_0_DEVICE_ID); XTmrCtr_CfgInitialize(&lfo_timer, TimerConPtr, TimerConPtr->BaseAddress); timer_reg = XTmrCtr_GetControlStatusReg(TimerConPtr->BaseAddress, 0) | PWM_CONFIG; XTmrCtr_SetControlStatusReg(TimerConPtr->BaseAddress, 0, timer_reg); timer_reg = XTmrCtr_GetControlStatusReg(TimerConPtr->BaseAddress, 1) | PWM_CONFIG; XTmrCtr_SetControlStatusReg(TimerConPtr->BaseAddress, 1, timer_reg); // Set an arbitrary intial value and start timer // Timer 0 sets period // Timer 1 sets high time - should always be half of the Timer 0 value for 50% duty cycle XTmrCtr_SetResetValue(&lfo_timer, 0, 10000000); XTmrCtr_SetResetValue(&lfo_timer, 1, 10000000 / 2); // Start timers XTmrCtr_Start(&lfo_timer, 0); XTmrCtr_Start(&lfo_timer, 1); // Initialize the XAdc driver. ConfigPtr = XAdcPs_LookupConfig(XPAR_XADCPS_0_DEVICE_ID); if (ConfigPtr == NULL) { return XST_FAILURE; } XAdcPs_CfgInitialize(&xadc, ConfigPtr, ConfigPtr->BaseAddress); // ADC Self Test Status = XAdcPs_SelfTest(&xadc); if (Status != XST_SUCCESS) { return XST_FAILURE; } // Set ADC to continuously cycle through the channels XAdcPs_SetSequencerMode(&xadc, XADCPS_SEQ_MODE_CONTINPASS); while(1) { // Read all of the GPIO inputs gpio_reg = XGpio_DiscreteRead(&gpio_in, 1); // Read the Steps control pot steps_adc_result = XAdcPs_GetAdcData(&xadc, XADCPS_CH_AUX_MIN + ADC_VAUX0_OFFSET); // Read the Rate control pot rate_adc_result = XAdcPs_GetAdcData(&xadc, XADCPS_CH_AUX_MIN + ADC_VAUX1_OFFSET); // Direction is connected to a 3 pos switch and is in gpio_reg(7:5) direction = (gpio_reg & (0xE0) >> 5); // Mode is the lower 4 bits of the gpio_reg, can be between 0 and 8 // Modes 4 and 5 are currently unused. mode = gpio_reg & (0x0F); // Convert ADC reading for steps // Quantized to possible values of 1-8 or 1-15 for dual octave modes step_calc = ((float) steps_adc_result / (float) ADC_MAX) * 100; if(mode == 3 || mode == 7) { steps = (u8) ceil(step_calc / 6.25); if(steps > 16) { steps = 15; } } else { steps = (u8) ceil(step_calc / 12.5); } // Convert ADC reading for rate // ADC reading is first converted to a value between 0 and 100 // Scaled for a frequency of about 1-20 Hz rate_calc = ((-7 * 100 * ((float) rate_adc_result / (float) ADC_MAX)) + 750) / 1000; rate = (u32) rate_calc * CLOCKS_PER_SEC; if(mode == 3 || mode == 7) { // For double octave modes, double the frequency rate = rate << 1; } // Write updated rate value into timers // Account for the extra 2 cycles added by the counter XTmrCtr_SetResetValue(&lfo_timer, 0, (rate-2)); XTmrCtr_SetResetValue(&lfo_timer, 1, (rate-2) / 2); // Write rate value into register 0 Xil_Out32(AXI_REG_BASEADDR, rate); // Write control values into register 1 control_reg = (mode << 16) | (direction << 8) | steps; Xil_Out32(AXI_REG_BASEADDR + 1, control_reg); } }