ソースを参照

Added table writing (not yet tested) and removed 'repeat-mode'.

master
kevin.larke 4年前
コミット
5ffd77da17
3個のファイルの変更154行の追加209行の削除
  1. 25
    25
      control/app/picadae_api.py
  2. 42
    67
      control/app/picadae_shell.py
  3. 87
    117
      control/tiny/i2c_timer_pwm.c

+ 25
- 25
control/app/picadae_api.py ファイルの表示

@@ -12,7 +12,7 @@ class TinyOp(Enum):
12 12
     noteOffOp    = 3
13 13
     setReadAddr  = 4
14 14
     writeOp      = 5
15
-    setModeOp    = 6
15
+    writeTableOp = 6
16 16
     invalidOp    = 7
17 17
     
18 18
 
@@ -30,7 +30,7 @@ class TinyRegAddr(Enum):
30 30
     kTmrPrescaleAddr = 10 
31 31
     kPwmDutyAddr     = 11
32 32
     kPwmFreqAddr     = 12
33
-    kModeAddr        = 13
33
+    kPwmDivAddr      = 13
34 34
     kStateAddr       = 14
35 35
     kErrorCodeAddr   = 15
36 36
 
@@ -155,9 +155,10 @@ class Picadae:
155 155
         self.keyMapD        = { d['midi']:d for d in key_mapL }
156 156
         self.i2c_base_addr  = i2c_base_addr
157 157
         self.prescaler_usec = prescaler_usec
158
+        self.log_level      = 0
158 159
         
159 160
         self.serialProc.start()
160
-        
161
+
161 162
     def close( self ):
162 163
         self.serialProc.quit()
163 164
         
@@ -179,7 +180,6 @@ class Picadae:
179 180
     def call_op( self, midi_pitch, op_code, argL ):
180 181
         return self.write( self._pitch_to_i2c_addr( midi_pitch ), op_code, argL )                          
181 182
 
182
-
183 183
     def set_read_addr( self, i2c_addr, mem_id, addr ):
184 184
         return self. write(i2c_addr, TinyOp.setReadAddr.value,[ mem_id, addr ])
185 185
                 
@@ -211,7 +211,7 @@ class Picadae:
211 211
             
212 212
             
213 213
 
214
-    def block_on_picadae_read( self, midi_pitch, mem_id, reg_addr, byteOutN, time_out_ms ):
214
+    def block_on_picadae_read( self, midi_pitch, mem_id, reg_addr, byteOutN, time_out_ms=250 ):
215 215
 
216 216
         i2c_addr = self._pitch_to_i2c_addr( midi_pitch )
217 217
         
@@ -251,34 +251,33 @@ class Picadae:
251 251
     
252 252
     def get_velocity_map( self, midi_pitch, midi_vel, time_out_ms=250 ):
253 253
         byteOutN = 2
254
-        return self.block_on_picadae_read( midi_pitch, TinyConst.kRdTableSrcId.value, midi_vel*2, byteOutN, time_out_ms )        
255
-    
256
-    def set_pwm_duty( self, midi_pitch, duty_cycle_pct ):
254
+        return self.block_on_picadae_read( midi_pitch, TinyConst.kRdTableSrcId.value, midi_vel*2, byteOutN, time_out_ms )
255
+
256
+    def set_pwm( self, midi_pitch, duty_cycle_pct ):
257 257
         return self.call_op( midi_pitch, TinyOp.setPwmOp.value, [ int( duty_cycle_pct * 255.0 /100.0 )])
258 258
 
259
-    def get_pwm_duty( self, midi_pitch, time_out_ms=250 ):
259
+    def get_pwm( self, midi_pitch, time_out_ms=250 ):
260 260
         return self.block_on_picadae_read_reg( midi_pitch, TinyRegAddr.kPwmDutyAddr.value, time_out_ms=time_out_ms )
261 261
     
262
-    def set_pwm_freq( self, midi_pitch, freq_div_id ):
263
-        # pwm frequency divider 1=1,2=8,3=64,4=256,5=1024
264
-        assert( 1 <= freq_div_id and freq_div_id <= 5 )
265
-        pass
266
-    
267 262
     def get_pwm_freq( self, midi_pitch, time_out_ms=250 ):
268 263
         return self.block_on_picadae_read_reg( midi_pitch, TinyRegAddr.kPwmFreqAddr.value, time_out_ms=time_out_ms )
269 264
 
270
-    def set_mode( self, midi_pitch, mode ):
271
-        # TODO validate mode value
272
-        return  self.call_op( midi_pitch, TinyOp.setModeOp.value, [ mode ] )
273
-        
274
-    def get_mode( self, midi_pitch, time_out_ms=250 ):
275
-        return self.block_on_picadae_read_reg( midi_pitch, TinyRegAddr.kModeAddr.value, time_out_ms=time_out_ms )
265
+    def get_pwm_div( self, midi_pitch, time_out_ms=250 ):
266
+        return self.block_on_picadae_read_reg( midi_pitch, TinyRegAddr.kPwmDivAddr.value, time_out_ms=time_out_ms )
267
+
268
+    def write_table( self, midi_pitch, time_out_ms=250 ):
269
+        # TODO: sending a dummy byte because we can't handle sending a command with no data bytes.
270
+        return self.call_op( midi_pitch, TinyOp.writeTableOp.value,[0])
276 271
 
277 272
     def make_note( self, midi_pitch, atk_us, dur_ms ):
278 273
         # TODO: handle error on note_on_us()
279 274
         self.note_on_us(midi_pitch, atk_us);
280 275
         time.sleep( dur_ms / 1000.0 )
281 276
         return self.note_off(midi_pitch)
277
+
278
+    def set_log_level( self, log_level ):
279
+        self.log_level = log_level
280
+        return Result()
282 281
         
283 282
     def _pitch_to_i2c_addr( self, pitch ):
284 283
         return self.keyMapD[ pitch ]['index'] + self.i2c_base_addr
@@ -305,11 +304,12 @@ class Picadae:
305 304
         return self.serialProc.send(SerialMsgId.DATA_MSG, byteA )
306 305
 
307 306
     def _print( self, opcode, i2c_addr, reg_addr, byteL ):
308
-        
309
-        s = "{} {} {}".format( opcode, i2c_addr, reg_addr )
310 307
 
311
-        for x in byteL:
312
-            s += " {}".format(x)
308
+        if self.log_level:
309
+            s = "{} {} {}".format( opcode, i2c_addr, reg_addr )
310
+
311
+            for x in byteL:
312
+                s += " {}".format(x)
313 313
 
314 314
 
315
-        print(s)
315
+            print(s)

+ 42
- 67
control/app/picadae_shell.py ファイルの表示

@@ -7,77 +7,44 @@ class PicadaeShell:
7 7
     def __init__( self, cfg ):
8 8
         self.p      = None
9 9
         self.parseD = {
10
-            'q':{ "func":None,           "varN":0,  "help":"quit"},
11
-            '?':{ "func":"help",         "varN":0,  "help":"Print usage text."},
12
-            'w':{ "func":"write",        "varN":-1, "help":"write <i2c_addr> <reg_addr> <data0> ... <dataN>"},
13
-            'r':{ "func":"read",         "varN":3,  "help":"read  <i2c_addr> <reg_addr> <byteN>"},
14
-            'v':{ "func":"note_on_vel",  "varN":2,  "help":"note-on <pitch> <vel>"},
15
-            'u':{ "func":"note_on_us",   "varN":2,  "help":"note-on <pitch> <usec>"},
16
-            'o':{ "func":"note_off",     "varN":1,  "help":"note-off <pitch>"},
17
-            'T':{ "func":"set_vel_map",  "varN":3,  "help":"table <pitch> <vel> <usec>"},
18
-            't':{ "func":"get_vel_map",  "varN":2,  "help":"table <pitch> <vel>"},
19
-            'D':{ "func":"set_pwm_duty", "varN":2,  "help":"duty <pitch> <percent>"},
20
-            'd':{ "func":"get_pwm_duty", "varN":1,  "help":"duty <pitch>"},
21
-            'F':{ "func":"set_pwm_freq", "varN":2,  "help":"freq <pitch> <hz>"},
22
-            'f':{ "func":"get_pwm_freq", "varN":1,  "help":"freq <pitch>"},
23
-            'M':{ "func":"set_mode",     "varN":2,  "help":"set_mode <pitch> <mode-bits>  (1=repeat 2=pwm)" },
24
-            'm':{ "func":"get_mode",     "varN":1,  "help":"get_mode <pitch>"},
25
-            'N':{ "func":"make_note",    "varN":3,  "help":"note <pitch> atkUs durMs"},
10
+            'q':{ "func":None,           "minN":0,  "maxN":0, "help":"quit"},
11
+            '?':{ "func":"_help",        "minN":0,  "maxN":0, "help":"Print usage text."},
12
+            'w':{ "func":"_write",       "minN":-1, "maxN":-1,"help":"write <i2c_addr> <reg_addr> <data0> ... <dataN>"},
13
+            'r':{ "func":"_read",        "minN":4,  "maxN":4, "help":"read  <i2c_addr> <src> <reg_addr> <byteN>"},
14
+            'v':{ "func":"note_on_vel",  "minN":2,  "maxN":2, "help":"note-on <pitch> <vel>"},
15
+            'u':{ "func":"note_on_us",   "minN":2,  "maxN":3, "help":"note-on <pitch> <usec> <prescale> (1=1, 2=8, 3=64,(4)=256 16us, 5=1024)"},
16
+            'o':{ "func":"note_off",     "minN":1,  "maxN":1, "help":"note-off <pitch>"},
17
+            'T':{ "func":"set_vel_map",  "minN":3,  "maxN":3, "help":"table <pitch> <vel> <usec>"},
18
+            't':{ "func":"get_vel_map",  "minN":2,  "maxN":2, "help":"table <pitch> <vel>"},
19
+            'D':{ "func":"set_pwm",      "minN":2,  "maxN":4, "help":"duty <pitch> <percent> {<hz> {<div>}} div:2=2,3=4,4=8,5=16,6=32,7=64,8=128,9=256,(10)=512 32us, 11=1024,12=2048,13=4096,14=8192,15=16384" },
20
+            'd':{ "func":"get_pwm_duty", "minN":1,  "maxN":1, "help":"duty <pitch>"},
21
+            'f':{ "func":"get_pwm_freq", "minN":1,  "maxN":1, "help":"freq <pitch>"},
22
+            'i':{ "func":"get_pwm_div",  "minN":1,  "maxN":1, "help":"div <pitch>"},
23
+            'W':{ "func":"write_table",  "minN":1,  "maxN":1, "help":"write_table <pitch>"},
24
+            'N':{ "func":"make_note",    "minN":3,  "maxN":3, "help":"note <pitch> atkUs durMs"},
25
+            'L':{ "func":"set_log_level","minN":1,  "maxN":1, "help":"log <level> (0-1)."}
26 26
             }
27 27
 
28
-    def _do_help( self, _ ):
28
+    def _help( self, _=None ):
29 29
         for k,d in self.parseD.items():
30 30
             s = "{} = {}".format( k, d['help'] )
31 31
             print(s)
32 32
         return Result()
33 33
 
34
-    def _do_write( self, argL ):
34
+    def _write( self, argL ):
35 35
         return self.p.write(argL[0], argL[1], argL[2:])
36 36
     
37
-    def _do_read( self, argL ):
38
-        return self.p.read(*argL)
39
-
40
-    def _do_note_on_vel( self, argL ):
41
-        return self.p.note_on_vel(*argL)
42
-    
43
-    def _do_note_on_us( self, argL ):
44
-        return self.p.note_on_us(*argL)
45
-
46
-    def _do_note_off( self, argL ):
47
-        return self.p.note_off(*argL)
48
-
49
-    def _do_set_vel_map( self, argL ):
50
-        return self.p.set_velocity_map(*argL)
51
-
52
-    def _do_get_vel_map( self, argL ):
53
-        return self.p.get_velocity_map(*argL)
54
-
55
-    def _do_set_pwm_duty( self, argL ):
56
-        return self.p.set_pwm_duty(*argL)
57
-
58
-    def _do_get_pwm_duty( self, argL ):
59
-        return self.p.get_pwm_duty(*argL)
60
-    
61
-    def _do_set_pwm_freq( self, argL ):
62
-        return self.p.set_pwm_freq(*argL)
63
-
64
-    def _do_get_pwm_freq( self, argL ):
65
-        return self.p.get_pwm_freq(*argL)
66
-
67
-    def _do_set_mode( self, argL ):
68
-        return self.p.set_mode(*argL)
69
-
70
-    def _do_get_mode( self, argL ):
71
-        return self.p.get_mode(*argL)
72
-    
73
-    def _do_make_note( self, argL ):
74
-        return self.p.make_note(*argL)
37
+    def _read( self, argL ):
38
+        return self.p.block_on_picadae_read(argL[0], argL[1], argL[2], argL[3])
75 39
         
76 40
     def _syntaxError( self, msg ):
77 41
         print("Syntax Error: " + msg )
78 42
         return Result()
79 43
             
80 44
     def _exec_cmd( self, tokL ):
45
+
46
+        result = Result()
47
+        
81 48
         if len(tokL) <= 0:
82 49
             return None
83 50
 
@@ -88,21 +55,29 @@ class PicadaeShell:
88 55
 
89 56
         d = self.parseD[ opcode ]
90 57
 
91
-        func_name = "_do_" + d['func']
58
+        func_name = d['func']
59
+        func      = None
92 60
 
61
+        # find the function associated with this command
93 62
         if hasattr(self, func_name ):
94
-            func   = getattr(self, func_name )
63
+            func = getattr(self, func_name )
64
+        elif hasattr(self.p, func_name ):
65
+            func = getattr(self.p, func_name )
66
+        else:
67
+           return self._syntaxError("Exec function not found: '{}'.".format(func_name))
95 68
 
96
-            try:
97
-                argL = [ int(tokL[i]) for i in range(1,len(tokL)) ]
98
-            except:
99
-                return self._syntaxError("Unable to create integer arguments.")
69
+        try:
70
+            # convert the parameter list into integers
71
+            argL = [ int(tokL[i]) for i in range(1,len(tokL)) ]
72
+        except:
73
+            return self._syntaxError("Unable to create integer arguments.")
100 74
 
101
-            if  d['varN'] != -1 and len(argL) != d['varN']:                
102
-                return self._syntaxError("Argument mismatch {} != {}.".format(len(argL),d['varN']))
103
-            
104
-            result = func(argL)
105
-            
75
+        # validate the count of command args
76
+        if  d['minN'] != -1 and (d['minN'] > len(argL) or len(argL) > d['maxN']):                
77
+            return self._syntaxError("Argument count mismatch. {} is out of range:{} to {}".format(len(argL),d['minN'],d['maxN']))
78
+
79
+        # call the command function
80
+        result = func(*argL)
106 81
 
107 82
         return result
108 83
     

+ 87
- 117
control/tiny/i2c_timer_pwm.c ファイルの表示

@@ -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
   {

読み込み中…
キャンセル
保存