Compare commits
2 Commits
8be49f95d0
...
5008c67002
Author | SHA1 | Date | |
---|---|---|---|
|
5008c67002 | ||
|
78e533a61f |
@ -16,7 +16,8 @@ class TinyOp(Enum):
|
|||||||
setReadAddr = 4
|
setReadAddr = 4
|
||||||
writeOp = 5
|
writeOp = 5
|
||||||
writeTableOp = 6
|
writeTableOp = 6
|
||||||
invalidOp = 7
|
holdDelayOp = 7
|
||||||
|
invalidOp = 8
|
||||||
|
|
||||||
|
|
||||||
class TinyRegAddr(Enum):
|
class TinyRegAddr(Enum):
|
||||||
@ -36,6 +37,9 @@ class TinyRegAddr(Enum):
|
|||||||
kPwmDivAddr = 13
|
kPwmDivAddr = 13
|
||||||
kStateAddr = 14
|
kStateAddr = 14
|
||||||
kErrorCodeAddr = 15
|
kErrorCodeAddr = 15
|
||||||
|
kMaxAllowTmrAddr = 16
|
||||||
|
kDelayCoarseAddr = 17
|
||||||
|
kDelayFineAddr = 18
|
||||||
|
|
||||||
class TinyConst(Enum):
|
class TinyConst(Enum):
|
||||||
kRdRegSrcId = TinyRegAddr.kRdRegAddrAddr.value # 0
|
kRdRegSrcId = TinyRegAddr.kRdRegAddrAddr.value # 0
|
||||||
@ -184,6 +188,7 @@ class Picadae:
|
|||||||
return self.write_tiny_reg( self._pitch_to_i2c_addr( midi_pitch ), op_code, argL )
|
return self.write_tiny_reg( self._pitch_to_i2c_addr( midi_pitch ), op_code, argL )
|
||||||
|
|
||||||
def set_read_addr( self, i2c_addr, mem_id, addr ):
|
def set_read_addr( self, i2c_addr, mem_id, addr ):
|
||||||
|
# mem_id: 0=reg_array 1=vel_table 2=eeprom
|
||||||
return self.write_tiny_reg(i2c_addr, TinyOp.setReadAddr.value,[ mem_id, addr ])
|
return self.write_tiny_reg(i2c_addr, TinyOp.setReadAddr.value,[ mem_id, addr ])
|
||||||
|
|
||||||
def read_request( self, i2c_addr, reg_addr, byteOutN ):
|
def read_request( self, i2c_addr, reg_addr, byteOutN ):
|
||||||
@ -246,6 +251,19 @@ class Picadae:
|
|||||||
return self.call_op( midi_pitch, TinyOp.noteOffOp.value,
|
return self.call_op( midi_pitch, TinyOp.noteOffOp.value,
|
||||||
[0] ) # TODO: sending a dummy byte because we can't handle sending a command with no data bytes.
|
[0] ) # TODO: sending a dummy byte because we can't handle sending a command with no data bytes.
|
||||||
|
|
||||||
|
def set_hold_delay( self, midi_pitch, pulse_usec ):
|
||||||
|
return self.call_op( midi_pitch, TinyOp.holdDelayOp.value, list(self._usec_to_coarse_and_fine(pulse_usec)) )
|
||||||
|
|
||||||
|
def get_hold_delay( self, midi_pitch, time_out_ms=250 ):
|
||||||
|
|
||||||
|
res = self.block_on_picadae_read_reg( midi_pitch, TinyRegAddr.kDelayCoarseAddr.value, byteOutN=2, time_out_ms=time_out_ms )
|
||||||
|
|
||||||
|
if len(res.value) == 2:
|
||||||
|
res.value = [ self.prescaler_usec*255*res.value[0] + self.prescaler_usec*res.value[1] ]
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
def set_velocity_map( self, midi_pitch, midi_vel, pulse_usec ):
|
def set_velocity_map( self, midi_pitch, midi_vel, pulse_usec ):
|
||||||
coarse,fine = self._usec_to_coarse_and_fine( pulse_usec )
|
coarse,fine = self._usec_to_coarse_and_fine( pulse_usec )
|
||||||
src = TinyConst.kWrAddrFl.value | TinyConst.kWrTableDstId.value
|
src = TinyConst.kWrAddrFl.value | TinyConst.kWrTableDstId.value
|
||||||
@ -258,7 +276,7 @@ class Picadae:
|
|||||||
|
|
||||||
def set_pwm_duty( self, midi_pitch, duty_cycle_pct ):
|
def set_pwm_duty( self, midi_pitch, duty_cycle_pct ):
|
||||||
if 0 <= duty_cycle_pct and duty_cycle_pct <= 100:
|
if 0 <= duty_cycle_pct and duty_cycle_pct <= 100:
|
||||||
duty_cycle_pct = 100.0 - duty_cycle_pct
|
# duty_cycle_pct = 100.0 - duty_cycle_pct
|
||||||
return self.call_op( midi_pitch, TinyOp.setPwmOp.value, [ int( duty_cycle_pct * 255.0 /100.0 )])
|
return self.call_op( midi_pitch, TinyOp.setPwmOp.value, [ int( duty_cycle_pct * 255.0 /100.0 )])
|
||||||
else:
|
else:
|
||||||
return Result(msg="Duty cycle (%f) out of range 0-100." % (duty_cycle_pct))
|
return Result(msg="Duty cycle (%f) out of range 0-100." % (duty_cycle_pct))
|
||||||
@ -279,6 +297,15 @@ class Picadae:
|
|||||||
def get_pwm_div( self, midi_pitch, time_out_ms=250 ):
|
def get_pwm_div( self, midi_pitch, time_out_ms=250 ):
|
||||||
return self.block_on_picadae_read_reg( midi_pitch, TinyRegAddr.kPwmDivAddr.value, time_out_ms=time_out_ms )
|
return self.block_on_picadae_read_reg( midi_pitch, TinyRegAddr.kPwmDivAddr.value, time_out_ms=time_out_ms )
|
||||||
|
|
||||||
|
def set_pwm_div( self, midi_pitch, div, time_out_ms=250 ):
|
||||||
|
res = self.get_pwm_duty( midi_pitch )
|
||||||
|
if res:
|
||||||
|
duty = res.value[0]
|
||||||
|
res = self.get_pwm_freq( midi_pitch )
|
||||||
|
if res:
|
||||||
|
res = self.call_op( midi_pitch, TinyOp.setPwmOp.value, [ int(duty), int(res.value[0]), int(div) ])
|
||||||
|
return res
|
||||||
|
|
||||||
def write_table( self, midi_pitch, time_out_ms=250 ):
|
def write_table( self, midi_pitch, time_out_ms=250 ):
|
||||||
# TODO: sending a dummy byte because we can't handle sending a command with no data bytes.
|
# TODO: sending a dummy byte because we can't handle sending a command with no data bytes.
|
||||||
return self.call_op( midi_pitch, TinyOp.writeTableOp.value,[0])
|
return self.call_op( midi_pitch, TinyOp.writeTableOp.value,[0])
|
||||||
|
@ -10,25 +10,27 @@ class PicadaeShell:
|
|||||||
def __init__( self, cfg ):
|
def __init__( self, cfg ):
|
||||||
self.p = None
|
self.p = None
|
||||||
self.parseD = {
|
self.parseD = {
|
||||||
'q':{ "func":None, "minN":0, "maxN":0, "help":"quit"},
|
'q':{ "func":None, "minN":0, "maxN":0, "help":"quit"},
|
||||||
'?':{ "func":"_help", "minN":0, "maxN":0, "help":"Print usage text."},
|
'?':{ "func":"_help", "minN":0, "maxN":0, "help":"Print usage text."},
|
||||||
'w':{ "func":"_write", "minN":-1, "maxN":-1,"help":"write <i2c_addr> <reg_addr> <data0> ... <dataN>"},
|
'w':{ "func":"_write", "minN":-1, "maxN":-1,"help":"write <i2c_addr> <reg_addr> <data0> ... <dataN>"},
|
||||||
'r':{ "func":"_read", "minN":4, "maxN":4, "help":"read <i2c_addr> <src> <reg_addr> <byteN>"},
|
'r':{ "func":"_read", "minN":4, "maxN":4, "help":"read <i2c_addr> <src> <reg_addr> <byteN> src: 0=reg_array 1=vel_table 2=eeprom"},
|
||||||
'v':{ "func":"note_on_vel", "minN":2, "maxN":2, "help":"note-on <pitch> <vel>"},
|
'v':{ "func":"note_on_vel", "minN":2, "maxN":2, "help":"note-on <pitch> <vel>"},
|
||||||
'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)"},
|
'u':{ "func":"note_on_us", "minN":2, "maxN":3, "help":"note-on <pitch> <usec> <prescale> (1=1, 2=8 .5us, 3=64 4us,(4)=256 16us, 5=1024 64us)"},
|
||||||
'o':{ "func":"note_off", "minN":1, "maxN":1, "help":"note-off <pitch>"},
|
'o':{ "func":"note_off", "minN":1, "maxN":1, "help":"note-off <pitch>"},
|
||||||
'T':{ "func":"set_vel_map", "minN":3, "maxN":3, "help":"table <pitch> <vel> <usec>"},
|
'T':{ "func":"set_vel_map", "minN":3, "maxN":3, "help":"table <pitch> <vel> <usec>"},
|
||||||
't':{ "func":"get_vel_map", "minN":2, "maxN":2, "help":"table <pitch> <vel>"},
|
't':{ "func":"get_vel_map", "minN":2, "maxN":2, "help":"table <pitch> <vel>"},
|
||||||
'D':{ "func":"set_pwm_duty", "minN":2, "maxN":4, "help":"duty <pitch> <percent> {<hz> {<div>}} " },
|
'D':{ "func":"set_pwm_duty", "minN":2, "maxN":4, "help":"duty <pitch> <percent> {<hz> {<div>}} " },
|
||||||
'd':{ "func":"get_pwm_duty", "minN":1, "maxN":1, "help":"duty <pitch>"},
|
'd':{ "func":"get_pwm_duty", "minN":1, "maxN":1, "help":"duty <pitch>"},
|
||||||
'F':{ "func":"set_pwm_freq", "minN":2, "maxN":2, "help":"freq <pitch> <hz> 254=~123Hz"},
|
'H':{ "func":"set_hold_delay", "minN":2, "maxN":2, "help":"hold delay <pitch> <usec>"},
|
||||||
'f':{ "func":"get_pwm_freq", "minN":1, "maxN":1, "help":"freq <pitch>"},
|
'h':{ "func":"get_hold_delay", "minN":1, "maxN":1, "help":"hold delay <pitch>"},
|
||||||
'I':{ "func":"set_pwm_div", "minN":2, "maxN":2, "help":"div <pitch> <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"},
|
'F':{ "func":"set_pwm_freq", "minN":2, "maxN":2, "help":"pwm freq <pitch> <hz> 254=~123Hz"},
|
||||||
'i':{ "func":"get_pwm_div", "minN":1, "maxN":1, "help":"div <pitch>"},
|
'f':{ "func":"get_pwm_freq", "minN":1, "maxN":1, "help":"pwm freq <pitch>"},
|
||||||
'W':{ "func":"write_table", "minN":1, "maxN":1, "help":"write_table <pitch>"},
|
'I':{ "func":"set_pwm_div", "minN":2, "maxN":2, "help":"pwm div <pitch> <div> div:2=2,3=4,4=8,(5)=16 1us,6=32,7=64,8=128,9=256,10=512 32us, 11=1024,12=2048,13=4096,14=8192,15=16384"},
|
||||||
'N':{ "func":"make_note", "minN":3, "maxN":3, "help":"note <pitch> <atkUs> <durMs>"},
|
'i':{ "func":"get_pwm_div", "minN":1, "maxN":1, "help":"pwm div <pitch>"},
|
||||||
'S':{ "func":"make_seq", "minN":5, "maxN":5, "help":"seq <pitch> <atkUs> <durMs> <deltaUs> <note_count>"},
|
'W':{ "func":"write_table", "minN":1, "maxN":1, "help":"write_table <pitch>"},
|
||||||
'L':{ "func":"set_log_level","minN":1, "maxN":1, "help":"log <level> (0-1)."}
|
'N':{ "func":"make_note", "minN":3, "maxN":3, "help":"note <pitch> <atkUs> <durMs>"},
|
||||||
|
'S':{ "func":"make_seq", "minN":5, "maxN":5, "help":"seq <pitch> <atkUs> <durMs> <deltaUs> <note_count>"},
|
||||||
|
'L':{ "func":"set_log_level", "minN":1, "maxN":1, "help":"log <level> (0-1)."}
|
||||||
}
|
}
|
||||||
|
|
||||||
def _help( self, _=None ):
|
def _help( self, _=None ):
|
||||||
@ -40,8 +42,8 @@ class PicadaeShell:
|
|||||||
def _write( self, argL ):
|
def _write( self, argL ):
|
||||||
return self.p.write(argL[0], argL[1], argL[2:])
|
return self.p.write(argL[0], argL[1], argL[2:])
|
||||||
|
|
||||||
def _read( self, argL ):
|
def _read( self, i2c_addr, src_id, reg_addr, byteN ):
|
||||||
return self.p.block_on_picadae_read(argL[0], argL[1], argL[2], argL[3])
|
return self.p.block_on_picadae_read(i2c_addr, src_id, reg_addr, byteN)
|
||||||
|
|
||||||
def _syntaxError( self, msg ):
|
def _syntaxError( self, msg ):
|
||||||
print("Syntax Error: " + msg )
|
print("Syntax Error: " + msg )
|
||||||
|
@ -44,8 +44,9 @@ enum
|
|||||||
kNoteOff_Op = 3, // Turn off note 5
|
kNoteOff_Op = 3, // Turn off note 5
|
||||||
kSetReadAddr_Op = 4, // Set a read addr. 6 {<src>} {<addr>} } src: 0=reg 1=table 2=eeprom
|
kSetReadAddr_Op = 4, // Set a read addr. 6 {<src>} {<addr>} } src: 0=reg 1=table 2=eeprom
|
||||||
kWrite_Op = 5, // Set write 7 {<addrfl|src> {addr} {<value0> ... {<valueN>}} addrFl:0x80 src: 4=reg 5=table 6=eeprom
|
kWrite_Op = 5, // Set write 7 {<addrfl|src> {addr} {<value0> ... {<valueN>}} addrFl:0x80 src: 4=reg 5=table 6=eeprom
|
||||||
kWriteTable_Op = 6, // Write table to EEprom 9
|
kWriteTable_Op = 6, // Write table to EEprom 9
|
||||||
kInvalid_Op = 7 //
|
kHoldDelay_Op = 7, // Set hold delay {<coarse> {<fine>}}
|
||||||
|
kInvalid_Op = 8 //
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -72,6 +73,10 @@ enum
|
|||||||
kState_idx = 14, // 1=attk 2=hold
|
kState_idx = 14, // 1=attk 2=hold
|
||||||
kError_Code_idx = 15, // Error Code
|
kError_Code_idx = 15, // Error Code
|
||||||
kMax_Coarse_Tmr_idx = 16, // Max. allowable coarse timer value
|
kMax_Coarse_Tmr_idx = 16, // Max. allowable coarse timer value
|
||||||
|
|
||||||
|
kDelay_Coarse_idx = 17, // (17,18)=2000 (0,6)=100
|
||||||
|
kDelay_Fine_idx = 18,
|
||||||
|
|
||||||
kMax_idx
|
kMax_idx
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -99,12 +104,16 @@ volatile uint8_t ctl_regs[] =
|
|||||||
4, // 10 (1-5) 4=16us per tick
|
4, // 10 (1-5) 4=16us per tick
|
||||||
|
|
||||||
127, // 11 (0-255) Pwm Duty cycle
|
127, // 11 (0-255) Pwm Duty cycle
|
||||||
254, // 12 (0-255) Pwm Frequency (123 Hz)
|
255, // 12 (0-255) Pwm Frequency (123 Hz)
|
||||||
10, // 13 (0-15) Pwm clock div
|
5, // 13 (0-15) Pwm clock div
|
||||||
|
|
||||||
0, // 14 state flags 1=attk 2=hold (read/only)
|
0, // 14 state flags 1=attk 2=hold (read/only)
|
||||||
0, // 15 (0-255) Error bit field
|
0, // 15 (0-255) Error bit field
|
||||||
14, // 16 (0-255) Max allowable coarse timer count
|
14, // 16 (0-255) Max allowable coarse timer count
|
||||||
|
|
||||||
|
0, // 17 (0-255) Hold coarse delay
|
||||||
|
6 // 18 (0-255) Hold fine delay 0,6=100us 0,124=2000us w/ 16us Tmr0 tick
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// These registers are saved to Eeprom
|
// 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
|
|||||||
#define clear_hold() PORTB &= ~(_BV(HOLD_PIN))
|
#define clear_hold() PORTB &= ~(_BV(HOLD_PIN))
|
||||||
#define set_hold() PORTB |= _BV(HOLD_PIN)
|
#define set_hold() PORTB |= _BV(HOLD_PIN)
|
||||||
|
|
||||||
|
|
||||||
|
void hold_begin()
|
||||||
|
{
|
||||||
|
hold_state = 1;
|
||||||
|
|
||||||
|
// Reset the PWM counter to to OCR1C (PWM TOP) so that it immediately triggers
|
||||||
|
// set_hold() and latches any new value for OCR1B (See: 12.2.2 Timer/Counter1 in PWM Mode)
|
||||||
|
// If this is not done and OCR1B was modified the first pulse will have the incorrect length.
|
||||||
|
TCNT1 = ctl_regs[kPwm_Freq_idx];
|
||||||
|
TIMSK |= _BV(OCIE1B) + _BV(TOIE1); // PWM interupt Enable interrupts
|
||||||
|
|
||||||
|
TCCR1 |= ctl_regs[ kPwm_Div_idx]; // 32us period (512 divider) prescaler
|
||||||
|
GTCCR |= _BV(PSR1); // Force the pre-scale to be latched by setting PSR1
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void hold_end()
|
||||||
|
{
|
||||||
|
clear_hold();
|
||||||
|
TIMSK &= ~_BV(OCIE0A); // Clear timer interrupt (shouldn't be necessary but doesn't hurt on during note-off message)
|
||||||
|
TIMSK &= ~(_BV(OCIE1B) + _BV(TOIE1)); // PWM interupt disable interrupts
|
||||||
|
|
||||||
|
TCCR1 = 0; // Stop the PWM timer by setting the pre-scale to 0
|
||||||
|
GTCCR |= _BV(PSR1); // Force the pre-scale to be latched by setting PSR1
|
||||||
|
|
||||||
|
hold_state = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Use the current tmr0 ctl_reg[] values to set the timer to the starting state.
|
// Use the current tmr0 ctl_reg[] values to set the timer to the starting state.
|
||||||
void tmr0_reset()
|
void tmr0_reset()
|
||||||
{
|
{
|
||||||
@ -216,7 +253,11 @@ void tmr0_reset()
|
|||||||
PORTB |= _BV(ATTK_PIN); // set the attack pin
|
PORTB |= _BV(ATTK_PIN); // set the attack pin
|
||||||
clear_hold(); // clear the hold pin
|
clear_hold(); // clear the hold pin
|
||||||
hold_state = 0;
|
hold_state = 0;
|
||||||
|
|
||||||
|
tmr0_state = 1;
|
||||||
|
OCR0A = 0xff;
|
||||||
|
|
||||||
|
/*
|
||||||
// if a coarse count exists then go into coarse mode
|
// if a coarse count exists then go into coarse mode
|
||||||
if( ctl_regs[kTmr_Coarse_idx] > 0 )
|
if( ctl_regs[kTmr_Coarse_idx] > 0 )
|
||||||
{
|
{
|
||||||
@ -228,6 +269,7 @@ void tmr0_reset()
|
|||||||
tmr0_state = 2;
|
tmr0_state = 2;
|
||||||
OCR0A = ctl_regs[kTmr_Fine_idx];
|
OCR0A = ctl_regs[kTmr_Fine_idx];
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
TCNT0 = 0;
|
TCNT0 = 0;
|
||||||
TIMSK |= _BV(OCIE0A); // enable the timer interrupt
|
TIMSK |= _BV(OCIE0A); // enable the timer interrupt
|
||||||
@ -237,32 +279,50 @@ ISR(TIMER0_COMPA_vect)
|
|||||||
{
|
{
|
||||||
switch( tmr0_state )
|
switch( tmr0_state )
|
||||||
{
|
{
|
||||||
case 0:
|
case 0: // timer disabled
|
||||||
// timer is disabled
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1: // attack coarse mode
|
||||||
// coarse mode
|
// Note: the '+1' here is necessary to absorb an interrupt which is occurring
|
||||||
if( ++tmr0_coarse_cur >= ctl_regs[kTmr_Coarse_idx] )
|
// for an unknown reason. It must have something to do with resetting the
|
||||||
|
// OCIE0A interrupt because it doesn't occur on the hold delay coarse timing.
|
||||||
|
if( ++tmr0_coarse_cur >= ctl_regs[kTmr_Coarse_idx]+1 )
|
||||||
{
|
{
|
||||||
tmr0_state = 2;
|
tmr0_state = 2;
|
||||||
OCR0A = ctl_regs[kTmr_Fine_idx];
|
OCR0A = ctl_regs[kTmr_Fine_idx];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2: // attack fine mode
|
||||||
// fine mode
|
|
||||||
|
|
||||||
// This marks the end of a timer period
|
|
||||||
|
|
||||||
clear_attack();
|
clear_attack();
|
||||||
|
|
||||||
TCNT1 = 0; // reset the PWM counter to 0
|
// if a coarse delay count exists then go into coarse mode
|
||||||
hold_state = 1; // enable the hold output
|
if( ctl_regs[kDelay_Coarse_idx] > 0 )
|
||||||
TIMSK |= _BV(OCIE1B) + _BV(TOIE1); // PWM interupt Enable interrupts
|
{
|
||||||
TIMSK &= ~_BV(OCIE0A); // clear timer interrupt
|
tmr0_state = 3;
|
||||||
|
tmr0_coarse_cur = 0;
|
||||||
|
OCR0A = 0xff;
|
||||||
|
}
|
||||||
|
else // otherwise go into fine mode
|
||||||
|
{
|
||||||
|
tmr0_state = 4;
|
||||||
|
OCR0A = ctl_regs[kDelay_Fine_idx];
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 3: // coarse hold delay
|
||||||
|
if( ++tmr0_coarse_cur >= ctl_regs[kDelay_Coarse_idx] )
|
||||||
|
{
|
||||||
|
tmr0_state = 4;
|
||||||
|
OCR0A = ctl_regs[kDelay_Fine_idx];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4: // hold delay end
|
||||||
|
TIMSK &= ~_BV(OCIE0A); // clear timer interrupt
|
||||||
|
tmr0_state = 0;
|
||||||
|
hold_begin();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,9 +330,11 @@ ISR(TIMER0_COMPA_vect)
|
|||||||
void tmr0_init()
|
void tmr0_init()
|
||||||
{
|
{
|
||||||
TIMSK &= ~_BV(OCIE0A); // Disable interrupt TIMER1_OVF
|
TIMSK &= ~_BV(OCIE0A); // Disable interrupt TIMER1_OVF
|
||||||
|
TCCR0A = 0; // Set the timer control registers to their default value
|
||||||
|
TCCR0B = 0;
|
||||||
TCCR0A |= 0x02; // CTC mode
|
TCCR0A |= 0x02; // CTC mode
|
||||||
TCCR0B |= ctl_regs[kTmr_Prescale_idx]; // set the prescaler
|
TCCR0B |= ctl_regs[kTmr_Prescale_idx]; // set the prescaler
|
||||||
GTCCR |= _BV(PSR0); // Set the pre-scaler to the selected value
|
GTCCR |= _BV(PSR0); // Trigger the pre-scaler to be reset to the selected value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -297,27 +359,24 @@ void pwm1_update()
|
|||||||
// At this point TCNT1 is reset to 0, new OCR1B values are latched from temp. loctaion to OCR1B
|
// At this point TCNT1 is reset to 0, new OCR1B values are latched from temp. loctaion to OCR1B
|
||||||
ISR(TIMER1_OVF_vect)
|
ISR(TIMER1_OVF_vect)
|
||||||
{
|
{
|
||||||
clear_hold();
|
set_hold();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when TCNT1 == OCR1B
|
// Called when TCNT1 == OCR1B
|
||||||
ISR(TIMER1_COMPB_vect)
|
ISR(TIMER1_COMPB_vect)
|
||||||
{
|
{
|
||||||
if(hold_state)
|
clear_hold();
|
||||||
set_hold();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void pwm1_init()
|
void pwm1_init()
|
||||||
{
|
{
|
||||||
TIMSK &= ~(_BV(OCIE1B) + _BV(TOIE1)); // Disable interrupts
|
|
||||||
|
|
||||||
DDRB |= _BV(HOLD_DIR); // setup PB3 as output
|
DDRB |= _BV(HOLD_DIR); // setup PB3 as output
|
||||||
|
|
||||||
TCCR1 |= ctl_regs[ kPwm_Div_idx]; // 32us period (512 divider) prescaler
|
TCCR1 = 0; // Set the control registers to their default
|
||||||
|
GTCCR = 0;
|
||||||
GTCCR |= _BV(PWM1B); // Enable PWM B and disconnect output pins
|
GTCCR |= _BV(PWM1B); // Enable PWM B and disconnect output pins
|
||||||
GTCCR |= _BV(PSR1); // Set the pre-scaler to the selected value
|
|
||||||
|
|
||||||
pwm1_update();
|
pwm1_update();
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -462,14 +521,6 @@ void on_receive( uint8_t byteN )
|
|||||||
for(i=0; i<stack_idx && i<3; ++i)
|
for(i=0; i<stack_idx && i<3; ++i)
|
||||||
ctl_regs[ kPwm_Duty_idx + i ] = stack[i];
|
ctl_regs[ kPwm_Duty_idx + i ] = stack[i];
|
||||||
|
|
||||||
// if the PWM prescaler was changed
|
|
||||||
if( i == 3 )
|
|
||||||
{
|
|
||||||
cli();
|
|
||||||
pwm1_init();
|
|
||||||
sei();
|
|
||||||
}
|
|
||||||
|
|
||||||
pwm1_update();
|
pwm1_update();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -496,9 +547,7 @@ void on_receive( uint8_t byteN )
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case kNoteOff_Op:
|
case kNoteOff_Op:
|
||||||
TIMSK &= ~_BV(OCIE0A); // clear timer interrupt (shouldn't be necessary)
|
hold_end();
|
||||||
//TIMSK &= ~(_BV(OCIE1B) + _BV(TOIE1)); // PWM interupt disable interrupts
|
|
||||||
hold_state = 0;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kSetReadAddr_Op:
|
case kSetReadAddr_Op:
|
||||||
@ -518,6 +567,11 @@ void on_receive( uint8_t byteN )
|
|||||||
case kWriteTable_Op:
|
case kWriteTable_Op:
|
||||||
write_table();
|
write_table();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case kHoldDelay_Op:
|
||||||
|
for(i=0; i<stack_idx && i<2; ++i)
|
||||||
|
ctl_regs[ kDelay_Coarse_idx + i ] = stack[i];
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user