source: rtos_arduino/trunk/arduino_lib/libraries/Robot_Control/src/Squawk.h@ 136

Last change on this file since 136 was 136, checked in by ertl-honda, 8 years ago

ライブラリとOS及びベーシックなサンプルの追加.

File size: 10.5 KB
Line 
1// Squawk Soft-Synthesizer Library for Arduino
2//
3// Davey Taylor 2013
4// d.taylor@arduino.cc
5
6#ifndef _SQUAWK_H_
7#define _SQUAWK_H_
8#include <stddef.h>
9#include <inttypes.h>
10#include "Arduino.h"
11
12#define Melody const uint8_t PROGMEM
13
14class SquawkStream {
15 public:
16 virtual ~SquawkStream() = 0;
17 virtual uint8_t read() = 0;
18 virtual void seek(size_t offset) = 0;
19};
20inline SquawkStream::~SquawkStream() { }
21
22class SquawkSynth {
23
24protected:
25 // Load and play specified melody
26 void play(SquawkStream *melody);
27
28public:
29 SquawkSynth() {};
30
31 // Initialize Squawk to generate samples at sample_rate Hz
32 void begin(uint16_t sample_rate);
33
34 // Load and play specified melody
35 // melody needs to point to PROGMEM data
36 void play(const uint8_t *melody);
37
38 // Resume currently loaded melody (or enable direct osc manipulation by sketch)
39 void play();
40
41 // Pause playback
42 void pause();
43
44 // Stop playback (unloads song)
45 void stop();
46
47 // Tune Squawk to a different frequency - default is 1.0
48 void tune(float tuning);
49
50 // Change the tempo - default is 50
51 void tempo(uint16_t tempo);
52};
53
54extern SquawkSynth Squawk;
55
56// oscillator structure
57typedef struct {
58 uint8_t vol;
59 uint16_t freq;
60 uint16_t phase;
61} osc_t;
62
63typedef osc_t Oscillator;
64
65// oscillator memory
66extern osc_t osc[4];
67extern uint8_t pcm;
68// channel 0 is pulse wave @ 25% duty
69// channel 1 is square wave
70// channel 2 is triangle wave
71// channel 3 is noise
72
73// For channel 3, freq is used as part of its LFSR and should not be changed.
74// LFSR: Linear feedback shift register, a method of producing a
75// pseudo-random bit sequence, used to generate nasty noise.
76
77#ifdef __AVR_ATmega32U4__
78// Supported configurations for ATmega32U4
79#define SQUAWK_PWM_PIN5 OCR3AL
80#define SQUAWK_PWM_PIN11 OCR0A
81#define SQUAWK_PWM_PIN3 OCR0B
82/*
83// NOT SUPPORTED YET
84#define SQUAWK_PWM_PIN6 OCR4D
85#define SQUAWK_PWM_PIN9 OCR4B
86#define SQUAWK_PWM_PIN10 OCR4B
87*/
88#endif
89
90#ifdef __AVR_ATmega168__
91// Supported configurations for ATmega168
92#define SQUAWK_PWM_PIN6 OCR0A
93#define SQUAWK_PWM_PIN5 OCR0B
94#define SQUAWK_PWM_PIN11 OCR2A
95#define SQUAWK_PWM_PIN3 OCR2B
96#endif
97
98#ifdef __AVR_ATmega328P__
99// Supported configurations for ATmega328P
100#define SQUAWK_PWM_PIN6 OCR0A
101#define SQUAWK_PWM_PIN5 OCR0B
102#define SQUAWK_PWM_PIN11 OCR2A
103#define SQUAWK_PWM_PIN3 OCR2B
104#endif
105
106/*
107// NOT SUPPORTED YET
108#define SQUAWK_SPI SPDR
109#define SQUAWK_RLD_PORTB PORTB
110#define SQUAWK_RLD_PORTC PORTC
111*/
112
113extern void squawk_playroutine() asm("squawk_playroutine");
114
115// SAMPLE GRINDER
116// generates samples and updates oscillators
117// uses 132 cycles (not counting playroutine)
118// ~1/3 CPU @ 44kHz on 16MHz
119#define SQUAWK_CONSTRUCT_ISR(TARGET_REGISTER) \
120uint16_t cia, cia_count; \
121intptr_t squawk_register = (intptr_t)&TARGET_REGISTER; \
122ISR(TIMER1_COMPA_vect, ISR_NAKED) { \
123 asm volatile( \
124 "push r2 " "\n\t" \
125 "in r2, __SREG__ " "\n\t" \
126 "push r18 " "\n\t" \
127 "push r27 " "\n\t" \
128 "push r26 " "\n\t" \
129 "push r0 " "\n\t" \
130 "push r1 " "\n\t" \
131\
132 "lds r18, osc+2*%[mul]+%[fre] " "\n\t" \
133 "lds r0, osc+2*%[mul]+%[pha] " "\n\t" \
134 "add r0, r18 " "\n\t" \
135 "sts osc+2*%[mul]+%[pha], r0 " "\n\t" \
136 "lds r18, osc+2*%[mul]+%[fre]+1" "\n\t" \
137 "lds r1, osc+2*%[mul]+%[pha]+1" "\n\t" \
138 "adc r1, r18 " "\n\t" \
139 "sts osc+2*%[mul]+%[pha]+1, r1 " "\n\t" \
140\
141 "mov r27, r1 " "\n\t" \
142 "sbrc r27, 7 " "\n\t" \
143 "com r27 " "\n\t" \
144 "lsl r27 " "\n\t" \
145 "lds r26, osc+2*%[mul]+%[vol] " "\n\t" \
146 "subi r27, 128 " "\n\t" \
147 "muls r27, r26 " "\n\t" \
148 "lsl r1 " "\n\t" \
149 "mov r26, r1 " "\n\t" \
150\
151 "lds r18, osc+0*%[mul]+%[fre] " "\n\t" \
152 "lds r0, osc+0*%[mul]+%[pha] " "\n\t" \
153 "add r0, r18 " "\n\t" \
154 "sts osc+0*%[mul]+%[pha], r0 " "\n\t" \
155 "lds r18, osc+0*%[mul]+%[fre]+1" "\n\t" \
156 "lds r1, osc+0*%[mul]+%[pha]+1" "\n\t" \
157 "adc r1, r18 " "\n\t" \
158 "sts osc+0*%[mul]+%[pha]+1, r1 " "\n\t" \
159\
160 "mov r18, r1 " "\n\t" \
161 "lsl r18 " "\n\t" \
162 "and r18, r1 " "\n\t" \
163 "lds r27, osc+0*%[mul]+%[vol] " "\n\t" \
164 "sbrc r18, 7 " "\n\t" \
165 "neg r27 " "\n\t" \
166 "add r26, r27 " "\n\t" \
167\
168 "lds r18, osc+1*%[mul]+%[fre] " "\n\t" \
169 "lds r0, osc+1*%[mul]+%[pha] " "\n\t" \
170 "add r0, r18 " "\n\t" \
171 "sts osc+1*%[mul]+%[pha], r0 " "\n\t" \
172 "lds r18, osc+1*%[mul]+%[fre]+1" "\n\t" \
173 "lds r1, osc+1*%[mul]+%[pha]+1" "\n\t" \
174 "adc r1, r18 " "\n\t" \
175 "sts osc+1*%[mul]+%[pha]+1, r1 " "\n\t" \
176\
177 "lds r27, osc+1*%[mul]+%[vol] " "\n\t" \
178 "sbrc r1, 7 " "\n\t" \
179 "neg r27 " "\n\t" \
180 "add r26, r27 " "\n\t" \
181\
182 "ldi r27, 1 " "\n\t" \
183 "lds r0, osc+3*%[mul]+%[fre] " "\n\t" \
184 "lds r1, osc+3*%[mul]+%[fre]+1" "\n\t" \
185 "add r0, r0 " "\n\t" \
186 "adc r1, r1 " "\n\t" \
187 "sbrc r1, 7 " "\n\t" \
188 "eor r0, r27 " "\n\t" \
189 "sbrc r1, 6 " "\n\t" \
190 "eor r0, r27 " "\n\t" \
191 "sts osc+3*%[mul]+%[fre], r0 " "\n\t" \
192 "sts osc+3*%[mul]+%[fre]+1, r1 " "\n\t" \
193\
194 "lds r27, osc+3*%[mul]+%[vol] " "\n\t" \
195 "sbrc r1, 7 " "\n\t" \
196 "neg r27 " "\n\t" \
197 "add r26, r27 " "\n\t" \
198\
199 "lds r27, pcm " "\n\t" \
200 "add r26, r27 " "\n\t" \
201 "sts %[reg], r26 " "\n\t" \
202\
203 "lds r27, cia_count+1 " "\n\t" \
204 "lds r26, cia_count " "\n\t" \
205 "sbiw r26, 1 " "\n\t" \
206 "breq call_playroutine " "\n\t" \
207 "sts cia_count+1, r27 " "\n\t" \
208 "sts cia_count, r26 " "\n\t" \
209 "pop r1 " "\n\t" \
210 "pop r0 " "\n\t" \
211 "pop r26 " "\n\t" \
212 "pop r27 " "\n\t" \
213 "pop r18 " "\n\t" \
214 "out __SREG__, r2 " "\n\t" \
215 "pop r2 " "\n\t" \
216 "reti " "\n\t" \
217 "call_playroutine: " "\n\t" \
218\
219 "lds r27, cia+1 " "\n\t" \
220 "lds r26, cia " "\n\t" \
221 "sts cia_count+1, r27 " "\n\t" \
222 "sts cia_count, r26 " "\n\t" \
223\
224 "sei " "\n\t" \
225 "push r19 " "\n\t" \
226 "push r20 " "\n\t" \
227 "push r21 " "\n\t" \
228 "push r22 " "\n\t" \
229 "push r23 " "\n\t" \
230 "push r24 " "\n\t" \
231 "push r25 " "\n\t" \
232 "push r30 " "\n\t" \
233 "push r31 " "\n\t" \
234\
235 "clr r1 " "\n\t" \
236 "call squawk_playroutine " "\n\t" \
237\
238 "pop r31 " "\n\t" \
239 "pop r30 " "\n\t" \
240 "pop r25 " "\n\t" \
241 "pop r24 " "\n\t" \
242 "pop r23 " "\n\t" \
243 "pop r22 " "\n\t" \
244 "pop r21 " "\n\t" \
245 "pop r20 " "\n\t" \
246 "pop r19 " "\n\t" \
247\
248 "pop r1 " "\n\t" \
249 "pop r0 " "\n\t" \
250 "pop r26 " "\n\t" \
251 "pop r27 " "\n\t" \
252 "pop r18 " "\n\t" \
253 "out __SREG__, r2 " "\n\t" \
254 "pop r2 " "\n\t" \
255 "reti " "\n\t" \
256 : \
257 : [reg] "M" _SFR_MEM_ADDR(TARGET_REGISTER), \
258 [mul] "M" (sizeof(Oscillator)), \
259 [pha] "M" (offsetof(Oscillator, phase)), \
260 [fre] "M" (offsetof(Oscillator, freq)), \
261 [vol] "M" (offsetof(Oscillator, vol)) \
262 ); \
263}
264
265#endif
Note: See TracBrowser for help on using the repository browser.