Skip to content

Instantly share code, notes, and snippets.

@terd-ferguson
Created May 29, 2016 21:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save terd-ferguson/27527bd9939bba5f1f2b7a3480c95d07 to your computer and use it in GitHub Desktop.
Save terd-ferguson/27527bd9939bba5f1f2b7a3480c95d07 to your computer and use it in GitHub Desktop.
implements two mcp4921 DACs for dual audio output (TM4C123)
/*
* 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