Added table writing (not yet tested) and removed 'repeat-mode'.
This commit is contained in:
parent
f24aec16e6
commit
5ffd77da17
@ -12,7 +12,7 @@ class TinyOp(Enum):
|
||||
noteOffOp = 3
|
||||
setReadAddr = 4
|
||||
writeOp = 5
|
||||
setModeOp = 6
|
||||
writeTableOp = 6
|
||||
invalidOp = 7
|
||||
|
||||
|
||||
@ -30,7 +30,7 @@ class TinyRegAddr(Enum):
|
||||
kTmrPrescaleAddr = 10
|
||||
kPwmDutyAddr = 11
|
||||
kPwmFreqAddr = 12
|
||||
kModeAddr = 13
|
||||
kPwmDivAddr = 13
|
||||
kStateAddr = 14
|
||||
kErrorCodeAddr = 15
|
||||
|
||||
@ -155,6 +155,7 @@ class Picadae:
|
||||
self.keyMapD = { d['midi']:d for d in key_mapL }
|
||||
self.i2c_base_addr = i2c_base_addr
|
||||
self.prescaler_usec = prescaler_usec
|
||||
self.log_level = 0
|
||||
|
||||
self.serialProc.start()
|
||||
|
||||
@ -179,7 +180,6 @@ class Picadae:
|
||||
def call_op( self, midi_pitch, op_code, argL ):
|
||||
return self.write( self._pitch_to_i2c_addr( midi_pitch ), op_code, argL )
|
||||
|
||||
|
||||
def set_read_addr( self, i2c_addr, mem_id, addr ):
|
||||
return self. write(i2c_addr, TinyOp.setReadAddr.value,[ mem_id, addr ])
|
||||
|
||||
@ -211,7 +211,7 @@ class Picadae:
|
||||
|
||||
|
||||
|
||||
def block_on_picadae_read( self, midi_pitch, mem_id, reg_addr, byteOutN, time_out_ms ):
|
||||
def block_on_picadae_read( self, midi_pitch, mem_id, reg_addr, byteOutN, time_out_ms=250 ):
|
||||
|
||||
i2c_addr = self._pitch_to_i2c_addr( midi_pitch )
|
||||
|
||||
@ -253,26 +253,21 @@ class Picadae:
|
||||
byteOutN = 2
|
||||
return self.block_on_picadae_read( midi_pitch, TinyConst.kRdTableSrcId.value, midi_vel*2, byteOutN, time_out_ms )
|
||||
|
||||
def set_pwm_duty( self, midi_pitch, duty_cycle_pct ):
|
||||
def set_pwm( self, midi_pitch, duty_cycle_pct ):
|
||||
return self.call_op( midi_pitch, TinyOp.setPwmOp.value, [ int( duty_cycle_pct * 255.0 /100.0 )])
|
||||
|
||||
def get_pwm_duty( self, midi_pitch, time_out_ms=250 ):
|
||||
def get_pwm( self, midi_pitch, time_out_ms=250 ):
|
||||
return self.block_on_picadae_read_reg( midi_pitch, TinyRegAddr.kPwmDutyAddr.value, time_out_ms=time_out_ms )
|
||||
|
||||
def set_pwm_freq( self, midi_pitch, freq_div_id ):
|
||||
# pwm frequency divider 1=1,2=8,3=64,4=256,5=1024
|
||||
assert( 1 <= freq_div_id and freq_div_id <= 5 )
|
||||
pass
|
||||
|
||||
def get_pwm_freq( self, midi_pitch, time_out_ms=250 ):
|
||||
return self.block_on_picadae_read_reg( midi_pitch, TinyRegAddr.kPwmFreqAddr.value, time_out_ms=time_out_ms )
|
||||
|
||||
def set_mode( self, midi_pitch, mode ):
|
||||
# TODO validate mode value
|
||||
return self.call_op( midi_pitch, TinyOp.setModeOp.value, [ mode ] )
|
||||
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 )
|
||||
|
||||
def get_mode( self, midi_pitch, time_out_ms=250 ):
|
||||
return self.block_on_picadae_read_reg( midi_pitch, TinyRegAddr.kModeAddr.value, time_out_ms=time_out_ms )
|
||||
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.
|
||||
return self.call_op( midi_pitch, TinyOp.writeTableOp.value,[0])
|
||||
|
||||
def make_note( self, midi_pitch, atk_us, dur_ms ):
|
||||
# TODO: handle error on note_on_us()
|
||||
@ -280,6 +275,10 @@ class Picadae:
|
||||
time.sleep( dur_ms / 1000.0 )
|
||||
return self.note_off(midi_pitch)
|
||||
|
||||
def set_log_level( self, log_level ):
|
||||
self.log_level = log_level
|
||||
return Result()
|
||||
|
||||
def _pitch_to_i2c_addr( self, pitch ):
|
||||
return self.keyMapD[ pitch ]['index'] + self.i2c_base_addr
|
||||
|
||||
@ -306,10 +305,11 @@ class Picadae:
|
||||
|
||||
def _print( self, opcode, i2c_addr, reg_addr, byteL ):
|
||||
|
||||
s = "{} {} {}".format( opcode, i2c_addr, reg_addr )
|
||||
if self.log_level:
|
||||
s = "{} {} {}".format( opcode, i2c_addr, reg_addr )
|
||||
|
||||
for x in byteL:
|
||||
s += " {}".format(x)
|
||||
for x in byteL:
|
||||
s += " {}".format(x)
|
||||
|
||||
|
||||
print(s)
|
||||
print(s)
|
||||
|
@ -7,77 +7,44 @@ class PicadaeShell:
|
||||
def __init__( self, cfg ):
|
||||
self.p = None
|
||||
self.parseD = {
|
||||
'q':{ "func":None, "varN":0, "help":"quit"},
|
||||
'?':{ "func":"help", "varN":0, "help":"Print usage text."},
|
||||
'w':{ "func":"write", "varN":-1, "help":"write <i2c_addr> <reg_addr> <data0> ... <dataN>"},
|
||||
'r':{ "func":"read", "varN":3, "help":"read <i2c_addr> <reg_addr> <byteN>"},
|
||||
'v':{ "func":"note_on_vel", "varN":2, "help":"note-on <pitch> <vel>"},
|
||||
'u':{ "func":"note_on_us", "varN":2, "help":"note-on <pitch> <usec>"},
|
||||
'o':{ "func":"note_off", "varN":1, "help":"note-off <pitch>"},
|
||||
'T':{ "func":"set_vel_map", "varN":3, "help":"table <pitch> <vel> <usec>"},
|
||||
't':{ "func":"get_vel_map", "varN":2, "help":"table <pitch> <vel>"},
|
||||
'D':{ "func":"set_pwm_duty", "varN":2, "help":"duty <pitch> <percent>"},
|
||||
'd':{ "func":"get_pwm_duty", "varN":1, "help":"duty <pitch>"},
|
||||
'F':{ "func":"set_pwm_freq", "varN":2, "help":"freq <pitch> <hz>"},
|
||||
'f':{ "func":"get_pwm_freq", "varN":1, "help":"freq <pitch>"},
|
||||
'M':{ "func":"set_mode", "varN":2, "help":"set_mode <pitch> <mode-bits> (1=repeat 2=pwm)" },
|
||||
'm':{ "func":"get_mode", "varN":1, "help":"get_mode <pitch>"},
|
||||
'N':{ "func":"make_note", "varN":3, "help":"note <pitch> atkUs durMs"},
|
||||
'q':{ "func":None, "minN":0, "maxN":0, "help":"quit"},
|
||||
'?':{ "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>"},
|
||||
'r':{ "func":"_read", "minN":4, "maxN":4, "help":"read <i2c_addr> <src> <reg_addr> <byteN>"},
|
||||
'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)"},
|
||||
'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":"get_vel_map", "minN":2, "maxN":2, "help":"table <pitch> <vel>"},
|
||||
'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" },
|
||||
'd':{ "func":"get_pwm_duty", "minN":1, "maxN":1, "help":"duty <pitch>"},
|
||||
'f':{ "func":"get_pwm_freq", "minN":1, "maxN":1, "help":"freq <pitch>"},
|
||||
'i':{ "func":"get_pwm_div", "minN":1, "maxN":1, "help":"div <pitch>"},
|
||||
'W':{ "func":"write_table", "minN":1, "maxN":1, "help":"write_table <pitch>"},
|
||||
'N':{ "func":"make_note", "minN":3, "maxN":3, "help":"note <pitch> atkUs durMs"},
|
||||
'L':{ "func":"set_log_level","minN":1, "maxN":1, "help":"log <level> (0-1)."}
|
||||
}
|
||||
|
||||
def _do_help( self, _ ):
|
||||
def _help( self, _=None ):
|
||||
for k,d in self.parseD.items():
|
||||
s = "{} = {}".format( k, d['help'] )
|
||||
print(s)
|
||||
return Result()
|
||||
|
||||
def _do_write( self, argL ):
|
||||
def _write( self, argL ):
|
||||
return self.p.write(argL[0], argL[1], argL[2:])
|
||||
|
||||
def _do_read( self, argL ):
|
||||
return self.p.read(*argL)
|
||||
|
||||
def _do_note_on_vel( self, argL ):
|
||||
return self.p.note_on_vel(*argL)
|
||||
|
||||
def _do_note_on_us( self, argL ):
|
||||
return self.p.note_on_us(*argL)
|
||||
|
||||
def _do_note_off( self, argL ):
|
||||
return self.p.note_off(*argL)
|
||||
|
||||
def _do_set_vel_map( self, argL ):
|
||||
return self.p.set_velocity_map(*argL)
|
||||
|
||||
def _do_get_vel_map( self, argL ):
|
||||
return self.p.get_velocity_map(*argL)
|
||||
|
||||
def _do_set_pwm_duty( self, argL ):
|
||||
return self.p.set_pwm_duty(*argL)
|
||||
|
||||
def _do_get_pwm_duty( self, argL ):
|
||||
return self.p.get_pwm_duty(*argL)
|
||||
|
||||
def _do_set_pwm_freq( self, argL ):
|
||||
return self.p.set_pwm_freq(*argL)
|
||||
|
||||
def _do_get_pwm_freq( self, argL ):
|
||||
return self.p.get_pwm_freq(*argL)
|
||||
|
||||
def _do_set_mode( self, argL ):
|
||||
return self.p.set_mode(*argL)
|
||||
|
||||
def _do_get_mode( self, argL ):
|
||||
return self.p.get_mode(*argL)
|
||||
|
||||
def _do_make_note( self, argL ):
|
||||
return self.p.make_note(*argL)
|
||||
def _read( self, argL ):
|
||||
return self.p.block_on_picadae_read(argL[0], argL[1], argL[2], argL[3])
|
||||
|
||||
def _syntaxError( self, msg ):
|
||||
print("Syntax Error: " + msg )
|
||||
return Result()
|
||||
|
||||
def _exec_cmd( self, tokL ):
|
||||
|
||||
result = Result()
|
||||
|
||||
if len(tokL) <= 0:
|
||||
return None
|
||||
|
||||
@ -88,21 +55,29 @@ class PicadaeShell:
|
||||
|
||||
d = self.parseD[ opcode ]
|
||||
|
||||
func_name = "_do_" + d['func']
|
||||
func_name = d['func']
|
||||
func = None
|
||||
|
||||
# find the function associated with this command
|
||||
if hasattr(self, func_name ):
|
||||
func = getattr(self, func_name )
|
||||
func = getattr(self, func_name )
|
||||
elif hasattr(self.p, func_name ):
|
||||
func = getattr(self.p, func_name )
|
||||
else:
|
||||
return self._syntaxError("Exec function not found: '{}'.".format(func_name))
|
||||
|
||||
try:
|
||||
argL = [ int(tokL[i]) for i in range(1,len(tokL)) ]
|
||||
except:
|
||||
return self._syntaxError("Unable to create integer arguments.")
|
||||
try:
|
||||
# convert the parameter list into integers
|
||||
argL = [ int(tokL[i]) for i in range(1,len(tokL)) ]
|
||||
except:
|
||||
return self._syntaxError("Unable to create integer arguments.")
|
||||
|
||||
if d['varN'] != -1 and len(argL) != d['varN']:
|
||||
return self._syntaxError("Argument mismatch {} != {}.".format(len(argL),d['varN']))
|
||||
|
||||
result = func(argL)
|
||||
# validate the count of command args
|
||||
if d['minN'] != -1 and (d['minN'] > len(argL) or len(argL) > d['maxN']):
|
||||
return self._syntaxError("Argument count mismatch. {} is out of range:{} to {}".format(len(argL),d['minN'],d['maxN']))
|
||||
|
||||
# call the command function
|
||||
result = func(*argL)
|
||||
|
||||
return result
|
||||
|
||||
|
@ -35,13 +35,13 @@
|
||||
// Opcodes
|
||||
enum
|
||||
{
|
||||
kSetPwm_Op = 0, // Set PWM registers 0 {<duty> {<freq>}}
|
||||
kNoteOnVel_Op = 1, // Turn on note 1 {<vel>}
|
||||
kNoteOnUsec_Op = 2, // Turn on note 2 {<coarse> {<fine> {<prescale>}}}
|
||||
kNoteOff_Op = 3, // Turn off note 3
|
||||
kSetReadAddr_Op = 4, // Set a read addr. 4 {<src>} {<addr>} } src: 0=reg 1=table 2=eeprom
|
||||
kWrite_Op = 5, // Set write 5 {<addrfl|src> {addr} {<value0> ... {<valueN>}} addrFl:0x80 src: 4=reg 5=table 6=eeprom
|
||||
kSetMode_Op = 6, // Set the mode flags 6 {<mode>} 1=repeat 2=pwm
|
||||
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
|
||||
kNoteOnVel_Op = 1, // Turn on note 3 {<vel>}
|
||||
kNoteOnUsec_Op = 2, // Turn on note 4 {<coarse> {<fine> {<prescale>}}}
|
||||
kNoteOff_Op = 3, // Turn off note 5
|
||||
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
|
||||
kWriteTable_Op = 6, // Write table to EEprom 9
|
||||
kInvalid_Op = 7 //
|
||||
};
|
||||
|
||||
@ -60,33 +60,25 @@ enum
|
||||
|
||||
kTmr_Coarse_idx = 8, //
|
||||
kTmr_Fine_idx = 9, //
|
||||
kTmr_Prescale_idx = 10, // Timer 0 clock divider: 1=1,2=8,3=64,4=256,5=1024 Default: 8 (16us)
|
||||
kTmr_Prescale_idx = 10, // Timer 0 clock divider: 1=1,2=8,3=64,4=256,5=1024 Default: 4 (16us)
|
||||
|
||||
kPwm_Duty_idx = 11, //
|
||||
kPwm_Freq_idx = 12, //
|
||||
kPwm_Div_idx = 13, //
|
||||
|
||||
kMode_idx = 13, // 1=repeat 2=pwm
|
||||
kState_idx = 14, // 1=attk 2=hold
|
||||
kError_Code_idx = 15, // Error Code
|
||||
kMax_Coarse_Tmr_idx = 16, // Max. allowable coarse timer value
|
||||
kMax_idx
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kMode_Repeat_Fl = 1,
|
||||
kMode_Pwm_Fl = 2,
|
||||
kAttk_Fl = 1,
|
||||
kHold_Fl = 2
|
||||
kState_Attk_Fl = 1,
|
||||
kState_Hold_Fl = 2
|
||||
};
|
||||
|
||||
|
||||
#define isInRepeatMode() ctl_regs[ kMode_idx ] & kMode_Repeat_Fl
|
||||
#define isInPwmMode() ctl_regs[ kMode_idx ] & kMode_Pwm_Fl
|
||||
|
||||
// Flags:
|
||||
// 1=Repeat: 1=Timer and PWM are free running. This allows testing with LED's. 0=Timer triggers does not reset on time out.
|
||||
// 2=PWM: On timer timeout 1=PWM HOLD 0=Set HOLD
|
||||
|
||||
volatile uint8_t ctl_regs[] =
|
||||
{
|
||||
0, // 0 (0-(kMax_idx-1)) Reg Read Addr
|
||||
@ -99,26 +91,39 @@ volatile uint8_t ctl_regs[] =
|
||||
0, // 6 (0-255) EE Write Addr
|
||||
kReg_Wr_Addr_idx, // 7 (0-2) Write source
|
||||
|
||||
245, // 8 (0-255) Timer 0 Coarse Value
|
||||
25, // 9 (0-255) Timer 0 Fine Value
|
||||
5, // 8 (0-255) Timer 0 Coarse Value (20400 us)
|
||||
0, // 9 (0-255) Timer 0 Fine Value
|
||||
4, // 10 (1-5) 4=16us per tick
|
||||
|
||||
127, // 11 (0-255) Pwm Duty cycle
|
||||
254, // 12 (0-255) Pwm Frequency (123 Hz)
|
||||
10, // 13 (0-15) Pwm clock div
|
||||
|
||||
kMode_Repeat_Fl, // 13 mode flags 1=Repeat 2=PWM
|
||||
0, // 14 state flags 1=attk 2=hold
|
||||
0, // 14 state flags 1=attk 2=hold (read/only)
|
||||
0, // 15 (0-255) Error bit field
|
||||
14, // 16 (0-255) Max allowable coarse timer count
|
||||
};
|
||||
|
||||
// These registers are saved to Eeprom
|
||||
uint8_t eeprom_addr[] =
|
||||
{
|
||||
kTmr_Prescale_idx,
|
||||
kPwm_Duty_idx,
|
||||
kPwm_Freq_idx,
|
||||
kPwm_Div_idx
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define tableN 256
|
||||
uint8_t table[ tableN ]; // [ coarse_0,fine_0, coarse_1, fine_1, .... coarse_127,fine_127]
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
kInvalid_Read_Src_ErrFl = 0x01,
|
||||
kInvalid_Write_Dst_ErrFl = 0x02
|
||||
kInvalid_Read_Src_ErrFl = 0x01,
|
||||
kInvalid_Write_Dst_ErrFl = 0x02,
|
||||
kInvalid_Coarse_Tmr_ErrFl = 0x04
|
||||
};
|
||||
|
||||
#define set_error( flag ) ctl_regs[ kError_Code_idx ] |= (flag)
|
||||
@ -143,7 +148,6 @@ void EEPROM_write(uint8_t ucAddress, uint8_t ucData)
|
||||
EECR |= (1<<EEPE); // Start eeprom write by setting EEPE
|
||||
}
|
||||
|
||||
|
||||
uint8_t EEPROM_read(uint8_t ucAddress)
|
||||
{
|
||||
// Wait for completion of previous write
|
||||
@ -155,50 +159,33 @@ uint8_t EEPROM_read(uint8_t ucAddress)
|
||||
return EEDR; // Return data from data register
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Read/Write table
|
||||
//
|
||||
|
||||
// To write table value 42 to 127 (coarse) 64 (fine)
|
||||
//
|
||||
// w 8 kTable_Addr_idx 42
|
||||
// w 8 kTable_Coarse_idx 127
|
||||
// w 8 kTable_fine_idx 64
|
||||
//
|
||||
// TO read table value 42
|
||||
// w 8 kTable_Addr_idx 42
|
||||
// r 8 kTable_Coarse_idx -> 127
|
||||
// r 8 kTable_Fine_idx -> 64
|
||||
|
||||
/*
|
||||
#define eeprom_addr( addr ) (kMax_idx + (addr))
|
||||
|
||||
void table_write_cur_value( void )
|
||||
void write_table()
|
||||
{
|
||||
uint8_t tbl_addr = ctl_regs[ kTable_Addr_idx ] * 2;
|
||||
uint8_t i;
|
||||
uint8_t regN = sizeof(eeprom_addr);
|
||||
|
||||
table[ tbl_addr+0 ] = ctl_regs[ kTable_Coarse_idx ];
|
||||
table[ tbl_addr+1 ] = ctl_regs[ kTable_Fine_idx ];
|
||||
// write the persistent registers
|
||||
for(i=0; i<regN; ++i)
|
||||
EEPROM_write( i, ctl_regs[ eeprom_addr[i] ] );
|
||||
|
||||
EEPROM_write( eeprom_addr( tbl_addr+0 ), ctl_regs[ kTable_Coarse_idx ] );
|
||||
EEPROM_write( eeprom_addr( tbl_addr+1 ), ctl_regs[ kTable_Fine_idx ]);
|
||||
// write the table
|
||||
for(i=0; i<tableN; ++i)
|
||||
EEPROM_write( regN+i, table[i] );
|
||||
}
|
||||
|
||||
void table_load( void )
|
||||
void load_table()
|
||||
{
|
||||
uint8_t i = 0;
|
||||
uint8_t i;
|
||||
uint8_t regN = sizeof(eeprom_addr);
|
||||
|
||||
for(; i<128; ++i)
|
||||
{
|
||||
uint8_t tbl_addr = i*2;
|
||||
table[tbl_addr+0] = EEPROM_read( eeprom_addr(tbl_addr+0) );
|
||||
table[tbl_addr+1] = EEPROM_read( eeprom_addr(tbl_addr+1) );
|
||||
}
|
||||
// read the persistent registers
|
||||
for(i=0; i<regN; ++i)
|
||||
ctl_regs[ eeprom_addr[i] ] = EEPROM_read(i);
|
||||
|
||||
// read the tabke
|
||||
for(i=0; i<tableN; ++i)
|
||||
table[i] = EEPROM_read(regN + i);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -208,16 +195,20 @@ void table_load( void )
|
||||
// Timer0
|
||||
//
|
||||
|
||||
volatile uint8_t tmr0_state = 0; // 0=disabled 1=coarse mode, 2=fine mode
|
||||
volatile uint8_t tmr0_state = 0; // current timer mode: 0=disabled 1=coarse mode, 2=fine mode
|
||||
volatile uint8_t tmr0_coarse_cur = 0;
|
||||
|
||||
#define set_attack() do { ctl_regs[kState_idx] |= kAttk_Fl; PORTB |= _BV(ATTK_PIN); } while(0)
|
||||
#define clear_attack() do { PORTB &= ~_BV(ATTK_PIN); ctl_regs[kState_idx] &= ~kAttk_Fl; } while(0)
|
||||
#define set_attack() do { ctl_regs[kState_idx] |= kState_Attk_Fl; PORTB |= _BV(ATTK_PIN); } while(0)
|
||||
#define clear_attack() do { PORTB &= ~_BV(ATTK_PIN); ctl_regs[kState_idx] &= ~kState_Attk_Fl; } while(0)
|
||||
|
||||
|
||||
// Use the current tmr0 ctl_reg[] values to set the timer to the starting state.
|
||||
void tmr0_reset()
|
||||
{
|
||||
tmr0_coarse_cur = 0; // clear the coarse time counter
|
||||
ctl_regs[kState_idx] |= kState_Attk_Fl; // set the attack state
|
||||
PORTB |= _BV(ATTK_PIN); // set the attack pin
|
||||
|
||||
// if a coarse count exists then go into coarse mode
|
||||
if( ctl_regs[kTmr_Coarse_idx] > 0 )
|
||||
{
|
||||
@ -230,11 +221,7 @@ void tmr0_reset()
|
||||
OCR0A = ctl_regs[kTmr_Fine_idx];
|
||||
}
|
||||
|
||||
tmr0_coarse_cur = 0;
|
||||
|
||||
ctl_regs[kState_idx] |= kAttk_Fl; // set the attack state
|
||||
PORTB |= _BV(ATTK_PIN); // set the attack pin
|
||||
TIMSK |= _BV(OCIE0A); // enable the timer interrupt
|
||||
TIMSK |= _BV(OCIE0A); // enable the timer interrupt
|
||||
}
|
||||
|
||||
ISR(TIMER0_COMPA_vect)
|
||||
@ -242,7 +229,7 @@ ISR(TIMER0_COMPA_vect)
|
||||
switch( tmr0_state )
|
||||
{
|
||||
case 0:
|
||||
// disabled
|
||||
// timer is disabled
|
||||
break;
|
||||
|
||||
case 1:
|
||||
@ -257,39 +244,12 @@ ISR(TIMER0_COMPA_vect)
|
||||
case 2:
|
||||
// fine mode
|
||||
|
||||
// If in repeat mode
|
||||
if(ctl_regs[kMode_idx] & kMode_Repeat_Fl)
|
||||
{
|
||||
uint8_t fl = ctl_regs[kState_idx] & kAttk_Fl;
|
||||
// This marks the end of a timer period
|
||||
|
||||
tmr0_reset(); // restart the timer
|
||||
clear_attack();
|
||||
|
||||
// ATTK_PIN is always set after tmr0_reset() but we need to toggle in 'repeat' mode
|
||||
if( fl )
|
||||
{
|
||||
clear_attack();
|
||||
}
|
||||
|
||||
// In repeat mode we run the PWM output continuously
|
||||
TIMSK |= _BV(OCIE1B) + _BV(TOIE1); // Enable PWM interrupts
|
||||
|
||||
}
|
||||
else // not in repeat mode
|
||||
{
|
||||
clear_attack();
|
||||
|
||||
if( ctl_regs[kMode_idx] & kMode_Pwm_Fl)
|
||||
{
|
||||
TIMSK |= _BV(OCIE1B) + _BV(TOIE1); // PWM interupt Enable interrupts
|
||||
}
|
||||
else
|
||||
{
|
||||
PORTB |= _BV(HOLD_PIN); // set the HOLD pin
|
||||
}
|
||||
|
||||
TIMSK &= ~_BV(OCIE0A); // clear timer interrupt
|
||||
|
||||
}
|
||||
TIMSK |= _BV(OCIE1B) + _BV(TOIE1); // PWM interupt Enable interrupts
|
||||
TIMSK &= ~_BV(OCIE0A); // clear timer interrupt
|
||||
|
||||
break;
|
||||
}
|
||||
@ -343,7 +303,7 @@ void pwm1_init()
|
||||
// set on TCNT1 == 0 // happens when TCNT1 matches OCR1C
|
||||
// clr on OCR1B == TCNT // happens when TCNT1 matches OCR1B
|
||||
// // COM1B1=1 COM1B0=0 (enable output on ~OC1B)
|
||||
TCCR1 |= 10; // 32us period (512 divider) prescaler
|
||||
TCCR1 |= ctl_regs[ kPwm_Div_idx]; // 32us period (512 divider) prescaler
|
||||
GTCCR |= _BV(PWM1B); // Enable PWM B and disconnect output pins
|
||||
GTCCR |= _BV(PSR1); // Set the pre-scaler to the selected value
|
||||
|
||||
@ -487,18 +447,36 @@ void on_receive( uint8_t byteN )
|
||||
switch( op_id )
|
||||
{
|
||||
case kSetPwm_Op:
|
||||
for(i=0; i<stack_idx && i<2; ++i)
|
||||
for(i=0; i<stack_idx && i<3; ++i)
|
||||
ctl_regs[ kPwm_Duty_idx + i ] = stack[i];
|
||||
|
||||
// if the PWM prescaler was changed
|
||||
if( i == 3 )
|
||||
pwm1_init();
|
||||
|
||||
pwm1_update();
|
||||
break;
|
||||
|
||||
|
||||
case kNoteOnUsec_Op:
|
||||
for(i=0; i<stack_idx && i<3; ++i)
|
||||
ctl_regs[ kTmr_Coarse_idx + i ] = stack[i];
|
||||
|
||||
// validate the coarse error value
|
||||
if( ctl_regs[ kTmr_Coarse_idx ] > ctl_regs[ kMax_Coarse_Tmr_idx ])
|
||||
{
|
||||
ctl_regs[ kTmr_Coarse_idx ] = ctl_regs[ kMax_Coarse_Tmr_idx ];
|
||||
set_error( kInvalid_Coarse_Tmr_ErrFl );
|
||||
}
|
||||
// if a prescaler was included then the timer needs to be re-initialized
|
||||
if( i == 3 )
|
||||
tmr0_init();
|
||||
|
||||
tmr0_reset();
|
||||
break;
|
||||
|
||||
case kNoteOff_Op:
|
||||
TIMSK &= ~_BV(OCIE0A); // clear timer interrupt (shouldn't be necessary)
|
||||
TIMSK &= ~(_BV(OCIE1B) + _BV(TOIE1)); // PWM interupt disable interrupts
|
||||
PORTB &= ~_BV(HOLD_PIN); // clear the HOLD pin
|
||||
break;
|
||||
@ -517,13 +495,8 @@ void on_receive( uint8_t byteN )
|
||||
_write_op( stack, stack_idx );
|
||||
break;
|
||||
|
||||
case kSetMode_Op:
|
||||
if( stack_idx > 0)
|
||||
{
|
||||
ctl_regs[ kMode_idx ] = stack[0];
|
||||
tmr0_reset();
|
||||
}
|
||||
|
||||
case kWriteTable_Op:
|
||||
write_table();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -550,9 +523,6 @@ int main(void)
|
||||
_delay_ms(1000);
|
||||
PINB = _BV(LED_PIN); // writes to PINB toggle the pins
|
||||
|
||||
// if in repeat mode
|
||||
if( ctl_regs[ kMode_idx ] & kMode_Repeat_Fl)
|
||||
tmr0_reset();
|
||||
|
||||
while(1)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user