10.2 C Source Code

configure.c

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/cpufunc.h>
#include "timer_callback.h"
#include "spi.h"
#include "pins.h"
  
void init_sysclock(void);
void init_tcb0(void);
  
#define PORTB_PIN2CTRL  _SFR_MEM8(0x0432)
  
void initializePeripherals() {
    init_sysclock();	
    init_tcb0();
    init_spi0();    
    
    PORTB_PIN2CTRL |= 0x8;
}
  
void init_sysclock(void)
{
    CPU_CCP = 0xD8;
    CLKCTRL_MCLKCTRLB = 0x00;
}
  
void init_tcb0(void)
{
    TCB0.CTRLA = TCB_CLKSEL_CLKDIV2_gc;  // base clock 16Mhz / 2 = 8 MHz
    TCB0.CTRLB = 0x00;  // all the defaults
    TCB0.CCMP = 7999;  // 8Mhz / 8000 = 1 kHz
    TCB0.INTCTRL = 0x01;  // enable interrupt		
    TCB0.CTRLA |= 0x01;  // enable timer	
}

main.c

/* 
 * File:   main.c
 */
  
#include <stdio.h>
#include <stdlib.h>
#include "configure.h"
#include <avr/interrupt.h>
  
int main(int argc, char** argv)
{
    initializePeripherals();
    sei(); //set global interrupt flag
    
    while(1) ;
}

sine_app.c

/* 
* There are two waveforms in this application:
* 1. sine wave
* 2. triangle wave
* 
* There are two global variables for control in this application:
*  - amp_factor - this defines the amplitude of the waveform 
*  - wave_select - this defines the waveform selection. 
*    It can either be 0 for sine or 1 for triangle.
*/
  
#include <stdio.h>
  
#include "timer_callback.h"
#include "spi.h"
#include "memutil.h"
  
int amp_factor = 1;
int wave_select = 0;
int counter = 0;
  
int sine[] = {
    0x2b,0x2d,0x30,0x32,0x35,0x38,0x3a,0x3d,
    0x3f,0x41,0x43,0x46,0x48,0x49,0x4b,0x4d,
    0x4e,0x50,0x51,0x52,0x53,0x54,0x54,0x55,
    0x55,0x55,0x55,0x55,0x54,0x54,0x53,0x52,
    0x51,0x50,0x4e,0x4d,0x4b,0x49,0x48,0x46,
    0x43,0x41,0x3f,0x3d,0x3a,0x38,0x35,0x32,
    0x30,0x2d,0x2b,0x28,0x25,0x23,0x20,0x1d,
    0x1b,0x18,0x16,0x14,0x12,0xf,0xd,0xc,
    0xa,0x8,0x7,0x5,0x4,0x3,0x2,0x1,
    0x1,0x0,0x0,0x0,0x0,0x0,0x1,0x1,
    0x2,0x3,0x4,0x5,0x7,0x8,0xa,0xc,
    0xd,0xf,0x12,0x14,0x16,0x18,0x1b,0x1d,
    0x20,0x23,0x25,0x28,0x2b
};
  
int tri_1k[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
  
struct
{
    int cnt;
    int *amp;
} waveform[] =
{
    {LEN(sine), sine},
    {LEN(tri_1k), tri_1k}
};
  
void timer_callback()
{
    uint8_t sample = (amp_factor * waveform[wave_select].amp[counter]) & 0x7F;
    if (++counter >= waveform[wave_select].cnt) {
        counter = 0;
    }
    
    select_dgi_spi();
    tx_spi0(0x03);
    tx_spi0(sample);
    tx_spi0(0xFC);
    deselect_dgi_spi();
}

spi.c

#include <avr/io.h>
#include "spi.h"
#include "pins.h"
  
void init_spi0(void)
{
    VPORTA.DIR |= (1 << MOSI_PIN) | (1 << SCK_PIN);
    VPORTF.DIR |= (1 << CS_PIN);
    	
    SPI0.CTRLA = 0 << SPI_CLK2X_bp | 0 << SPI_DORD_bp | 1 << SPI_MASTER_bp | SPI_PRESC_DIV64_gc; 
    SPI0.CTRLB = (1 << SPI_SSD_bp);  // disable SS#
    SPI0.CTRLA |=  1 << SPI_ENABLE_bp;
}
  
void select_dgi_spi(void)
{
    VPORTF.OUT &= ~(1 << CS_PIN);
}
  
void deselect_dgi_spi(void)
{
    VPORTF.OUT |= (1 << CS_PIN);
}
  
void tx_spi0(uint8_t tx_byte)
{
    uint8_t tx_rdy = 0;
    
    SPI0.DATA = tx_byte;
    while(!tx_rdy)
        tx_rdy = (SPI0.INTFLAGS & SPI_IF_bm );	
}
  
void tx_string_spi0(char* tx_string)
{
    while (*tx_string)
        tx_spi0(*(tx_string++));
}
  
void tx_data_spi0(uint8_t tx_byte[], int length)
{
    while (length--)
        tx_spi0(*(tx_byte++));
}

timer_loop.c

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/cpufunc.h>
#include "timer_callback.h"
  
unsigned char period = 1;
unsigned char tick = 0; 
  
ISR(TCB0_INT_vect)
{
    TCB0.INTFLAGS = 0x01;
    
    if (++tick > period) {
        tick = 0;
        timer_callback();
    }
}