Landtiger LPC1768 C BigLib 1
A self made, custom C library for the LandTiger board.
 
Loading...
Searching...
No Matches
dac.c
Go to the documentation of this file.
1#include "dac.h"
2#include "timer.h"
3#include <LPC17xx.h>
4
5#define DAC_CLK_HZ 25000000
6#define DAC_SIN_TABLE_SZ 45
7
10
13
15// at a specific frequency in order to generate the desired tone.
16const u16 DAC_Sin[] = {410, 467, 523, 576, 627, 673, 714, 749, 778, 799, 813, 819, 817, 807, 789,
17 764, 732, 694, 650, 602, 550, 495, 438, 381, 324, 270, 217, 169, 125, 87,
18 55, 30, 12, 2, 0, 6, 20, 41, 70, 105, 146, 193, 243, 297, 353};
19
20_PRIVATE inline u32 get_tone_timing(u16 note, u8 octave)
21{
22 // Gets the Hz of the tone at the specified octave
23 const u32 freq = (octave <= DAC_OCT_4) ? note << (DAC_OCT_4 - octave) : note >> (octave - DAC_OCT_4);
24
31 return DAC_CLK_HZ / (freq * DAC_SIN_TABLE_SZ);
32}
33
34_PRIVATE inline u16 adjust_sample_volume(u16 sample, u8 volume)
35{
36 if (volume == 0)
37 return 0; // Mute
38
39 sample -= 410;
40 sample /= (10 / volume); // If volume is 1 -> sample /= 10 (decrease volume), if 10 -> sample /= 1 (increase volume)
41 sample += 410;
42
43 return sample;
44}
45
46// TIMER INTERRUPTS & SINE WAVE
47
49{
50 if (DAC_SinVolume == 0)
51 {
52 LPC_DAC->DACR = 0;
53 return;
54 }
55
56 // Sending next sample
58 LPC_DAC->DACR = (volumed_sample << 6);
59
62}
63
64// PUBLIC FUNCTIONS
65
66void DAC_BUZInit(u8 timer_a, u8 timer_b, u8 int_priority)
67{
68 // Enable Analog OUT (function 10) on PIN on P0.26, located in PINSEL1
69 LPC_PINCON->PINSEL1 |= (2 << 20);
70 LPC_GPIO0->FIODIR |= (1 << 26);
71
72 TIMER_Init(&DAC_SamplesTimer, timer_a, NO_PRESCALER, int_priority);
73 TIMER_Init(&DAC_SecondsTimer, timer_b, NO_PRESCALER, int_priority);
74}
75
76void DAC_BUZDeinit(void)
77{
78 LPC_PINCON->PINSEL1 &= ~(3 << 20);
79 LPC_GPIO0->FIODIR &= ~(1 << 26);
80
84}
85
86void DAC_BUZSetVolume(u8 volume)
87{
88 DAC_SinVolume = (IS_BETWEEN_EQ(volume, 0, 10)) ? volume : DAC_VOL_DEFAULT;
89}
90
91void DAC_BUZPlay(DAC_Tone tone, u16 bpm)
92{
93 // How many samples need to be sent to the DAC in a second in order to play the tone
96 .actions = TIM_MR_INT | TIM_MR_RES,
97 .match = get_tone_timing(tone.note, tone.octave)});
98
99 // Since a tone has a type (i.e. a duration which depends on the BPM), the duration of the tone
100 // needs to be controlled by another timer, which, on match, will stop & clear the samples timer.
101 // The duration (in seconds) of the tone is calculated by the formula: (60 * type) / bpm. Since
102 // each second the seconds timer ticks 25 million times, we need to multiply that by the duration
103 const u32 tone_duration = DAC_CLK_HZ * ((60 * tone.type) / bpm);
106 .actions = TIM_MR_INT | TIM_MR_RES | TIM_MR_STP,
107 .match = tone_duration});
108
109 // Starts the timers (i.e. plays)
112}
113
118
119void DAC_BUZStop(void)
120{
123 LPC_DAC->DACR &= ~(0x3FF << 6);
124
127
130}
_PRIVATE void next_sample(void)
Definition dac.c:48
#define DAC_CLK_HZ
Definition dac.c:5
bool DAC_BUZIsPlaying(void)
Definition dac.c:114
_PRIVATE TIMER DAC_SecondsTimer
Definition dac.c:9
void DAC_BUZSetVolume(u8 volume)
Sets the volume of the buzzer.
Definition dac.c:86
_PRIVATE TIMER DAC_SamplesTimer
Definition dac.c:8
void DAC_BUZInit(u8 timer_a, u8 timer_b, u8 int_priority)
Initializes the DAC peripheral.
Definition dac.c:66
const u16 DAC_Sin[]
Sine wave samples for the DAC. They represent one complete period. Each sample needs to be sent to th...
Definition dac.c:16
void DAC_BUZDeinit(void)
Definition dac.c:76
#define DAC_SIN_TABLE_SZ
Definition dac.c:6
void DAC_BUZStop(void)
Definition dac.c:119
_PRIVATE u32 DAC_SinTableIndex
Definition dac.c:12
_PRIVATE u8 DAC_SinVolume
Definition dac.c:11
_PRIVATE u16 adjust_sample_volume(u16 sample, u8 volume)
Definition dac.c:34
void DAC_BUZPlay(DAC_Tone tone, u16 bpm)
Plays the given note for the given duration.
Definition dac.c:91
@ DAC_OCT_4
Definition dac_types.h:32
#define DAC_VOL_DEFAULT
Definition dac_types.h:55
u8 octave
Definition dac_types.h:50
u16 note
Definition dac_types.h:49
u8 which
Definition timer_types.h:44
void TIMER_Reset(TIMER timer)
Resets a TIMER peripheral without deconfiguring it.
Definition timer.c:265
void TIMER_Init(TIMER *timer, u8 which, u32 prescaler, u8 int_priority)
Initializes a TIMER peripheral.
Definition timer.c:62
void TIMER_Disable(TIMER timer)
Disables a TIMER peripheral.
Definition timer.c:229
void TIMER_Enable(TIMER timer)
Enables a TIMER peripheral.
Definition timer.c:203
bool TIMER_IsEnabled(TIMER timer)
Checks if a TIMER peripheral is enabled.
Definition timer.c:248
void TIMER_Deinit(TIMER timer)
Deconfigures a TIMER peripheral (also match registers).
Definition timer.c:124
void TIMER_SetMatch(TIMER timer, TIMER_MatchRegister match_reg)
Sets the match value for a match register of a TIMER peripheral.
Definition timer.c:162
void TIMER_SetInterruptHandler(TIMER timer, u8 source, TIMER_InterruptHandler handler)
Sets the interrupt handler for a TIMER peripheral, on a specific source between the 4 match registers...
Definition timer_irq.c:60
@ TIM_MR0
Definition timer_types.h:20
@ TIM_MR_INT
Definition timer_types.h:30
@ TIM_MR_RES
Definition timer_types.h:31
@ TIM_MR_STP
Definition timer_types.h:32
@ TIM_INT_SRC_MR0
Definition timer_types.h:55
#define NO_PRESCALER
Definition types.h:40
uint8_t u8
Definition types.h:8
#define _PRIVATE
Definition types.h:37
#define IS_BETWEEN_EQ(value, low, hi)
Definition types.h:23
uint16_t u16
Definition types.h:7
uint32_t u32
Definition types.h:6