Top Banner
LCD.H /* * 16x2 LCD Driver Header File for STM32F4 Discovery * Andrew Kozik Embedded Systems Project 2015 (UCT) */ #ifndef __LCD_H #define __LCD_H #include "stm32f4xx.h" #define LCD_CTRL_EN_PIN GPIO_Pin_4 #define LCD_CTRL_EN_GPIO_PORT GPIOE #define LCD_CTRL_EN_GPIO_CLK RCC_AHB1Periph_GPIOE #define LCD_CTRL_EN_SOURCE GPIO_PinSource15 #define LCD_CTRL_RS_PIN GPIO_Pin_2 #define LCD_CTRL_RS_GPIO_PORT GPIOE #define LCD_CTRL_RS_GPIO_CLK RCC_AHB1Periph_GPIOE #define LCD_CTRL_RS_SOURCE GPIO_PinSource14 #define LCD_CTRL_D4_PIN GPIO_Pin_10 #define LCD_CTRL_D4_GPIO_PORT GPIOE #define LCD_CTRL_D4_GPIO_CLK RCC_AHB1Periph_GPIOE #define LCD_CTRL_D4_SOURCE GPIO_PinSource8 #define LCD_CTRL_D5_PIN GPIO_Pin_11 #define LCD_CTRL_D5_GPIO_PORT GPIOE #define LCD_CTRL_D5_GPIO_CLK RCC_AHB1Periph_GPIOE #define LCD_CTRL_D5_SOURCE GPIO_PinSource9 #define LCD_CTRL_D6_PIN GPIO_Pin_12 #define LCD_CTRL_D6_GPIO_PORT GPIOE #define LCD_CTRL_D6_GPIO_CLK RCC_AHB1Periph_GPIOE #define LCD_CTRL_D6_SOURCE GPIO_PinSource12 #define LCD_CTRL_D7_PIN GPIO_Pin_13 #define LCD_CTRL_D7_GPIO_PORT GPIOE #define LCD_CTRL_D7_GPIO_CLK RCC_AHB1Periph_GPIOE #define LCD_CTRL_D7_SOURCE GPIO_PinSource15 #define LCD_LINE_LENGTH (uint8_t)16 #define LCD_LINE_TWO_ADDR (uint8_t)64 #define LCD_EN_LOW() GPIO_ResetBits(LCD_CTRL_EN_GPIO_PORT, LCD_CTRL_EN_PIN) #define LCD_EN_HIGH() GPIO_SetBits(LCD_CTRL_EN_GPIO_PORT, LCD_CTRL_EN_PIN) #define LCD_RS_LOW() GPIO_ResetBits(LCD_CTRL_RS_GPIO_PORT, LCD_CTRL_RS_PIN) #define LCD_RS_HIGH() GPIO_SetBits(LCD_CTRL_RS_GPIO_PORT, LCD_CTRL_RS_PIN) #define LCD_RS(x) GPIO_WriteBit(LCD_CTRL_RS_GPIO_PORT, LCD_CTRL_RS_PIN, x) #define LCD_EN(x) GPIO_WriteBit(LCD_CTRL_EN_GPIO_PORT, LCD_CTRL_EN_PIN, x) #define GET_BIT(a, b) ((a >> b) & 1) /* Delay required by HD44780 */ #ifdef LCD_DELAY_EXTERN extern void DelayMs(uint32_t); #else extern void DelayMs2(uint32_t); #endif /* LCD_Constants */ #define LCD_DataLength_4Bit (uint8_t)0 #define LCD_LineNumber_1Line (uint8_t)0 #define LCD_LineNumber_2Lines (uint8_t)8 #define LCD_CharacterFont_5x8Dots (uint8_t)0 #define LCD_CharacterFont_5x10Dots (uint8_t)4 #define LCD_CursorDirection_Decrement (uint8_t)0 #define LCD_CursorDirection_Increment (uint8_t)2 #define LCD_DisplayShift_NoShift (uint8_t)0 #define LCD_DisplayShift_Shift (uint8_t)1 #define LCD_DisplayState_On (uint8_t)4 #define LCD_DisplayState_Off (uint8_t)0 #define LCD_CursorState_On (uint8_t)2 #define LCD_CursorState_Off (uint8_t)0 #define LCD_BlinkCursor_On (uint8_t)1 #define LCD_BlinkCursor_Off (uint8_t)0 #define LCD_MoveOrShift_MoveCursor (uint8_t)0 #define LCD_MoveOrShift_ShiftDisplay (uint8_t)8 #define LCD_ShiftDirection_Left (uint8_t)0 #define LCD_ShiftDirection_Right (uint8_t)4 /* LCD Commands */
19

Embedded Systems Project 3rd Year

Jan 15, 2017

Download

Documents

Andrew Kozik
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Embedded Systems Project 3rd Year

LCD.H

/*

* 16x2 LCD Driver Header File for STM32F4 Discovery

* Andrew Kozik Embedded Systems Project 2015 (UCT)

*/

#ifndef __LCD_H

#define __LCD_H

#include "stm32f4xx.h"

#define LCD_CTRL_EN_PIN GPIO_Pin_4

#define LCD_CTRL_EN_GPIO_PORT GPIOE

#define LCD_CTRL_EN_GPIO_CLK RCC_AHB1Periph_GPIOE

#define LCD_CTRL_EN_SOURCE GPIO_PinSource15

#define LCD_CTRL_RS_PIN GPIO_Pin_2

#define LCD_CTRL_RS_GPIO_PORT GPIOE

#define LCD_CTRL_RS_GPIO_CLK RCC_AHB1Periph_GPIOE

#define LCD_CTRL_RS_SOURCE GPIO_PinSource14

#define LCD_CTRL_D4_PIN GPIO_Pin_10

#define LCD_CTRL_D4_GPIO_PORT GPIOE

#define LCD_CTRL_D4_GPIO_CLK RCC_AHB1Periph_GPIOE

#define LCD_CTRL_D4_SOURCE GPIO_PinSource8

#define LCD_CTRL_D5_PIN GPIO_Pin_11

#define LCD_CTRL_D5_GPIO_PORT GPIOE

#define LCD_CTRL_D5_GPIO_CLK RCC_AHB1Periph_GPIOE

#define LCD_CTRL_D5_SOURCE GPIO_PinSource9

#define LCD_CTRL_D6_PIN GPIO_Pin_12

#define LCD_CTRL_D6_GPIO_PORT GPIOE

#define LCD_CTRL_D6_GPIO_CLK RCC_AHB1Periph_GPIOE

#define LCD_CTRL_D6_SOURCE GPIO_PinSource12

#define LCD_CTRL_D7_PIN GPIO_Pin_13

#define LCD_CTRL_D7_GPIO_PORT GPIOE

#define LCD_CTRL_D7_GPIO_CLK RCC_AHB1Periph_GPIOE

#define LCD_CTRL_D7_SOURCE GPIO_PinSource15

#define LCD_LINE_LENGTH (uint8_t)16

#define LCD_LINE_TWO_ADDR (uint8_t)64

#define LCD_EN_LOW() GPIO_ResetBits(LCD_CTRL_EN_GPIO_PORT, LCD_CTRL_EN_PIN)

#define LCD_EN_HIGH() GPIO_SetBits(LCD_CTRL_EN_GPIO_PORT, LCD_CTRL_EN_PIN)

#define LCD_RS_LOW() GPIO_ResetBits(LCD_CTRL_RS_GPIO_PORT, LCD_CTRL_RS_PIN)

#define LCD_RS_HIGH() GPIO_SetBits(LCD_CTRL_RS_GPIO_PORT, LCD_CTRL_RS_PIN)

#define LCD_RS(x) GPIO_WriteBit(LCD_CTRL_RS_GPIO_PORT, LCD_CTRL_RS_PIN, x)

#define LCD_EN(x) GPIO_WriteBit(LCD_CTRL_EN_GPIO_PORT, LCD_CTRL_EN_PIN, x)

#define GET_BIT(a, b) ((a >> b) & 1)

/* Delay required by HD44780 */

#ifdef LCD_DELAY_EXTERN

extern void DelayMs(uint32_t);

#else

extern void DelayMs2(uint32_t);

#endif

/* LCD_Constants */

#define LCD_DataLength_4Bit (uint8_t)0

#define LCD_LineNumber_1Line (uint8_t)0

#define LCD_LineNumber_2Lines (uint8_t)8

#define LCD_CharacterFont_5x8Dots (uint8_t)0

#define LCD_CharacterFont_5x10Dots (uint8_t)4

#define LCD_CursorDirection_Decrement (uint8_t)0

#define LCD_CursorDirection_Increment (uint8_t)2

#define LCD_DisplayShift_NoShift (uint8_t)0

#define LCD_DisplayShift_Shift (uint8_t)1

#define LCD_DisplayState_On (uint8_t)4

#define LCD_DisplayState_Off (uint8_t)0

#define LCD_CursorState_On (uint8_t)2

#define LCD_CursorState_Off (uint8_t)0

#define LCD_BlinkCursor_On (uint8_t)1

#define LCD_BlinkCursor_Off (uint8_t)0

#define LCD_MoveOrShift_MoveCursor (uint8_t)0

#define LCD_MoveOrShift_ShiftDisplay (uint8_t)8

#define LCD_ShiftDirection_Left (uint8_t)0

#define LCD_ShiftDirection_Right (uint8_t)4

/* LCD Commands */

Page 2: Embedded Systems Project 3rd Year

#define LCD_CMD_ClearDisplay (uint8_t)1

#define LCD_CMD_CursorHome (uint8_t)2

/* LCD Command prefixes */

#define LCD_PFX_EntryModeSet (uint8_t)4

#define LCD_PFX_DisplayOnOff (uint8_t)8

#define LCD_PFX_CursorDisplayShift (uint8_t)16

#define LCD_PFX_FunctionSet (uint8_t)32

#define LCD_PFX_CgramSetAddress (uint8_t)64

#define LCD_PFX_DdramSetAddress (uint8_t)128

/* Structures */

typedef struct

{

uint8_t DataLength; /* LCD communication bus length. Only 4-bit supported yet */

uint8_t LineNumber; /* Number of lines displayed on LCD. */

uint8_t CharacterFont; /* Displayed character font */

} LCD_InitTypeDef;

typedef struct

{

uint8_t CursorDirection; /* Cursor move direction during data read/write */

uint8_t DisplayShift; /* Specifies display shift during data read/write */

} LCD_EntryModeCmdTypeDef;

typedef struct

{

uint8_t DisplayState; /* Display on/off control */

uint8_t CursorState; /* Cursor on/off control */

uint8_t BlinkCursor; /* Blinking at cursor position character on/off control */

} LCD_DisplayOnOffCmdTypedef;

typedef struct

{

uint8_t MoveOrShift; /* Specifies preferred printing mode */

uint8_t ShiftDirection; /* Specifies display shifting direcion if shifting on */

} LCD_CursorDisplayShiftCmdTypeDef;

void lcd_init();

void lcd_init_struct(LCD_InitTypeDef *LCD_InitStruct);

void lcd_clear(void);

void lcd_send_nibble(uint8_t n);

void lcd_send_byte(uint8_t address, uint8_t n);

void lcd_set_ddram_address(uint8_t address);

void lcd_set_cgram_address(uint8_t address);

void lcd_goto(uint8_t cx, uint8_t cy);

void lcd_write_custom_char(uint8_t num, const uint8_t *c);

void lcd_put_char(char c);

void lcd_put_string(const char *s);

void lcd_put_signed_int(int32_t value);

void lcd_put_unsigned_int(uint32_t value);

void lcd_entry_mode_cmd(LCD_EntryModeCmdTypeDef *LCD_EntryModeCmdStruct);

void lcd_display_onoff_cmd(LCD_DisplayOnOffCmdTypedef *LCD_DisplayOnOffStruct);

void lcd_cursor_display_shift_cmd(LCD_CursorDisplayShiftCmdTypeDef *LCD_CursorDisplayShiftStruct);

#endif

Page 3: Embedded Systems Project 3rd Year

LCD.C

/*

* 16x2 LCD Driver Implementation File for STM32F4 Discovery

* Andrew Kozik Embedded Systems Project 2015 (UCT)

*/

#include "lcd.h"

void lcd_lowlevel_init();

void lcd_write_cmd(uint8_t n);

void lcd_write_data(uint8_t n);

void delay_ms(uint32_t nTime)

{

volatile uint32_t n = nTime * SystemCoreClock / 10000;

while(n > 0) n--;

}

void lcd_init() {

LCD_InitTypeDef LCD_TypeDef;

LCD_TypeDef.CharacterFont = LCD_CharacterFont_5x8Dots;

LCD_TypeDef.DataLength = LCD_DataLength_4Bit;

LCD_TypeDef.LineNumber = LCD_LineNumber_2Lines;

lcd_init_struct(&LCD_TypeDef);

}

void lcd_init_struct(LCD_InitTypeDef *LCD_InitStruct)

{

uint8_t ctrl, i;

ctrl = LCD_PFX_FunctionSet |

LCD_InitStruct->DataLength |

LCD_InitStruct->LineNumber |

LCD_InitStruct->CharacterFont;

lcd_lowlevel_init();

LCD_EN(0);

LCD_RS(0);

delay_ms(15);

for (i = 0; i < 3; i++)

{

lcd_send_nibble(3);

delay_ms(5);

}

lcd_send_nibble(2);

delay_ms(5);

lcd_send_byte(0, ctrl);

ctrl = LCD_PFX_DisplayOnOff |

LCD_DisplayState_On |

LCD_CursorState_Off |

LCD_BlinkCursor_Off;

lcd_send_byte(0, ctrl);

ctrl = LCD_CMD_ClearDisplay;

lcd_send_byte(0, ctrl);

ctrl = LCD_PFX_EntryModeSet |

LCD_CursorDirection_Increment |

LCD_DisplayShift_NoShift;

lcd_send_byte(0, ctrl);

}

void lcd_clear(void)

{

lcd_send_byte(0, LCD_CMD_ClearDisplay);

lcd_send_byte(0, LCD_CMD_CursorHome);

}

void lcd_send_nibble(uint8_t n)

{

GPIO_WriteBit(LCD_CTRL_D4_GPIO_PORT, LCD_CTRL_D4_PIN, GET_BIT(n, 0));

GPIO_WriteBit(LCD_CTRL_D5_GPIO_PORT, LCD_CTRL_D5_PIN, GET_BIT(n, 1));

GPIO_WriteBit(LCD_CTRL_D6_GPIO_PORT, LCD_CTRL_D6_PIN, GET_BIT(n, 2));

GPIO_WriteBit(LCD_CTRL_D7_GPIO_PORT, LCD_CTRL_D7_PIN, GET_BIT(n, 3));

delay_ms(1);

LCD_EN_HIGH();

delay_ms(1);

Page 4: Embedded Systems Project 3rd Year

LCD_EN_LOW();

}

void lcd_send_byte(uint8_t address, uint8_t n)

{

LCD_RS(address);

delay_ms(1);

lcd_send_nibble(n >> 4);

lcd_send_nibble(n & 0xf);

}

void lcd_set_ddram_address(uint8_t address)

{

lcd_send_byte(0, address | LCD_PFX_DdramSetAddress);

}

void lcd_set_cgram_address(uint8_t address)

{

lcd_send_byte(0, address | LCD_PFX_CgramSetAddress);

}

void lcd_goto(uint8_t cx, uint8_t cy)

{

uint8_t address;

if (cy != 1)

address = LCD_LINE_TWO_ADDR;

else

address = 0;

address += cx - 1;

lcd_set_ddram_address(address);

}

void lcd_write_custom_char(uint8_t num, const uint8_t c[])

{

uint8_t i;

if(num < 7)

{

lcd_send_byte(0, 0x40 | (num << 3));

for(i = 0; i < 8; i++)

lcd_send_byte(1, c[i]);

lcd_set_ddram_address(0);

}

}

void lcd_put_char(char c)

{

switch (c) {

case '\a':

lcd_goto(1, 1);

break;

case '\f':

lcd_send_byte(0, LCD_CMD_ClearDisplay);

delay_ms(2);

break;

case '\n':

lcd_goto(1, 2);

break;

case '\b':

lcd_send_byte(0, 0x10);

break;

default:

lcd_send_byte(1, c);

break;

}

}

void lcd_put_string(const char *s)

{

const char *p = s;

while(*p != 0)

{

lcd_put_char(*p);

p++;

}

Page 5: Embedded Systems Project 3rd Year

}

void lcd_put_signed_int(int32_t n)

{

char c1[32];

if(n == 0)

{

lcd_put_char('0');

return;

}

signed int value = n;

unsigned int absolute;

int i = 0;

if(value < 0) {

absolute = -value;

} else {

absolute = value;

}

while (absolute > 0) {

c1[i] = '0' + absolute % 10;

absolute /= 10;

i++;

}

lcd_put_char((value < 0) ? '-' : '+');

i--;

while(i >= 0){

lcd_put_char(c1[i--]);

}

}

void lcd_put_unsigned_int(uint32_t n)

{

char c1[32];

uint32_t value = n;

uint32_t i = 0;

if(n == 0)

{

lcd_put_char('0');

return;

}

while (value > 0) {

c1[i] = '0' + value % 10;

value /= 10;

i++;

}

while(i-- > 0){

lcd_put_char(c1[i]);

}

}

void lcd_lowlevel_init(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

RCC_AHB1PeriphClockCmd(LCD_CTRL_EN_GPIO_CLK | LCD_CTRL_RS_GPIO_CLK |

LCD_CTRL_D4_GPIO_CLK | LCD_CTRL_D5_GPIO_CLK |

LCD_CTRL_D6_GPIO_CLK | LCD_CTRL_D7_GPIO_CLK, ENABLE);

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Pin = LCD_CTRL_EN_PIN;

GPIO_Init(LCD_CTRL_EN_GPIO_PORT, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = LCD_CTRL_RS_PIN;

GPIO_Init(LCD_CTRL_RS_GPIO_PORT, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = LCD_CTRL_D4_PIN;

GPIO_Init(LCD_CTRL_D4_GPIO_PORT, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = LCD_CTRL_D5_PIN;

GPIO_Init(LCD_CTRL_D5_GPIO_PORT, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = LCD_CTRL_D6_PIN;

GPIO_Init(LCD_CTRL_D6_GPIO_PORT, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = LCD_CTRL_D7_PIN;

GPIO_Init(LCD_CTRL_D7_GPIO_PORT, &GPIO_InitStructure);

GPIO_SetBits(LCD_CTRL_EN_GPIO_PORT, LCD_CTRL_EN_PIN);

}

Page 6: Embedded Systems Project 3rd Year

void lcd_entry_mode_cmd(LCD_EntryModeCmdTypeDef *LCD_EntryModeCmdStruct)

{

uint8_t ctrl;

ctrl = LCD_PFX_EntryModeSet |

LCD_EntryModeCmdStruct->CursorDirection |

LCD_EntryModeCmdStruct->DisplayShift;

lcd_send_byte(0, ctrl);

}

void lcd_display_onoff_cmd(LCD_DisplayOnOffCmdTypedef *LCD_DisplayOnOffStruct)

{

uint8_t ctrl;

ctrl = LCD_PFX_DisplayOnOff |

LCD_DisplayOnOffStruct->BlinkCursor |

LCD_DisplayOnOffStruct->CursorState |

LCD_DisplayOnOffStruct->DisplayState;

lcd_send_byte(0, ctrl);

}

void lcd_cursor_display_shift_cmd(

LCD_CursorDisplayShiftCmdTypeDef *LCD_CursorDisplayShiftStruct)

{

uint8_t ctrl;

ctrl = LCD_PFX_CursorDisplayShift |

LCD_CursorDisplayShiftStruct->MoveOrShift |

LCD_CursorDisplayShiftStruct->ShiftDirection;

lcd_send_byte(0, ctrl);

}

Page 7: Embedded Systems Project 3rd Year

GUITAR_GEN.H

/*

* Sound Generator Header File for STM32F4 Discovery

* Andrew Kozik Embedded Systems Project 2015 (UCT)

*/

#ifndef GUITAR_GEN_H_

#define GUITAR_GEN_H_

#define C_BUFFER_SIZE 1468

#define Cs_BUFFER_SIZE 1385

#define D_BUFFER_SIZE 1308

#define Ds_BUFFER_SIZE 1234

#define E_BUFFER_SIZE 1165

#define F_BUFFER_SIZE 1100

#define Fs_BUFFER_SIZE 1038

#define G_BUFFER_SIZE 980

#define Gs_BUFFER_SIZE 925

#define A_BUFFER_SIZE 873

#define As_BUFFER_SIZE 824

#define B_BUFFER_SIZE 778

#include "stm32f4xx.h"

#include "math.h"

#include "audio.h"

typedef enum {C, Cs, D, Ds, E, F, Fs, G, Gs, A, As, B} TONE;

typedef enum {BUFFER_1, BUFFER_2, BUFFER_3} LAST_BUFFER;

void guitar_gen_init(); // Initializes the sound generation module.

void guitar_gen_update_buffers(int16_t* target_buffer);

void guitar_gen_strum(TONE x, int octave); // Pluck the string.

int guitar_tone_to_buffer_size(TONE x); // Converts the tone enum to the buffer size that results in the respective pitch.

int16_t* guitar_update_next_buffer(int curr_buffer_size); // Switches to the next tone generation buffer and returns the next buffer.

#endif

Page 8: Embedded Systems Project 3rd Year

GUITAR_GEN.C

/*

* Sound Generator Implementation for STM32F4 Discovery

* Andrew Kozik Embedded Systems Project 2015 (UCT)

*/

#include "guitar_gen.h"

int16_t buffer_1[2000]; // Permanent "tone" buffers used for Karplus-Strong generation.

int16_t buffer_2[2000]; // Size is arbitrary, but must be bigger than the lowest tone's

int16_t buffer_3[2000]; // buffer size.

int buffer_1_size = 1; // Sets the size of the permanent tone buffers, these values

int buffer_2_size = 1; // are altered to change the pitch that the relevant buffer

int buffer_3_size = 1; // produces.

LAST_BUFFER last_buffer = BUFFER_3; // Tells us which buffer was last used for tone synthesis.

int buff_1_count = 0; // Holds the position we are at when iterating through the

int buff_2_count = 0; // permanent buffers.

int buff_3_count = 0;

void guitar_gen_init() {

int i;

for (i=0; i < buffer_1_size; i++) { // Clear the tone buffers.

buffer_1[i] = 0;

}

for (i=0; i < buffer_2_size; i++) {

buffer_2[i] = 0;

}

for (i=0; i < buffer_3_size; i++) {

buffer_3[i] = 0;

}

RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG, ENABLE); // Enable the random number generator. (for Karplus-Strong synthesis)

RNG_Cmd(ENABLE);

}

void guitar_gen_update_buffers(int16_t* target_buffer) {

int i;

for (i = 0; i < BUFFER_SIZE; i+=2) { // Copy tone buffers to audio buffer and update tone buffer.

int16_t current = (buffer_1[buff_1_count % buffer_1_size] // Sum and copy the tone buffers to the audio buffer.

+ buffer_2[buff_2_count % buffer_2_size]

+ buffer_3[buff_3_count % buffer_3_size])/2;

target_buffer[i] = current/2;

target_buffer[i+1] = current/2;

buffer_1[buff_1_count % buffer_1_size] = // Update the tone buffers. (Karplus-Strong)

0.99*(buffer_1[buff_1_count % buffer_1_size]

+ buffer_1[(buff_1_count + 1) % buffer_1_size]) / 2;

buffer_2[buff_2_count % buffer_2_size] =

0.99*(buffer_2[buff_2_count % buffer_2_size]

+ buffer_2[(buff_2_count + 1) % buffer_2_size]) / 2;

buffer_3[buff_3_count % buffer_3_size] =

0.99*(buffer_3[buff_3_count % buffer_3_size]

+ buffer_3[(buff_3_count + 1) % buffer_3_size]) / 2;

buff_1_count++; // Increment our position in the tone buffers.

buff_2_count++;

buff_3_count++;

}

}

void guitar_gen_strum(TONE x, int octave) {

int curr_buff_size = guitar_tone_to_buffer_size(x)/pow(2, octave+2);

int16_t * current_buffer = guitar_update_next_buffer(curr_buff_size);

int i;

for (i = 0; i < curr_buff_size; i++) { // To simulate a strum, tone buffer is filled with random noise.

while (!RNG_GetFlagStatus(RNG_FLAG_DRDY)) {}

current_buffer[i] = RNG_GetRandomNumber();

}

}

int guitar_tone_to_buffer_size(TONE x) {

switch (x) {

case C: return C_BUFFER_SIZE;

case Cs: return Cs_BUFFER_SIZE;

case D: return D_BUFFER_SIZE;

case Ds: return Ds_BUFFER_SIZE;

Page 9: Embedded Systems Project 3rd Year

case E: return E_BUFFER_SIZE;

case F: return F_BUFFER_SIZE;

case Fs: return Fs_BUFFER_SIZE;

case G: return G_BUFFER_SIZE;

case Gs: return Gs_BUFFER_SIZE;

case A: return A_BUFFER_SIZE;

case As: return As_BUFFER_SIZE;

case B: return B_BUFFER_SIZE;

}

return -1;

}

int16_t* guitar_update_next_buffer(int curr_buff_size) {

switch (last_buffer) {

case BUFFER_1:

buffer_2_size = curr_buff_size;

last_buffer = BUFFER_2;

buff_2_count = 0;

return buffer_2;

case BUFFER_2:

buffer_3_size = curr_buff_size;

last_buffer = BUFFER_3;

buff_3_count = 0;

return buffer_3;

case BUFFER_3:

buffer_1_size = curr_buff_size;

last_buffer = BUFFER_1;

buff_1_count = 0;

return buffer_1;

}

return ((void *)0);

}

Page 10: Embedded Systems Project 3rd Year

CODEC.H

/*

* CS43L22 Codec Driver Header File for STM32F4 Discovery

* Andrew Kozik Embedded Systems Project 2015 (UCT)

*/

#ifndef CODEC_H_

#define CODEC_H_

#include "stm32f4xx.h"

#define I2C_SCL_PIN GPIO_Pin_6 // Define uC pins used for I2C communication with codec.

#define I2C_SDA_PIN GPIO_Pin_9

#define I2C_SCL_PINSOURCE GPIO_PinSource6

#define I2C_SDA_PINSOURCE GPIO_PinSource9

#define I2C_SCL_GPIO_PORT GPIOB

#define I2C_SDA_GPIO_PORT GPIOB

#define I2C_SCL_CLK RCC_AHB1ENR_GPIOBEN

#define I2C_SDA_CLK RCC_AHB1ENR_GPIOBEN

#define I2S_WS_PIN GPIO_Pin_4 // Define uC pins used for I2S sound transfer with codec.

#define I2S_SCLK_PIN GPIO_Pin_10

#define I2S_SD_PIN GPIO_Pin_12

#define I2S_MCLK_PIN GPIO_Pin_7

#define I2S_WS_PINSOURCE GPIO_PinSource4

#define I2S_SCLK_PINSOURCE GPIO_PinSource10

#define I2S_SD_PINSOURCE GPIO_PinSource12

#define I2S_MCLK_PINSOURCE GPIO_PinSource7

#define I2S_WS_GPIO_PORT GPIOA

#define I2S_SCLK_GPIO_PORT GPIOC

#define I2S_SD_GPIO_PORT GPIOC

#define I2S_MCLK_GPIO_PORT GPIOC

#define I2S_WS_CLK RCC_AHB1ENR_GPIOAEN

#define I2S_SCLK_CLK RCC_AHB1ENR_GPIOCEN

#define I2S_SD_CLK RCC_AHB1ENR_GPIOCEN

#define I2S_MCLK_CLK RCC_AHB1ENR_GPIOCEN

#define CODEC_RESET_PIN GPIO_Pin_4 // Define uC GPIO pin to reset audio codec.

#define CODEC_RESET_GPIO_PORT GPIOD

#define CODEC_RESET_CLK RCC_AHB1ENR_GPIODEN

#define CODEC_SPI SPI3

#define CODEC_I2C I2C1

#define CODEC_SPI_AF GPIO_AF_SPI3

#define CODEC_I2C_AF GPIO_AF_I2C1

#define CODEC_SPI_CLK RCC_APB1ENR_SPI3EN

#define CODEC_I2C_CLK RCC_APB1ENR_I2C1EN

#define CODEC_MAP_CHIP_ID 0x01 // Define audio codec map registers.

#define CODEC_MAP_PWR_CTRL1 0x02

#define CODEC_MAP_PWR_CTRL2 0x04

#define CODEC_MAP_CLK_CTRL 0x05

#define CODEC_MAP_IF_CTRL1 0x06

#define CODEC_MAP_IF_CTRL2 0x07

#define CODEC_MAP_PASSTHROUGH_A_SELECT 0x08

#define CODEC_MAP_PASSTHROUGH_B_SELECT 0x09

#define CODEC_MAP_ANALOG_SET 0x0A

#define CODEC_MAP_PASSTHROUGH_GANG_CTRL 0x0C

#define CODEC_MAP_PLAYBACK_CTRL1 0x0D

#define CODEC_MAP_MISC_CTRL 0x0E

#define CODEC_MAP_PLAYBACK_CTRL2 0x0F

#define CODEC_MAP_PASSTHROUGH_A_VOL 0x14

#define CODEC_MAP_PASSTHROUGH_B_VOL 0x15

#define CODEC_MAP_PCMA_VOL 0x1A

#define CODEC_MAP_PCMB_VOL 0x1B

#define CODEC_MAP_BEEP_FREQ_ONTIME 0x1C

#define CODEC_MAP_BEEP_VOL_OFFTIME 0x1D

#define CODEC_MAP_BEEP_TONE_CFG 0x1E

#define CODEC_MAP_TONE_CTRL 0x1F

#define CODEC_MAP_MASTER_A_VOL 0x20

#define CODEC_MAP_MASTER_B_VOL 0x21

#define CODEC_MAP_HP_A_VOL 0x22

#define CODEC_MAP_HP_B_VOL 0x23

#define CODEC_MAP_SPEAK_A_VOL 0x24

#define CODEC_MAP_SPEAK_B_VOL 0x25

#define CODEC_MAP_CH_MIX_SWAP 0x26

#define CODEC_MAP_LIMIT_CTRL1 0x27

Page 11: Embedded Systems Project 3rd Year

#define CODEC_MAP_LIMIT_CTRL2 0x28

#define CODEC_MAP_LIMIT_ATTACK 0x29

#define CODEC_MAP_OVFL_CLK_STATUS 0x2E

#define CODEC_MAP_BATT_COMP 0x2F

#define CODEC_MAP_VP_BATT_LEVEL 0x30

#define CODEC_MAP_SPEAK_STATUS 0x31

#define CODEC_MAP_CHARGE_PUMP_FREQ 0x34

#define CODEC_MAPBYTE_INC 0x80

#define CODEC_I2C_ADDRESS 0x94 // Define uC I2C audio codec address.

void codec_init(void); // Initialize the audio codec.

void codec_send_ctrl(uint8_t control_bytes[], // Send control bytes to the codec over I2C.

uint8_t num_bytes);

uint8_t codec_read_register(uint8_t map_byte); // Read from audio codec register.

void codec_ctrl_init(); // Initialize the audio codec map registers.

#endif

Page 12: Embedded Systems Project 3rd Year

CODEC.C

/*

* CS43L22 Codec Driver Implementation for STM32F4 Discovery

* Andrew Kozik Embedded Systems Project 2015 (UCT)

*/

#include "codec.h"

void codec_init() {

RCC_APB1PeriphClockCmd(CODEC_SPI_CLK | CODEC_I2C_CLK, ENABLE); // Enable power clocks to I2C and SPI.

RCC_AHB1PeriphClockCmd(I2C_SCL_CLK | I2C_SDA_CLK |

CODEC_RESET_CLK | I2S_WS_CLK | I2S_SCLK_CLK |

I2S_SD_CLK | I2S_MCLK_CLK, ENABLE); // Enable GPIO power clocks

RCC_PLLI2SCmd(ENABLE); // Enable PLL on I2S.

GPIO_InitTypeDef I2C_SCL_SDA_TypeDef; // Initialize I2C pins.

I2C_SCL_SDA_TypeDef.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN;

I2C_SCL_SDA_TypeDef.GPIO_Mode = GPIO_Mode_AF;

I2C_SCL_SDA_TypeDef.GPIO_OType = GPIO_OType_OD;

I2C_SCL_SDA_TypeDef.GPIO_PuPd = GPIO_PuPd_NOPULL;

I2C_SCL_SDA_TypeDef.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(I2C_SCL_GPIO_PORT, &I2C_SCL_SDA_TypeDef);

GPIO_PinAFConfig(I2C_SCL_GPIO_PORT, I2C_SCL_PINSOURCE, CODEC_I2C_AF); // Map Alternate Function pins to I2C1.

GPIO_PinAFConfig(I2C_SCL_GPIO_PORT, I2C_SDA_PINSOURCE, CODEC_I2C_AF);

GPIO_InitTypeDef CODEC_RESET_TypeDef; // Initialize audio codec reset pin.

CODEC_RESET_TypeDef.GPIO_Pin = CODEC_RESET_PIN;

CODEC_RESET_TypeDef.GPIO_Mode = GPIO_Mode_OUT;

CODEC_RESET_TypeDef.GPIO_OType = GPIO_OType_PP;

CODEC_RESET_TypeDef.GPIO_PuPd = GPIO_PuPd_DOWN;

GPIO_Init(CODEC_RESET_GPIO_PORT, &CODEC_RESET_TypeDef);

GPIO_InitTypeDef I2S_WS_TypeDef; // Initialize I2S Pins.

I2S_WS_TypeDef.GPIO_Pin = I2S_WS_PIN;

I2S_WS_TypeDef.GPIO_Mode = GPIO_Mode_AF;

I2S_WS_TypeDef.GPIO_OType = GPIO_OType_PP;

I2S_WS_TypeDef.GPIO_PuPd = GPIO_PuPd_NOPULL;

I2S_WS_TypeDef.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(I2S_WS_GPIO_PORT, &I2S_WS_TypeDef);

GPIO_PinAFConfig(I2S_WS_GPIO_PORT, I2S_WS_PINSOURCE, CODEC_SPI_AF); // Map pin to SPI3 for I2S use.

GPIO_InitTypeDef I2S_SCLK_SD_MCLK_TypeDef; // Initialize I2S Pins.

I2S_SCLK_SD_MCLK_TypeDef.GPIO_Pin = I2S_SCLK_PIN | I2S_SD_PIN | I2S_MCLK_PIN;

I2S_SCLK_SD_MCLK_TypeDef.GPIO_Mode = GPIO_Mode_AF;

I2S_SCLK_SD_MCLK_TypeDef.GPIO_OType = GPIO_OType_PP;

I2S_SCLK_SD_MCLK_TypeDef.GPIO_PuPd = GPIO_PuPd_NOPULL;

I2S_SCLK_SD_MCLK_TypeDef.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(I2S_SCLK_GPIO_PORT, &I2S_SCLK_SD_MCLK_TypeDef);

GPIO_PinAFConfig(I2S_SCLK_GPIO_PORT, I2S_SCLK_PINSOURCE, CODEC_SPI_AF); // Map Pins to SPI3 for I2S use.

GPIO_PinAFConfig(I2S_SCLK_GPIO_PORT, I2S_SD_PINSOURCE, CODEC_SPI_AF);

GPIO_PinAFConfig(I2S_SCLK_GPIO_PORT, I2S_MCLK_PINSOURCE, CODEC_SPI_AF);

GPIO_ResetBits(CODEC_RESET_GPIO_PORT, CODEC_RESET_PIN); // Keep audio codec off.

SPI_I2S_DeInit(CODEC_SPI);

I2S_InitTypeDef I2Sx_TypeDef; // Initialize SPI I2S.

I2Sx_TypeDef.I2S_AudioFreq = I2S_AudioFreq_48k;

I2Sx_TypeDef.I2S_MCLKOutput = I2S_MCLKOutput_Enable;

I2Sx_TypeDef.I2S_Mode = I2S_Mode_MasterTx;

I2Sx_TypeDef.I2S_Standard = I2S_Standard_Phillips;

I2Sx_TypeDef.I2S_DataFormat = I2S_DataFormat_16b;

I2Sx_TypeDef.I2S_CPOL = I2S_CPOL_Low;

I2S_Init(CODEC_SPI, &I2Sx_TypeDef);

I2C_DeInit(CODEC_I2C);

I2C_InitTypeDef I2Cx_TypeDef; // Initialize I2C.

I2Cx_TypeDef.I2C_ClockSpeed = 100000;

I2Cx_TypeDef.I2C_Mode = I2C_Mode_I2C;

I2Cx_TypeDef.I2C_OwnAddress1 = 99;

I2Cx_TypeDef.I2C_Ack = I2C_Ack_Enable;

I2Cx_TypeDef.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

I2Cx_TypeDef.I2C_DutyCycle = I2C_DutyCycle_2;

I2C_Init(CODEC_I2C, &I2Cx_TypeDef);

I2C_Cmd(CODEC_I2C, ENABLE);

}

void codec_ctrl_init()

{

uint32_t delay_count = 1000000;

uint8_t codec_cmd_buffer[5]; // Buff stores list of commands to send codec.

Page 13: Embedded Systems Project 3rd Year

uint8_t reg_value = 0xFF;

GPIO_SetBits(CODEC_RESET_GPIO_PORT, CODEC_RESET_PIN);

while (delay_count > 0)

{

delay_count--;

}

codec_cmd_buffer[0] = CODEC_MAP_PLAYBACK_CTRL1; // Keep audio codec OFF.

codec_cmd_buffer[1] = 0x01;

codec_send_ctrl(codec_cmd_buffer, 2);

codec_cmd_buffer[0] = 0x00; // Begin initialization sequence.

codec_cmd_buffer[1] = 0x99;

codec_send_ctrl(codec_cmd_buffer, 2);

codec_cmd_buffer[0] = 0x47;

codec_cmd_buffer[1] = 0x80;

codec_send_ctrl(codec_cmd_buffer, 2);

reg_value = codec_read_register(0x32);

codec_cmd_buffer[0] = 0x32;

codec_cmd_buffer[1] = reg_value | 0x80;

codec_send_ctrl(codec_cmd_buffer, 2);

reg_value = codec_read_register(0x32);

codec_cmd_buffer[0] = 0x32;

codec_cmd_buffer[1] = reg_value & (~0x80);

codec_send_ctrl(codec_cmd_buffer, 2);

codec_cmd_buffer[0] = 0x00;

codec_cmd_buffer[1] = 0x00;

codec_send_ctrl(codec_cmd_buffer, 2); // Initialization sequence complete.

codec_cmd_buffer[0] = CODEC_MAP_PWR_CTRL2;

codec_cmd_buffer[1] = 0xAF;

codec_send_ctrl(codec_cmd_buffer, 2);

codec_cmd_buffer[0] = CODEC_MAP_PLAYBACK_CTRL1;

codec_cmd_buffer[1] = 0x70;

codec_send_ctrl(codec_cmd_buffer, 2);

codec_cmd_buffer[0] = CODEC_MAP_CLK_CTRL;

codec_cmd_buffer[1] = 0x81; // Auto detect clock.

codec_send_ctrl(codec_cmd_buffer, 2);

codec_cmd_buffer[0] = CODEC_MAP_IF_CTRL1;

codec_cmd_buffer[1] = 0x07;

codec_send_ctrl(codec_cmd_buffer, 2);

codec_cmd_buffer[0] = 0x0A; // Analog ZC SR settings

codec_cmd_buffer[1] = 0x00;

codec_send_ctrl(codec_cmd_buffer, 2);

codec_cmd_buffer[0] = 0x27; // Limit Ctl 1 thresholds

codec_cmd_buffer[1] = 0x00;

codec_send_ctrl(codec_cmd_buffer, 2);

codec_cmd_buffer[0] = 0x1A | CODEC_MAPBYTE_INC;

codec_cmd_buffer[1] = 0x0A;

codec_cmd_buffer[2] = 0x0A;

codec_send_ctrl(codec_cmd_buffer, 3);

codec_cmd_buffer[0] = 0x1F; // Tone ctl

codec_cmd_buffer[1] = 0x0F;

codec_send_ctrl(codec_cmd_buffer, 2);

codec_cmd_buffer[0] = CODEC_MAP_PWR_CTRL1;

codec_cmd_buffer[1] = 0x9E;

codec_send_ctrl(codec_cmd_buffer, 2);

}

void codec_send_ctrl(uint8_t control_bytes[], uint8_t num_bytes)

{

uint8_t bytes_sent=0;

while (I2C_GetFlagStatus(CODEC_I2C, I2C_FLAG_BUSY)) {}

I2C_GenerateSTART(CODEC_I2C, ENABLE);

while (!I2C_GetFlagStatus(CODEC_I2C, I2C_FLAG_SB)) {}

I2C_Send7bitAddress(CODEC_I2C, CODEC_I2C_ADDRESS, I2C_Direction_Transmitter);

while (!I2C_CheckEvent(CODEC_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) {}

while (bytes_sent < num_bytes)

{

I2C_SendData(CODEC_I2C, control_bytes[bytes_sent]);

bytes_sent++;

while (!I2C_CheckEvent(CODEC_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTING)) {}

}

while(!I2C_GetFlagStatus(CODEC_I2C, I2C_FLAG_BTF)) {}

I2C_GenerateSTOP(CODEC_I2C, ENABLE);

}

Page 14: Embedded Systems Project 3rd Year

uint8_t codec_read_register(uint8_t map_byte)

{

uint8_t received_byte = 0;

while (I2C_GetFlagStatus(CODEC_I2C, I2C_FLAG_BUSY)) {}

I2C_GenerateSTART(CODEC_I2C, ENABLE);

while (!I2C_GetFlagStatus(CODEC_I2C, I2C_FLAG_SB)) {}

I2C_Send7bitAddress(CODEC_I2C, CODEC_I2C_ADDRESS, I2C_Direction_Transmitter);

while (!I2C_CheckEvent(CODEC_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) {}

I2C_SendData(CODEC_I2C, map_byte); // Sets the transmitter address.

while (!I2C_CheckEvent(CODEC_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTING)) {}

I2C_GenerateSTOP(CODEC_I2C, ENABLE);

while (I2C_GetFlagStatus(CODEC_I2C, I2C_FLAG_BUSY)) {}

I2C_AcknowledgeConfig(CODEC_I2C, DISABLE);

I2C_GenerateSTART(CODEC_I2C, ENABLE);

while (!I2C_GetFlagStatus(CODEC_I2C, I2C_FLAG_SB)) {}

I2C_Send7bitAddress(CODEC_I2C, CODEC_I2C_ADDRESS, I2C_Direction_Receiver);

while (!I2C_CheckEvent(CODEC_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) {}

while (!I2C_CheckEvent(CODEC_I2C, I2C_EVENT_MASTER_BYTE_RECEIVED)) {}

received_byte = I2C_ReceiveData(CODEC_I2C);

I2C_GenerateSTOP(CODEC_I2C, ENABLE);

return received_byte;

}

Page 15: Embedded Systems Project 3rd Year

AUDIO.H

/*

* Audio DMA Interface Header File for STM32F4 Discovery

* Andrew Kozik Embedded Systems Project 2015 (UCT)

*/

#ifndef AUDIO_H_

#define AUDIO_H_

#include "stm32f4xx.h"

#include "math.h"

#include "guitar_gen.h"

#define BUFFER_SIZE 256 // 256 halfwords in each audio buffer.

void audio_init(); // Initialize the audio system for DMA.

void audio_clear_buffers(); // Clear the audio buffers.

#endif

Page 16: Embedded Systems Project 3rd Year

AUDIO.C

/*

* Audio DMA Interface Implementation for STM32F4 Discovery

* Andrew Kozik Embedded Systems Project 2015 (UCT)

*/

#include "audio.h"

int16_t double_buffer_1[BUFFER_SIZE]; // The first DMA audio buffer. (ping-pong buffering)

int16_t double_buffer_2[BUFFER_SIZE]; // The second DMA audio buffer. (ping-pong buffering)

void DMA1_Stream7_IRQHandler() { // Called when audio buffer transfer is complete.

DMA_ClearITPendingBit(DMA1_Stream7, DMA_IT_TCIF7); // Clear the interrupt bit so the DMA transmission isn't jammed

if (DMA_GetCurrentMemoryTarget(DMA1_Stream7) == DMA_Memory_0) { // If currently reading audio buff 1 then write to audio buff 2.

guitar_gen_update_buffers(double_buffer_2);

} else {

guitar_gen_update_buffers(double_buffer_1);

}

}

void audio_init() {

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); // Enable the DMA clock.

I2S_Cmd(SPI3, ENABLE); // Enable I2S on SPI3.

DMA_InitTypeDef DMA1_TypeDef;

DMA1_TypeDef.DMA_BufferSize = BUFFER_SIZE;

DMA1_TypeDef.DMA_Channel = DMA_Channel_0;

DMA1_TypeDef.DMA_DIR = DMA_DIR_MemoryToPeripheral;

DMA1_TypeDef.DMA_Mode = DMA_Mode_Circular; // DMA continually loops through audio buffers.

DMA1_TypeDef.DMA_FIFOMode = DMA_FIFOMode_Disable; // Don't need FIFO mode.

DMA1_TypeDef.DMA_Memory0BaseAddr = (uint32_t) &double_buffer_1; // Set first buffer to audio buffer 1.

DMA1_TypeDef.DMA_MemoryBurst = DMA_MemoryBurst_Single; // Don't want burst reads from memory.

DMA1_TypeDef.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // 16 bit signed int is used in buffers.

DMA1_TypeDef.DMA_MemoryInc = DMA_MemoryInc_Enable; // Enable increment through memory. (inc thru audio buffer)

DMA1_TypeDef.DMA_PeripheralBaseAddr = 0x40003C0C;

DMA1_TypeDef.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

DMA1_TypeDef.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; // Don't want burst writes to peripheral.

DMA1_TypeDef.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // Don't want peripheral to incr counter.

DMA1_TypeDef.DMA_Priority = DMA_Priority_High; // High priority as must be frequently

DMA_Init(DMA1_Stream7, &DMA1_TypeDef); // updated for sound to be distortion-free.

DMA_ITConfig(DMA1_Stream7, DMA_IT_TC, ENABLE); // Enable the DMA transfer complete interrupt.

NVIC_InitTypeDef NVIC_DMA1_TypeDef;

NVIC_DMA1_TypeDef.NVIC_IRQChannel = DMA1_Stream7_IRQn; // Map the interrupt to the NVIC.

NVIC_DMA1_TypeDef.NVIC_IRQChannelPreemptionPriority = 0;

NVIC_DMA1_TypeDef.NVIC_IRQChannelSubPriority = 0;

NVIC_DMA1_TypeDef.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_DMA1_TypeDef);

DMA_DoubleBufferModeConfig(DMA1_Stream7, // Set second buffer to audio buffer 2 and set default buffer to buffer 1.

(uint32_t) &double_buffer_2, DMA_Memory_0);

DMA_DoubleBufferModeCmd(DMA1_Stream7, ENABLE); // Enable double buffering.

audio_clear_buffers();

DMA_Cmd(DMA1_Stream7, ENABLE); // Enable DMA.

SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Tx, ENABLE); // Enable I2S transmission over DMA.

}

void audio_clear_buffers() {

int i;

for (i=0; i<BUFFER_SIZE; i++) {

double_buffer_1[i] = 0;

double_buffer_2[i] = 0;

}

}

Page 17: Embedded Systems Project 3rd Year

MAIN.C

/*

* Demo of Karplus-Strong algorithm implementation on STM32F4 Discovery

* Andrew Kozik Embedded Systems Project 2015 (UCT)

*/

#include "stm32f4xx.h"

#include "stm32f4_discovery.h"

#include "lcd.h"

#include "codec.h"

#include "audio.h"

#include "guitar_gen.h"

void delay(int time) {

int i;

for (i = 0; i < 5*time; i++) {}

}

int main(void) {

lcd_init();

codec_init();

codec_ctrl_init();

audio_init();

guitar_gen_init();

const char * string = "Embedded Project\n(C) 2015";

lcd_put_string(string);

while (1) {

guitar_gen_strum(A, 0); // Play the bass-line to Hysteria by Muse

delay (200000);

guitar_gen_strum(A, 0);

delay (200000);

guitar_gen_strum(G, 1);

delay (200000);

guitar_gen_strum(A, 0);

delay (200000);

guitar_gen_strum(G, 1);

delay (200000);

guitar_gen_strum(A, 1);

delay (200000);

guitar_gen_strum(A, 0);

delay (200000);

guitar_gen_strum(G, 1);

delay (200000);

guitar_gen_strum(A, 0);

delay (200000);

guitar_gen_strum(E, 1);

delay (200000);

guitar_gen_strum(A, 0);

delay (200000);

guitar_gen_strum(F, 1);

delay (200000);

guitar_gen_strum(F, 1);

delay (200000);

guitar_gen_strum(E, 1);

delay (200000);

guitar_gen_strum(D, 1);

delay (200000);

guitar_gen_strum(E, 1);

delay (200000);

guitar_gen_strum(E, 0);

delay (200000);

guitar_gen_strum(E, 0);

delay (200000);

guitar_gen_strum(D, 1);

delay (200000);

guitar_gen_strum(E, 0);

delay (200000);

guitar_gen_strum(D, 1);

delay (200000);

guitar_gen_strum(E, 1);

delay (200000);

guitar_gen_strum(E, 0);

delay (200000);

Page 18: Embedded Systems Project 3rd Year

guitar_gen_strum(G, 1);

delay (200000);

guitar_gen_strum(E, 0);

delay (200000);

guitar_gen_strum(E, 1);

delay (200000);

guitar_gen_strum(E, 0);

delay (200000);

guitar_gen_strum(G, 1);

delay (200000);

guitar_gen_strum(G, 1);

delay (200000);

guitar_gen_strum(E, 1);

delay (200000);

guitar_gen_strum(G, 1);

delay (200000);

guitar_gen_strum(A, 1);

delay (200000);

guitar_gen_strum(D, 1);

delay (200000);

guitar_gen_strum(D, 1);

delay (200000);

guitar_gen_strum(C, 2);

delay (200000);

guitar_gen_strum(D, 1);

delay (200000);

guitar_gen_strum(C, 2);

delay (200000);

guitar_gen_strum(D, 2);

delay (200000);

guitar_gen_strum(D, 1);

delay (200000);

guitar_gen_strum(C, 2);

delay (200000);

guitar_gen_strum(D, 1);

delay (200000);

guitar_gen_strum(C, 2);

delay (200000);

guitar_gen_strum(B, 1);

delay (200000);

guitar_gen_strum(D, 1);

delay (200000);

guitar_gen_strum(B, 1);

delay (200000);

guitar_gen_strum(As, 1);

delay (200000);

guitar_gen_strum(D, 1);

delay (200000);

guitar_gen_strum(As, 1);

delay (200000);

guitar_gen_strum(A, 1);

delay (200000);

guitar_gen_strum(G, 1);

delay (200000);

guitar_gen_strum(A, 0);

delay (200000);

guitar_gen_strum(G, 1);

delay (200000);

guitar_gen_strum(A, 0);

delay (200000);

guitar_gen_strum(G, 1);

delay (200000);

guitar_gen_strum(A, 1);

delay (200000);

guitar_gen_strum(A, 0);

delay (200000);

guitar_gen_strum(G, 1);

delay (200000);

guitar_gen_strum(A, 0);

delay (200000);

guitar_gen_strum(E, 1);

delay (200000);

guitar_gen_strum(A, 0);

delay (200000);

Page 19: Embedded Systems Project 3rd Year

guitar_gen_strum(F, 1);

delay (200000);

guitar_gen_strum(F, 1);

delay (200000);

guitar_gen_strum(E, 1);

delay (200000);

guitar_gen_strum(D, 1);

delay (200000);

guitar_gen_strum(E, 1);

delay (200000);

}

}