Created
May 29, 2016 21:34
-
-
Save terd-ferguson/27527bd9939bba5f1f2b7a3480c95d07 to your computer and use it in GitHub Desktop.
implements two mcp4921 DACs for dual audio output (TM4C123)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* spi.c | |
* | |
* Created on: Mar 15, 2016 | |
* Author: joseph | |
*/ | |
#include <stdint.h> // Variable definitions for the C99 standard. | |
#include <stdio.h> // Input and output facilities for the C99 standard. | |
#include <stdlib.h> | |
#include <stdbool.h> // Boolean definitions for the C99 standard. | |
#include <math.h> | |
#include "inc/tm4c123gh6pm.h" // Definitions for the interrupt and register assignments. | |
#include "inc/hw_memmap.h" // Memory map definitions of the Tiva C Series device. | |
#include "inc/hw_types.h" // Definitions of common types and macros. | |
#include "inc/hw_ssi.h" | |
#include "driverlib/sysctl.h" // Definitions and macros for System Control API of DriverLib. | |
#include "driverlib/interrupt.h" // Defines and macros for NVIC Controller API of DriverLib. | |
#include "driverlib/gpio.h" // Definitions and macros for GPIO API of DriverLib. | |
#include "driverlib/timer.h" // Defines and macros for Timer API of DriverLib. | |
#include "driverlib/pin_map.h" //Mapping of peripherals to pins for all parts. | |
#include "driverlib/uart.h" // Definitions and macros for UART API of DriverLib. | |
#include "driverlib/adc.h" // Definitions for ADC API of DriverLib. | |
#include "driverlib/fpu.h" // Prototypes for the FPU manipulation routines. | |
#include "driverlib/ssi.h" // Definitions and prototypes for the SSI/SPI routines. | |
#include "utils/uartstdio.h" // Prototypes for the UART console functions. | |
// Needs to add "utils/uartstdio.c" through a relative link. | |
#define ADC0_SEQ_NUM 0 | |
#define spi_freq 44100 | |
#define CS1 GPIO_PIN_0 | |
#define CS2 GPIO_PIN_1 | |
#define tx1 GPIO_PIN_2 | |
#define tx2 GPIO_PIN_3 | |
#define LDAC GPIO_PIN_4 | |
#define sck GPIO_PIN_5 | |
#define SPI_DATA_MASK 0x0FFF | |
#define SPI_CTRL_MASK 0x7000 | |
uint32_t sys_clock; | |
uint32_t i; | |
uint32_t D[8]; | |
uint16_t data1[16]; | |
uint16_t data2[16]; | |
uint16_t dummy1; | |
uint16_t dummy2; | |
uint16_t bit[16] = { | |
0x0001, | |
0x0002, | |
0x0004, | |
0x0008, | |
0x0010, | |
0x0020, | |
0x0040, | |
0x0080, | |
0x0100, | |
0x0200, | |
0x0400, | |
0x0800, | |
0x1000, | |
0x2000, | |
0x4000, | |
0x8000 | |
}; | |
void timer0_spi(void); | |
void init_pins(void); | |
void init_ADC(void); | |
void init_timers(void); | |
int main(void) | |
{ | |
SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN); | |
sys_clock = 80000000; | |
init_pins(); | |
init_ADC(); | |
init_timers(); | |
timer0_spi(); | |
IntMasterEnable(); | |
TimerEnable(TIMER0_BASE, TIMER_A); | |
} | |
void init_pins(void) | |
{ | |
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); | |
// chip selects, transmit signals, LOAD DAC, sck | |
GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, CS1 | CS2 | tx1 | tx2 | LDAC | sck); | |
//initialize pin values | |
GPIOPinWrite(GPIO_PORTB_BASE, sck, 0); | |
GPIOPinWrite(GPIO_PORTB_BASE, CS1, CS1); | |
GPIOPinWrite(GPIO_PORTB_BASE, CS2, CS2); | |
GPIOPinWrite(GPIO_PORTB_BASE, LDAC, LDAC); | |
GPIOPinWrite(GPIO_PORTB_BASE, tx1, 0); | |
GPIOPinWrite(GPIO_PORTB_BASE, tx2, 0); | |
} | |
void init_timers(void) | |
{ | |
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); | |
TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC); | |
TimerLoadSet(TIMER0_BASE, TIMER_A, sys_clock/spi_freq -1); | |
IntRegister(INT_TIMER0A, timer0_spi); | |
IntEnable(INT_TIMER0A); | |
TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT); | |
} | |
void init_ADC(void) | |
{ | |
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); | |
SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); | |
GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_0); | |
GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_1); | |
ADCSequenceConfigure(ADC0_BASE, ADC0_SEQ_NUM, ADC_TRIGGER_PROCESSOR, 0); | |
ADCSequenceStepConfigure(ADC0_BASE, ADC0_SEQ_NUM, 0, ADC_CTL_CH7); | |
ADCSequenceStepConfigure(ADC0_BASE, ADC0_SEQ_NUM, 1, ADC_CTL_IE | ADC_CTL_END | ADC_CTL_CH6); | |
ADCSequenceEnable(ADC0_BASE, ADC0_SEQ_NUM); | |
} | |
void timer0_spi(void) | |
{ | |
ADCProcessorTrigger(ADC0_BASE, ADC0_SEQ_NUM); | |
while(!ADCIntStatus(ADC0_BASE, ADC0_SEQ_NUM, false)) {} | |
ADCIntClear(ADC0_BASE, ADC0_SEQ_NUM); | |
ADCSequenceDataGet(ADC0_BASE, ADC0_SEQ_NUM, &D); | |
TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT); | |
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
dummy1 = (D[0] & SPI_DATA_MASK) | SPI_CTRL_MASK; | |
dummy2 = (D[1] & SPI_DATA_MASK) | SPI_CTRL_MASK; | |
for(i=0; i<16; i++) | |
{ | |
//create a vector of data from LSB to MSB and move value to ones place | |
data1[i] = (dummy1 & bit[i]) >> i; | |
data2[i] = (dummy2 & bit[i]) >> i; | |
} | |
//set CS1 on | |
GPIOPinWrite(GPIO_PORTB_BASE, CS1, 0); | |
for(i=0; i<16; i++) | |
{ | |
//push data bits to DAC starting with MSB | |
GPIOPinWrite(GPIO_PORTB_BASE, tx1, tx1*data1[15-i]); | |
//sck pulse | |
GPIOPinWrite(GPIO_PORTB_BASE, sck, sck); | |
GPIOPinWrite(GPIO_PORTB_BASE, sck, 0); | |
} | |
//set CS1 off, set CS2 on | |
GPIOPinWrite(GPIO_PORTB_BASE, CS1, CS1); | |
GPIOPinWrite(GPIO_PORTB_BASE, CS2, 0); | |
for(i=0; i<16; i++) | |
{ | |
//push data bits to DAC starting with MSB | |
GPIOPinWrite(GPIO_PORTB_BASE, tx2, tx2*data2[15-i]); | |
//sck pulse | |
GPIOPinWrite(GPIO_PORTB_BASE, sck, sck); | |
GPIOPinWrite(GPIO_PORTB_BASE, sck, 0); | |
} | |
//chip select 2 is off | |
GPIOPinWrite(GPIO_PORTB_BASE, CS2, CS2); | |
//execute both DACs with LDAC | |
GPIOPinWrite(GPIO_PORTB_BASE, LDAC, 0); | |
GPIOPinWrite(GPIO_PORTB_BASE, LDAC, LDAC); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment