|
@@ -35,13 +35,13 @@
|
35
|
35
|
// Opcodes
|
36
|
36
|
enum
|
37
|
37
|
{
|
38
|
|
- kSetPwm_Op = 0, // Set PWM registers 0 {<duty> {<freq>}}
|
39
|
|
- kNoteOnVel_Op = 1, // Turn on note 1 {<vel>}
|
40
|
|
- kNoteOnUsec_Op = 2, // Turn on note 2 {<coarse> {<fine> {<prescale>}}}
|
41
|
|
- kNoteOff_Op = 3, // Turn off note 3
|
42
|
|
- kSetReadAddr_Op = 4, // Set a read addr. 4 {<src>} {<addr>} } src: 0=reg 1=table 2=eeprom
|
43
|
|
- kWrite_Op = 5, // Set write 5 {<addrfl|src> {addr} {<value0> ... {<valueN>}} addrFl:0x80 src: 4=reg 5=table 6=eeprom
|
44
|
|
- kSetMode_Op = 6, // Set the mode flags 6 {<mode>} 1=repeat 2=pwm
|
|
38
|
+ kSetPwm_Op = 0, // Set PWM duty/hz/div 0 {<duty> {<freq> {<div>}}} div:2=2,3=4,4=8,5=16,6=32,7=64,8=128,9=256,10=512,11=1024,12=2048,13=4096,14=8192,15=16384
|
|
39
|
+ kNoteOnVel_Op = 1, // Turn on note 3 {<vel>}
|
|
40
|
+ kNoteOnUsec_Op = 2, // Turn on note 4 {<coarse> {<fine> {<prescale>}}}
|
|
41
|
+ kNoteOff_Op = 3, // Turn off note 5
|
|
42
|
+ kSetReadAddr_Op = 4, // Set a read addr. 6 {<src>} {<addr>} } src: 0=reg 1=table 2=eeprom
|
|
43
|
+ kWrite_Op = 5, // Set write 7 {<addrfl|src> {addr} {<value0> ... {<valueN>}} addrFl:0x80 src: 4=reg 5=table 6=eeprom
|
|
44
|
+ kWriteTable_Op = 6, // Write table to EEprom 9
|
45
|
45
|
kInvalid_Op = 7 //
|
46
|
46
|
};
|
47
|
47
|
|
|
@@ -60,33 +60,25 @@ enum
|
60
|
60
|
|
61
|
61
|
kTmr_Coarse_idx = 8, //
|
62
|
62
|
kTmr_Fine_idx = 9, //
|
63
|
|
- kTmr_Prescale_idx = 10, // Timer 0 clock divider: 1=1,2=8,3=64,4=256,5=1024 Default: 8 (16us)
|
|
63
|
+ kTmr_Prescale_idx = 10, // Timer 0 clock divider: 1=1,2=8,3=64,4=256,5=1024 Default: 4 (16us)
|
64
|
64
|
|
65
|
65
|
kPwm_Duty_idx = 11, //
|
66
|
66
|
kPwm_Freq_idx = 12, //
|
|
67
|
+ kPwm_Div_idx = 13, //
|
67
|
68
|
|
68
|
|
- kMode_idx = 13, // 1=repeat 2=pwm
|
69
|
69
|
kState_idx = 14, // 1=attk 2=hold
|
70
|
70
|
kError_Code_idx = 15, // Error Code
|
|
71
|
+ kMax_Coarse_Tmr_idx = 16, // Max. allowable coarse timer value
|
71
|
72
|
kMax_idx
|
72
|
73
|
};
|
73
|
74
|
|
74
|
75
|
enum
|
75
|
76
|
{
|
76
|
|
- kMode_Repeat_Fl = 1,
|
77
|
|
- kMode_Pwm_Fl = 2,
|
78
|
|
- kAttk_Fl = 1,
|
79
|
|
- kHold_Fl = 2
|
|
77
|
+ kState_Attk_Fl = 1,
|
|
78
|
+ kState_Hold_Fl = 2
|
80
|
79
|
};
|
81
|
80
|
|
82
|
81
|
|
83
|
|
-#define isInRepeatMode() ctl_regs[ kMode_idx ] & kMode_Repeat_Fl
|
84
|
|
-#define isInPwmMode() ctl_regs[ kMode_idx ] & kMode_Pwm_Fl
|
85
|
|
-
|
86
|
|
-// Flags:
|
87
|
|
-// 1=Repeat: 1=Timer and PWM are free running. This allows testing with LED's. 0=Timer triggers does not reset on time out.
|
88
|
|
-// 2=PWM: On timer timeout 1=PWM HOLD 0=Set HOLD
|
89
|
|
-
|
90
|
82
|
volatile uint8_t ctl_regs[] =
|
91
|
83
|
{
|
92
|
84
|
0, // 0 (0-(kMax_idx-1)) Reg Read Addr
|
|
@@ -99,26 +91,39 @@ volatile uint8_t ctl_regs[] =
|
99
|
91
|
0, // 6 (0-255) EE Write Addr
|
100
|
92
|
kReg_Wr_Addr_idx, // 7 (0-2) Write source
|
101
|
93
|
|
102
|
|
- 245, // 8 (0-255) Timer 0 Coarse Value
|
103
|
|
- 25, // 9 (0-255) Timer 0 Fine Value
|
|
94
|
+ 5, // 8 (0-255) Timer 0 Coarse Value (20400 us)
|
|
95
|
+ 0, // 9 (0-255) Timer 0 Fine Value
|
104
|
96
|
4, // 10 (1-5) 4=16us per tick
|
105
|
97
|
|
106
|
98
|
127, // 11 (0-255) Pwm Duty cycle
|
107
|
99
|
254, // 12 (0-255) Pwm Frequency (123 Hz)
|
|
100
|
+ 10, // 13 (0-15) Pwm clock div
|
108
|
101
|
|
109
|
|
- kMode_Repeat_Fl, // 13 mode flags 1=Repeat 2=PWM
|
110
|
|
- 0, // 14 state flags 1=attk 2=hold
|
|
102
|
+ 0, // 14 state flags 1=attk 2=hold (read/only)
|
111
|
103
|
0, // 15 (0-255) Error bit field
|
|
104
|
+ 14, // 16 (0-255) Max allowable coarse timer count
|
|
105
|
+};
|
|
106
|
+
|
|
107
|
+// These registers are saved to Eeprom
|
|
108
|
+uint8_t eeprom_addr[] =
|
|
109
|
+{
|
|
110
|
+ kTmr_Prescale_idx,
|
|
111
|
+ kPwm_Duty_idx,
|
|
112
|
+ kPwm_Freq_idx,
|
|
113
|
+ kPwm_Div_idx
|
112
|
114
|
};
|
113
|
115
|
|
|
116
|
+
|
|
117
|
+
|
114
|
118
|
#define tableN 256
|
115
|
119
|
uint8_t table[ tableN ]; // [ coarse_0,fine_0, coarse_1, fine_1, .... coarse_127,fine_127]
|
116
|
120
|
|
117
|
121
|
|
118
|
122
|
enum
|
119
|
123
|
{
|
120
|
|
- kInvalid_Read_Src_ErrFl = 0x01,
|
121
|
|
- kInvalid_Write_Dst_ErrFl = 0x02
|
|
124
|
+ kInvalid_Read_Src_ErrFl = 0x01,
|
|
125
|
+ kInvalid_Write_Dst_ErrFl = 0x02,
|
|
126
|
+ kInvalid_Coarse_Tmr_ErrFl = 0x04
|
122
|
127
|
};
|
123
|
128
|
|
124
|
129
|
#define set_error( flag ) ctl_regs[ kError_Code_idx ] |= (flag)
|
|
@@ -143,7 +148,6 @@ void EEPROM_write(uint8_t ucAddress, uint8_t ucData)
|
143
|
148
|
EECR |= (1<<EEPE); // Start eeprom write by setting EEPE
|
144
|
149
|
}
|
145
|
150
|
|
146
|
|
-
|
147
|
151
|
uint8_t EEPROM_read(uint8_t ucAddress)
|
148
|
152
|
{
|
149
|
153
|
// Wait for completion of previous write
|
|
@@ -155,50 +159,33 @@ uint8_t EEPROM_read(uint8_t ucAddress)
|
155
|
159
|
return EEDR; // Return data from data register
|
156
|
160
|
}
|
157
|
161
|
|
158
|
|
-//------------------------------------------------------------------------------
|
159
|
|
-//------------------------------------------------------------------------------
|
160
|
|
-//------------------------------------------------------------------------------
|
161
|
|
-//
|
162
|
|
-// Read/Write table
|
163
|
|
-//
|
164
|
|
-
|
165
|
|
-// To write table value 42 to 127 (coarse) 64 (fine)
|
166
|
|
-//
|
167
|
|
-// w 8 kTable_Addr_idx 42
|
168
|
|
-// w 8 kTable_Coarse_idx 127
|
169
|
|
-// w 8 kTable_fine_idx 64
|
170
|
|
-//
|
171
|
|
-// TO read table value 42
|
172
|
|
-// w 8 kTable_Addr_idx 42
|
173
|
|
-// r 8 kTable_Coarse_idx -> 127
|
174
|
|
-// r 8 kTable_Fine_idx -> 64
|
175
|
|
-
|
176
|
|
-/*
|
177
|
|
-#define eeprom_addr( addr ) (kMax_idx + (addr))
|
178
|
|
-
|
179
|
|
-void table_write_cur_value( void )
|
|
162
|
+void write_table()
|
180
|
163
|
{
|
181
|
|
- uint8_t tbl_addr = ctl_regs[ kTable_Addr_idx ] * 2;
|
182
|
|
-
|
183
|
|
- table[ tbl_addr+0 ] = ctl_regs[ kTable_Coarse_idx ];
|
184
|
|
- table[ tbl_addr+1 ] = ctl_regs[ kTable_Fine_idx ];
|
|
164
|
+ uint8_t i;
|
|
165
|
+ uint8_t regN = sizeof(eeprom_addr);
|
185
|
166
|
|
186
|
|
- EEPROM_write( eeprom_addr( tbl_addr+0 ), ctl_regs[ kTable_Coarse_idx ] );
|
187
|
|
- EEPROM_write( eeprom_addr( tbl_addr+1 ), ctl_regs[ kTable_Fine_idx ]);
|
|
167
|
+ // write the persistent registers
|
|
168
|
+ for(i=0; i<regN; ++i)
|
|
169
|
+ EEPROM_write( i, ctl_regs[ eeprom_addr[i] ] );
|
|
170
|
+
|
|
171
|
+ // write the table
|
|
172
|
+ for(i=0; i<tableN; ++i)
|
|
173
|
+ EEPROM_write( regN+i, table[i] );
|
188
|
174
|
}
|
189
|
175
|
|
190
|
|
-void table_load( void )
|
|
176
|
+void load_table()
|
191
|
177
|
{
|
192
|
|
- uint8_t i = 0;
|
|
178
|
+ uint8_t i;
|
|
179
|
+ uint8_t regN = sizeof(eeprom_addr);
|
193
|
180
|
|
194
|
|
- for(; i<128; ++i)
|
195
|
|
- {
|
196
|
|
- uint8_t tbl_addr = i*2;
|
197
|
|
- table[tbl_addr+0] = EEPROM_read( eeprom_addr(tbl_addr+0) );
|
198
|
|
- table[tbl_addr+1] = EEPROM_read( eeprom_addr(tbl_addr+1) );
|
199
|
|
- }
|
|
181
|
+ // read the persistent registers
|
|
182
|
+ for(i=0; i<regN; ++i)
|
|
183
|
+ ctl_regs[ eeprom_addr[i] ] = EEPROM_read(i);
|
|
184
|
+
|
|
185
|
+ // read the tabke
|
|
186
|
+ for(i=0; i<tableN; ++i)
|
|
187
|
+ table[i] = EEPROM_read(regN + i);
|
200
|
188
|
}
|
201
|
|
-*/
|
202
|
189
|
|
203
|
190
|
|
204
|
191
|
//------------------------------------------------------------------------------
|
|
@@ -208,16 +195,20 @@ void table_load( void )
|
208
|
195
|
// Timer0
|
209
|
196
|
//
|
210
|
197
|
|
211
|
|
-volatile uint8_t tmr0_state = 0; // 0=disabled 1=coarse mode, 2=fine mode
|
|
198
|
+volatile uint8_t tmr0_state = 0; // current timer mode: 0=disabled 1=coarse mode, 2=fine mode
|
212
|
199
|
volatile uint8_t tmr0_coarse_cur = 0;
|
213
|
200
|
|
214
|
|
-#define set_attack() do { ctl_regs[kState_idx] |= kAttk_Fl; PORTB |= _BV(ATTK_PIN); } while(0)
|
215
|
|
-#define clear_attack() do { PORTB &= ~_BV(ATTK_PIN); ctl_regs[kState_idx] &= ~kAttk_Fl; } while(0)
|
|
201
|
+#define set_attack() do { ctl_regs[kState_idx] |= kState_Attk_Fl; PORTB |= _BV(ATTK_PIN); } while(0)
|
|
202
|
+#define clear_attack() do { PORTB &= ~_BV(ATTK_PIN); ctl_regs[kState_idx] &= ~kState_Attk_Fl; } while(0)
|
216
|
203
|
|
217
|
204
|
|
218
|
205
|
// Use the current tmr0 ctl_reg[] values to set the timer to the starting state.
|
219
|
206
|
void tmr0_reset()
|
220
|
207
|
{
|
|
208
|
+ tmr0_coarse_cur = 0; // clear the coarse time counter
|
|
209
|
+ ctl_regs[kState_idx] |= kState_Attk_Fl; // set the attack state
|
|
210
|
+ PORTB |= _BV(ATTK_PIN); // set the attack pin
|
|
211
|
+
|
221
|
212
|
// if a coarse count exists then go into coarse mode
|
222
|
213
|
if( ctl_regs[kTmr_Coarse_idx] > 0 )
|
223
|
214
|
{
|
|
@@ -230,11 +221,7 @@ void tmr0_reset()
|
230
|
221
|
OCR0A = ctl_regs[kTmr_Fine_idx];
|
231
|
222
|
}
|
232
|
223
|
|
233
|
|
- tmr0_coarse_cur = 0;
|
234
|
|
-
|
235
|
|
- ctl_regs[kState_idx] |= kAttk_Fl; // set the attack state
|
236
|
|
- PORTB |= _BV(ATTK_PIN); // set the attack pin
|
237
|
|
- TIMSK |= _BV(OCIE0A); // enable the timer interrupt
|
|
224
|
+ TIMSK |= _BV(OCIE0A); // enable the timer interrupt
|
238
|
225
|
}
|
239
|
226
|
|
240
|
227
|
ISR(TIMER0_COMPA_vect)
|
|
@@ -242,7 +229,7 @@ ISR(TIMER0_COMPA_vect)
|
242
|
229
|
switch( tmr0_state )
|
243
|
230
|
{
|
244
|
231
|
case 0:
|
245
|
|
- // disabled
|
|
232
|
+ // timer is disabled
|
246
|
233
|
break;
|
247
|
234
|
|
248
|
235
|
case 1:
|
|
@@ -257,39 +244,12 @@ ISR(TIMER0_COMPA_vect)
|
257
|
244
|
case 2:
|
258
|
245
|
// fine mode
|
259
|
246
|
|
260
|
|
- // If in repeat mode
|
261
|
|
- if(ctl_regs[kMode_idx] & kMode_Repeat_Fl)
|
262
|
|
- {
|
263
|
|
- uint8_t fl = ctl_regs[kState_idx] & kAttk_Fl;
|
264
|
|
-
|
265
|
|
- tmr0_reset(); // restart the timer
|
266
|
|
-
|
267
|
|
- // ATTK_PIN is always set after tmr0_reset() but we need to toggle in 'repeat' mode
|
268
|
|
- if( fl )
|
269
|
|
- {
|
270
|
|
- clear_attack();
|
271
|
|
- }
|
272
|
|
-
|
273
|
|
- // In repeat mode we run the PWM output continuously
|
274
|
|
- TIMSK |= _BV(OCIE1B) + _BV(TOIE1); // Enable PWM interrupts
|
|
247
|
+ // This marks the end of a timer period
|
275
|
248
|
|
276
|
|
- }
|
277
|
|
- else // not in repeat mode
|
278
|
|
- {
|
279
|
|
- clear_attack();
|
|
249
|
+ clear_attack();
|
280
|
250
|
|
281
|
|
- if( ctl_regs[kMode_idx] & kMode_Pwm_Fl)
|
282
|
|
- {
|
283
|
|
- TIMSK |= _BV(OCIE1B) + _BV(TOIE1); // PWM interupt Enable interrupts
|
284
|
|
- }
|
285
|
|
- else
|
286
|
|
- {
|
287
|
|
- PORTB |= _BV(HOLD_PIN); // set the HOLD pin
|
288
|
|
- }
|
289
|
|
-
|
290
|
|
- TIMSK &= ~_BV(OCIE0A); // clear timer interrupt
|
291
|
|
-
|
292
|
|
- }
|
|
251
|
+ TIMSK |= _BV(OCIE1B) + _BV(TOIE1); // PWM interupt Enable interrupts
|
|
252
|
+ TIMSK &= ~_BV(OCIE0A); // clear timer interrupt
|
293
|
253
|
|
294
|
254
|
break;
|
295
|
255
|
}
|
|
@@ -343,7 +303,7 @@ void pwm1_init()
|
343
|
303
|
// set on TCNT1 == 0 // happens when TCNT1 matches OCR1C
|
344
|
304
|
// clr on OCR1B == TCNT // happens when TCNT1 matches OCR1B
|
345
|
305
|
// // COM1B1=1 COM1B0=0 (enable output on ~OC1B)
|
346
|
|
- TCCR1 |= 10; // 32us period (512 divider) prescaler
|
|
306
|
+ TCCR1 |= ctl_regs[ kPwm_Div_idx]; // 32us period (512 divider) prescaler
|
347
|
307
|
GTCCR |= _BV(PWM1B); // Enable PWM B and disconnect output pins
|
348
|
308
|
GTCCR |= _BV(PSR1); // Set the pre-scaler to the selected value
|
349
|
309
|
|
|
@@ -487,20 +447,38 @@ void on_receive( uint8_t byteN )
|
487
|
447
|
switch( op_id )
|
488
|
448
|
{
|
489
|
449
|
case kSetPwm_Op:
|
490
|
|
- for(i=0; i<stack_idx && i<2; ++i)
|
|
450
|
+ for(i=0; i<stack_idx && i<3; ++i)
|
491
|
451
|
ctl_regs[ kPwm_Duty_idx + i ] = stack[i];
|
|
452
|
+
|
|
453
|
+ // if the PWM prescaler was changed
|
|
454
|
+ if( i == 3 )
|
|
455
|
+ pwm1_init();
|
|
456
|
+
|
492
|
457
|
pwm1_update();
|
493
|
458
|
break;
|
|
459
|
+
|
494
|
460
|
|
495
|
461
|
case kNoteOnUsec_Op:
|
496
|
462
|
for(i=0; i<stack_idx && i<3; ++i)
|
497
|
463
|
ctl_regs[ kTmr_Coarse_idx + i ] = stack[i];
|
|
464
|
+
|
|
465
|
+ // validate the coarse error value
|
|
466
|
+ if( ctl_regs[ kTmr_Coarse_idx ] > ctl_regs[ kMax_Coarse_Tmr_idx ])
|
|
467
|
+ {
|
|
468
|
+ ctl_regs[ kTmr_Coarse_idx ] = ctl_regs[ kMax_Coarse_Tmr_idx ];
|
|
469
|
+ set_error( kInvalid_Coarse_Tmr_ErrFl );
|
|
470
|
+ }
|
|
471
|
+ // if a prescaler was included then the timer needs to be re-initialized
|
|
472
|
+ if( i == 3 )
|
|
473
|
+ tmr0_init();
|
|
474
|
+
|
498
|
475
|
tmr0_reset();
|
499
|
476
|
break;
|
500
|
477
|
|
501
|
478
|
case kNoteOff_Op:
|
|
479
|
+ TIMSK &= ~_BV(OCIE0A); // clear timer interrupt (shouldn't be necessary)
|
502
|
480
|
TIMSK &= ~(_BV(OCIE1B) + _BV(TOIE1)); // PWM interupt disable interrupts
|
503
|
|
- PORTB &= ~_BV(HOLD_PIN); // clear the HOLD pin
|
|
481
|
+ PORTB &= ~_BV(HOLD_PIN); // clear the HOLD pin
|
504
|
482
|
break;
|
505
|
483
|
|
506
|
484
|
case kSetReadAddr_Op:
|
|
@@ -517,13 +495,8 @@ void on_receive( uint8_t byteN )
|
517
|
495
|
_write_op( stack, stack_idx );
|
518
|
496
|
break;
|
519
|
497
|
|
520
|
|
- case kSetMode_Op:
|
521
|
|
- if( stack_idx > 0)
|
522
|
|
- {
|
523
|
|
- ctl_regs[ kMode_idx ] = stack[0];
|
524
|
|
- tmr0_reset();
|
525
|
|
- }
|
526
|
|
-
|
|
498
|
+ case kWriteTable_Op:
|
|
499
|
+ write_table();
|
527
|
500
|
break;
|
528
|
501
|
}
|
529
|
502
|
}
|
|
@@ -550,9 +523,6 @@ int main(void)
|
550
|
523
|
_delay_ms(1000);
|
551
|
524
|
PINB = _BV(LED_PIN); // writes to PINB toggle the pins
|
552
|
525
|
|
553
|
|
- // if in repeat mode
|
554
|
|
- if( ctl_regs[ kMode_idx ] & kMode_Repeat_Fl)
|
555
|
|
- tmr0_reset();
|
556
|
526
|
|
557
|
527
|
while(1)
|
558
|
528
|
{
|