Browse Source

tiny/i2c_timer_pwm.c : Added hold delay and other changes to validate operation after logic analyzer analysis.

master
kevin 3 years ago
parent
commit
78e533a61f
1 changed files with 96 additions and 42 deletions
  1. 96
    42
      control/tiny/i2c_timer_pwm.c

+ 96
- 42
control/tiny/i2c_timer_pwm.c View File

@@ -44,8 +44,9 @@ enum
44 44
  kNoteOff_Op        =  3,  // Turn off note         5
45 45
  kSetReadAddr_Op    =  4,  // Set a read addr.      6 {<src>} {<addr>} }  src: 0=reg 1=table 2=eeprom
46 46
  kWrite_Op          =  5,  // Set write             7 {<addrfl|src> {addr}  {<value0> ... {<valueN>}}  addrFl:0x80  src: 4=reg 5=table 6=eeprom
47
- kWriteTable_Op     =  6,  // Write table to EEprom 9 
48
- kInvalid_Op        =  7   //                                             
47
+ kWriteTable_Op     =  6,  // Write table to EEprom 9
48
+ kHoldDelay_Op      =  7,  // Set hold delay          {<coarse> {<fine>}}
49
+ kInvalid_Op        =  8   //                                             
49 50
 };
50 51
 
51 52
 
@@ -72,6 +73,10 @@ enum
72 73
  kState_idx          = 14, // 1=attk 2=hold
73 74
  kError_Code_idx     = 15, // Error Code
74 75
  kMax_Coarse_Tmr_idx = 16, // Max. allowable coarse timer value
76
+
77
+ kDelay_Coarse_idx   = 17, // (17,18)=2000 (0,6)=100
78
+ kDelay_Fine_idx     = 18,
79
+ 
75 80
  kMax_idx
76 81
 };
77 82
 
@@ -99,12 +104,16 @@ volatile uint8_t ctl_regs[] =
99 104
    4,                // 10 (1-5)    4=16us per tick
100 105
    
101 106
  127,                // 11 (0-255)  Pwm Duty cycle
102
- 254,                // 12 (0-255)  Pwm Frequency  (123 Hz)
103
-  10,                // 13 (0-15)   Pwm clock div 
107
+ 255,                // 12 (0-255)  Pwm Frequency  (123 Hz)
108
+   5,                // 13 (0-15)   Pwm clock div 
104 109
    
105 110
    0,                // 14 state flags 1=attk   2=hold  (read/only)
106 111
    0,                // 15 (0-255)  Error bit field
107 112
    14,               // 16 (0-255) Max allowable coarse timer count
113
+
114
+   0,                // 17 (0-255) Hold coarse delay  
115
+   6               // 18 (0-255) Hold fine delay    0,6=100us 0,124=2000us w/ 16us Tmr0 tick
116
+   
108 117
 };
109 118
 
110 119
 // These registers are saved to Eeprom
@@ -208,6 +217,34 @@ volatile uint8_t hold_state = 0;  // state=0 hold should not be set, state=1 hol
208 217
 #define clear_hold() PORTB &= ~(_BV(HOLD_PIN))
209 218
 #define set_hold()   PORTB |= _BV(HOLD_PIN)
210 219
 
220
+
221
+void hold_begin()
222
+{
223
+  hold_state = 1;
224
+  
225
+  // Reset the PWM counter to to OCR1C (PWM TOP) so that it immediately triggers
226
+  // set_hold() and latches any new value for OCR1B (See: 12.2.2 Timer/Counter1 in PWM Mode)
227
+  // If this is not done and OCR1B was modified the first pulse will have the incorrect length.
228
+  TCNT1   = ctl_regs[kPwm_Freq_idx];  
229
+  TIMSK  |= _BV(OCIE1B) + _BV(TOIE1);    // PWM interupt Enable interrupts
230
+
231
+  TCCR1  |= ctl_regs[ kPwm_Div_idx];     // 32us period (512 divider) prescaler
232
+  GTCCR  |= _BV(PSR1);                   // Force the pre-scale to be latched by setting PSR1
233
+  
234
+}
235
+
236
+void hold_end()
237
+{
238
+  clear_hold();
239
+  TIMSK  &= ~_BV(OCIE0A);                // Clear timer interrupt (shouldn't be necessary but doesn't hurt on during note-off message)
240
+  TIMSK  &= ~(_BV(OCIE1B) + _BV(TOIE1)); // PWM interupt disable interrupts
241
+
242
+  TCCR1  = 0;              // Stop the PWM timer by setting the pre-scale to 0
243
+  GTCCR  |= _BV(PSR1);     // Force the pre-scale to be latched by setting PSR1
244
+  
245
+  hold_state = 0;
246
+}
247
+
211 248
 // Use the current tmr0 ctl_reg[] values to set the timer to the starting state.
212 249
 void tmr0_reset()
213 250
 {
@@ -216,7 +253,11 @@ void tmr0_reset()
216 253
   PORTB                |= _BV(ATTK_PIN);   // set the attack pin
217 254
   clear_hold();                            // clear the hold pin
218 255
   hold_state = 0;
256
+
257
+  tmr0_state = 1;
258
+  OCR0A      = 0xff;
219 259
   
260
+  /*
220 261
   // if a coarse count exists then go into coarse mode 
221 262
   if( ctl_regs[kTmr_Coarse_idx] > 0 )
222 263
   {
@@ -228,6 +269,7 @@ void tmr0_reset()
228 269
     tmr0_state = 2;
229 270
     OCR0A     = ctl_regs[kTmr_Fine_idx];
230 271
   }
272
+  */
231 273
   
232 274
   TCNT0  = 0;
233 275
   TIMSK |= _BV(OCIE0A);     // enable the timer interrupt
@@ -237,32 +279,50 @@ ISR(TIMER0_COMPA_vect)
237 279
 {
238 280
   switch( tmr0_state )
239 281
   {
240
-    case 0:
241
-      // timer is disabled
282
+    case 0: // timer disabled
242 283
       break;
243 284
 
244
-    case 1: 
245
-      // coarse mode
246
-      if( ++tmr0_coarse_cur >= ctl_regs[kTmr_Coarse_idx] )
285
+    case 1: // attack coarse mode
286
+      // Note: the '+1' here is necessary to absorb an interrupt which is occurring
287
+      // for an unknown reason.  It must have something to do with resetting the
288
+      // OCIE0A interrupt because it doesn't occur on the hold delay coarse timing.
289
+      if( ++tmr0_coarse_cur >= ctl_regs[kTmr_Coarse_idx]+1 )
247 290
       {
248
-        tmr0_state  = 2;
249
-        OCR0A     = ctl_regs[kTmr_Fine_idx];        
291
+        tmr0_state = 2;
292
+        OCR0A      = ctl_regs[kTmr_Fine_idx];        
250 293
       }
251 294
       break;
252 295
 
253
-    case 2:
254
-      // fine mode
255
-
256
-      // This marks the end of a timer period 
257
-
296
+    case 2: // attack fine mode
258 297
       clear_attack();
259 298
 
260
-      TCNT1      = 0;   // reset the PWM counter to 0
261
-      hold_state = 1;   // enable the hold output
262
-      TIMSK  |= _BV(OCIE1B) + _BV(TOIE1);  // PWM interupt Enable interrupts          
263
-      TIMSK &= ~_BV(OCIE0A);               // clear timer interrupt
264
-      
299
+      // if a coarse delay count exists then go into coarse mode 
300
+      if( ctl_regs[kDelay_Coarse_idx] > 0 )
301
+      {
302
+        tmr0_state      = 3;
303
+        tmr0_coarse_cur = 0;
304
+        OCR0A           = 0xff;
305
+      }
306
+      else // otherwise go into fine mode
307
+      {
308
+        tmr0_state = 4;
309
+        OCR0A      = ctl_regs[kDelay_Fine_idx];
310
+      }
311
+      break;
312
+
313
+    case 3: // coarse hold delay
314
+      if( ++tmr0_coarse_cur >= ctl_regs[kDelay_Coarse_idx] )
315
+      {
316
+        tmr0_state = 4;
317
+        OCR0A      = ctl_regs[kDelay_Fine_idx];        
318
+      }      
265 319
       break;
320
+      
321
+    case 4: // hold delay end
322
+      TIMSK      &= ~_BV(OCIE0A);    // clear timer interrupt
323
+      tmr0_state  = 0;
324
+      hold_begin();
325
+      break;      
266 326
   }
267 327
 }
268 328
 
@@ -270,9 +330,11 @@ ISR(TIMER0_COMPA_vect)
270 330
 void tmr0_init()
271 331
 {
272 332
   TIMSK  &= ~_BV(OCIE0A);                 // Disable interrupt TIMER1_OVF
333
+  TCCR0A = 0;                             // Set the timer control registers to their default value
334
+  TCCR0B = 0;
273 335
   TCCR0A  |=  0x02;                       // CTC mode
274 336
   TCCR0B  |= ctl_regs[kTmr_Prescale_idx]; // set the prescaler
275
-  GTCCR   |= _BV(PSR0);                   // Set the pre-scaler to the selected value
337
+  GTCCR   |= _BV(PSR0);                   // Trigger the pre-scaler to be reset to the selected value
276 338
 }
277 339
 
278 340
 
@@ -297,27 +359,24 @@ void pwm1_update()
297 359
 // At this point TCNT1 is reset to 0, new OCR1B values are latched from temp. loctaion to OCR1B
298 360
 ISR(TIMER1_OVF_vect)
299 361
 {
300
-  clear_hold();
362
+  set_hold();
301 363
 }
302 364
 
303 365
 // Called when TCNT1 == OCR1B
304 366
 ISR(TIMER1_COMPB_vect)
305 367
 {
306
-  if(hold_state)
307
-    set_hold();
368
+  clear_hold();
308 369
 }
309 370
 
310 371
 
311 372
 void pwm1_init()
312 373
 {
313
-  TIMSK  &= ~(_BV(OCIE1B) + _BV(TOIE1));    // Disable interrupts
314
-  
315 374
   DDRB   |=  _BV(HOLD_DIR);  // setup PB3 as output
316
-
317
-  TCCR1  |= ctl_regs[ kPwm_Div_idx];    // 32us period (512 divider) prescaler
375
+  
376
+  TCCR1 = 0; // Set the control registers to their default
377
+  GTCCR = 0;
318 378
   GTCCR  |= _BV(PWM1B);    // Enable PWM B and disconnect output pins
319
-  GTCCR  |= _BV(PSR1);     // Set the pre-scaler to the selected value
320
-
379
+  
321 380
   pwm1_update();
322 381
 
323 382
 }
@@ -462,14 +521,6 @@ void on_receive( uint8_t byteN )
462 521
       for(i=0; i<stack_idx && i<3; ++i)
463 522
         ctl_regs[ kPwm_Duty_idx + i ] = stack[i];
464 523
 
465
-      // if the PWM prescaler was changed
466
-      if( i == 3 )
467
-      {
468
-        cli();
469
-        pwm1_init();
470
-        sei();
471
-      }
472
-      
473 524
       pwm1_update();
474 525
       break;
475 526
 
@@ -496,9 +547,7 @@ void on_receive( uint8_t byteN )
496 547
       break;
497 548
 
498 549
     case kNoteOff_Op:
499
-      TIMSK  &= ~_BV(OCIE0A);                // clear timer interrupt (shouldn't be necessary)
500
-      //TIMSK  &= ~(_BV(OCIE1B) + _BV(TOIE1)); // PWM interupt disable interrupts
501
-      hold_state = 0;
550
+      hold_end();
502 551
       break;
503 552
 
504 553
     case kSetReadAddr_Op:
@@ -518,6 +567,11 @@ void on_receive( uint8_t byteN )
518 567
     case kWriteTable_Op:
519 568
       write_table();
520 569
       break;
570
+
571
+    case kHoldDelay_Op:
572
+      for(i=0; i<stack_idx && i<2; ++i)
573
+        ctl_regs[ kDelay_Coarse_idx + i ] = stack[i];
574
+      
521 575
   }
522 576
 }
523 577
 

Loading…
Cancel
Save