Updates to support 16Mhz and reading from register memory from picadae_shell.py.
This commit is contained in:
parent
de586ca2e3
commit
6dc45c0127
@ -5,48 +5,61 @@ from multiprocessing import Process, Pipe
|
|||||||
# Message header id's for messages passed between the application
|
# Message header id's for messages passed between the application
|
||||||
# process and the microcontroller and video processes
|
# process and the microcontroller and video processes
|
||||||
|
|
||||||
TinyOpD = {
|
class TinyOp(Enum):
|
||||||
'setPwmOp': 0,
|
setPwmOp = 0
|
||||||
'noteOnVelOp': 1,
|
noteOnVelOp = 1
|
||||||
'noteOnUsecOp': 2,
|
noteOnUsecOp = 2
|
||||||
'noteOffOp': 3,
|
noteOffOp = 3
|
||||||
'readOp': 4,
|
setReadAddr = 4
|
||||||
'writeOp': 5
|
writeOp = 5
|
||||||
}
|
|
||||||
|
|
||||||
class TinyRegAddr(Enum):
|
class TinyRegAddr(Enum):
|
||||||
kRdRegAddrAddr = 0,
|
kRdRegAddrAddr = 0
|
||||||
kRdTableAddrAddr = 1,
|
kRdTableAddrAddr = 1
|
||||||
kRdEEAddrAddr = 2,
|
kRdEEAddrAddr = 2
|
||||||
kRdSrcAddr = 3,
|
kRdSrcAddr = 3
|
||||||
kWrRegAddrAddr = 4,
|
kWrRegAddrAddr = 4
|
||||||
kWrTableAddrAddr = 5,
|
kWrTableAddrAddr = 5
|
||||||
kWrEEAddrAddr = 6,
|
kWrEEAddrAddr = 6
|
||||||
kWrDstAddr = 7,
|
kWrDstAddr = 7
|
||||||
kTmrCoarseAddr = 8,
|
kTmrCoarseAddr = 8
|
||||||
kTmrFineAddr = 9,
|
kTmrFineAddr = 9
|
||||||
kTmrPrescaleAddr = 10,
|
kTmrPrescaleAddr = 10
|
||||||
kPwmEnableAddr = 11,
|
kPwmDutyAddr = 11
|
||||||
kPwmDutyAddr = 12,
|
kPwmFreqAddr = 12
|
||||||
kPwmFreqAddr = 13,
|
kModeAddr = 13
|
||||||
kModeAddr = 14,
|
kStateAddr = 14
|
||||||
kStateAddr = 15,
|
kErrorCodeAddr = 15
|
||||||
kErrorCodeAddr = 16
|
|
||||||
|
|
||||||
class TinyConst(Enum):
|
class TinyConst(Enum):
|
||||||
kRdRegSrcId = TinyRegAddr.kRdRegAddrAddr, # 0
|
kRdRegSrcId = TinyRegAddr.kRdRegAddrAddr # 0
|
||||||
kRdTableSrcId = TinyRegAddr.kRdTableAddrAddr, # 1
|
kRdTableSrcId = TinyRegAddr.kRdTableAddrAddr # 1
|
||||||
kRdEESrcId = TinyRegAddr.kRdEEAddrAddr # 2
|
kRdEESrcId = TinyRegAddr.kRdEEAddrAddr # 2
|
||||||
|
|
||||||
kWrRegDstId = TinyRegAddr.kWrRegAddrAddr, # 4
|
kWrRegDstId = TinyRegAddr.kWrRegAddrAddr # 4
|
||||||
kWrTableDstId = TinyRegAddr.kWrTableAddrAddr, # 5
|
kWrTableDstId = TinyRegAddr.kWrTableAddrAddr # 5
|
||||||
kWrEEDstId = TinyRegAddr.kWrEEAddrAddr, # 6
|
kWrEEDstId = TinyRegAddr.kWrEEAddrAddr # 6
|
||||||
kWrAddrFl = 0x08, # first avail bit above kWrEEAddr
|
kWrAddrFl = 0x08 # first avail bit above kWrEEAddr
|
||||||
|
|
||||||
class SerialMsgId(Enum):
|
class SerialMsgId(Enum):
|
||||||
QUIT_MSG = 0xffff
|
QUIT_MSG = 0xffff
|
||||||
DATA_MSG = 0xfffe
|
DATA_MSG = 0xfffe
|
||||||
|
|
||||||
|
class Result(object):
|
||||||
|
def __init__( self, value=None, msg=None ):
|
||||||
|
self.value = value
|
||||||
|
self.msg = msg
|
||||||
|
|
||||||
|
def set_error( self, msg ):
|
||||||
|
if self.msg is None:
|
||||||
|
self.msg = ""
|
||||||
|
|
||||||
|
self.msg += " " + msg
|
||||||
|
|
||||||
|
def __bool__( self ):
|
||||||
|
return self.msg is None
|
||||||
|
|
||||||
|
|
||||||
def _serial_process_func( serial_dev, baud, pipe ):
|
def _serial_process_func( serial_dev, baud, pipe ):
|
||||||
|
|
||||||
@ -101,6 +114,7 @@ class SerialProcess(Process):
|
|||||||
super(SerialProcess, self).__init__(target=_serial_process_func, name="Serial", args=(serial_dev,serial_baud,child_end,))
|
super(SerialProcess, self).__init__(target=_serial_process_func, name="Serial", args=(serial_dev,serial_baud,child_end,))
|
||||||
self.doneFl = False
|
self.doneFl = False
|
||||||
|
|
||||||
|
|
||||||
def quit(self):
|
def quit(self):
|
||||||
# send quit msg to the child process
|
# send quit msg to the child process
|
||||||
self.parent_end.send((SerialMsgId.QUIT_MSG,0))
|
self.parent_end.send((SerialMsgId.QUIT_MSG,0))
|
||||||
@ -108,6 +122,7 @@ class SerialProcess(Process):
|
|||||||
def send(self,msg_id,value):
|
def send(self,msg_id,value):
|
||||||
# send a msg to the child process
|
# send a msg to the child process
|
||||||
self.parent_end.send((msg_id,value))
|
self.parent_end.send((msg_id,value))
|
||||||
|
return Result()
|
||||||
|
|
||||||
def recv(self):
|
def recv(self):
|
||||||
#
|
#
|
||||||
@ -127,7 +142,7 @@ class SerialProcess(Process):
|
|||||||
|
|
||||||
|
|
||||||
class Picadae:
|
class Picadae:
|
||||||
def __init__( self, key_mapL, i2c_base_addr=1, serial_dev='/dev/ttyACM0', serial_baud=38400 ):
|
def __init__( self, key_mapL, i2c_base_addr=21, serial_dev='/dev/ttyACM0', serial_baud=38400, prescaler_usec=16 ):
|
||||||
"""
|
"""
|
||||||
key_mapL = [{ index, board, ch, type, midi, class }]
|
key_mapL = [{ index, board, ch, type, midi, class }]
|
||||||
serial_dev = /dev/ttyACM0
|
serial_dev = /dev/ttyACM0
|
||||||
@ -137,65 +152,86 @@ class Picadae:
|
|||||||
self.serialProc = SerialProcess( serial_dev, serial_baud )
|
self.serialProc = SerialProcess( serial_dev, serial_baud )
|
||||||
self.keyMapD = { d['midi']:d for d in key_mapL }
|
self.keyMapD = { d['midi']:d for d in key_mapL }
|
||||||
self.i2c_base_addr = i2c_base_addr
|
self.i2c_base_addr = i2c_base_addr
|
||||||
self.prescaler_usec = 32
|
self.prescaler_usec = prescaler_usec
|
||||||
|
|
||||||
self.serialProc.start()
|
self.serialProc.start()
|
||||||
|
|
||||||
def close( self ):
|
def close( self ):
|
||||||
self.serialProc.quit()
|
self.serialProc.quit()
|
||||||
|
|
||||||
|
def wait_for_serial_sync(self, timeoutMs=10000):
|
||||||
|
|
||||||
|
# wait for the letter 'a' to come back from the serial port
|
||||||
|
result = self.block_on_serial_read(1,timeoutMs)
|
||||||
|
|
||||||
|
if result and len(result.value)>0 and result.value[0] == ord('a'):
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
result.set_error("Serial sync failed.")
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
def write( self, i2c_addr, reg_addr, byteL ):
|
def write( self, i2c_addr, reg_addr, byteL ):
|
||||||
return self._send( 'w', i2c_addr, reg_addr, [ len(byteL) ] + byteL )
|
return self._send( 'w', i2c_addr, reg_addr, [ len(byteL) ] + byteL )
|
||||||
|
|
||||||
def set_read_addr( self, i2c_addr, src, addr ):
|
def set_read_addr( self, i2c_addr, mem_id, addr ):
|
||||||
return self. write(i2c_addr, TinyOpD['readOp'], src, addr )
|
return self. write(i2c_addr, TinyOp.setReadAddr.value,[ mem_id, addr ])
|
||||||
|
|
||||||
def set_reg_read_addr( self, i2c_addr, addr ):
|
def read_request( self, i2c_addr, reg_addr, byteOutN ):
|
||||||
return self.set_read_addr(i2c_addr, TinyRegAddr.kRdRegAddrAddr, addr )
|
return self._send( 'r', i2c_addr, reg_addr,[ byteOutN ] )
|
||||||
|
|
||||||
def set_table_read_addr( self, i2c_addr, addr ):
|
def block_on_serial_read( self, byteOutN, time_out_ms=250 ):
|
||||||
return self.set_read_addr(i2c_addr, TinyRegAddr.kRdTableAddrAddr, addr )
|
|
||||||
|
|
||||||
def set_eeprom_read_addr( self, i2c_addr, addr ):
|
|
||||||
return self.set_read_addr(i2c_addr, TinyRegAddr.kRdEEAddrAddr, addr )
|
|
||||||
|
|
||||||
def read_request( self, i2c_addr, reg_addr, argL ):
|
|
||||||
return self._send( 'r', i2c_addr, reg_addr, [ byteOutN, len(argL) ] + argL )
|
|
||||||
|
|
||||||
def read_poll( self ):
|
|
||||||
return self.serialProc.recv()
|
|
||||||
|
|
||||||
def read_block( self, i2c_addr, reg_addr, argL, byteOutN, time_out_ms ):
|
|
||||||
|
|
||||||
self.read_request( self, i2c_addr, reg_addr, argL, byteOutN )
|
|
||||||
|
|
||||||
ts = datetime.datetime.now() + datetime.timeDelta(milliseconds=time_out_ms)
|
|
||||||
|
|
||||||
|
ts = datetime.datetime.now() + datetime.timedelta(milliseconds=time_out_ms)
|
||||||
retL = []
|
retL = []
|
||||||
|
|
||||||
while datetime.datetime.now() < ts and len(retL) < byteOutN:
|
while datetime.datetime.now() < ts and len(retL) < byteOutN:
|
||||||
|
|
||||||
|
# If a value is available at the serial port return is otherwise return None.
|
||||||
x = self.serialProc.recv()
|
x = self.serialProc.recv()
|
||||||
if x is not None:
|
|
||||||
retL.append(x)
|
if x is not None and x[0] == SerialMsgId.DATA_MSG:
|
||||||
|
for b in x[1]:
|
||||||
|
retL.append(int(b))
|
||||||
|
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
|
|
||||||
return retL
|
result = Result(value=retL)
|
||||||
|
|
||||||
|
if len(retL) < byteOutN:
|
||||||
|
result.set_error("Serial port time out on read.")
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def block_on_picadae_read( self, i2c_addr, mem_id, reg_addr, argL, byteOutN, time_out_ms ):
|
||||||
|
|
||||||
|
result = self.set_read_addr( i2c_addr, mem_id, reg_addr )
|
||||||
|
|
||||||
|
if result:
|
||||||
|
result = self.read_request( i2c_addr, TinyOp.setReadAddr.value, byteOutN )
|
||||||
|
|
||||||
|
if result:
|
||||||
|
result = self.block_on_serial_read( byteOutN, time_out_ms )
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def note_on_vel( self, midi_pitch, midi_vel ):
|
def note_on_vel( self, midi_pitch, midi_vel ):
|
||||||
return self.write( self._pitch_to_i2c_addr( midi_pitch ),
|
return self.write( self._pitch_to_i2c_addr( midi_pitch ),
|
||||||
TinyOpD['noteOnVelOp'],
|
TinyOp.noteOnVelOp.value,
|
||||||
[self._validate_vel(midi_vel)] )
|
[self._validate_vel(midi_vel)] )
|
||||||
|
|
||||||
def note_on_us( self, midi_pitch, pulse_usec ):
|
def note_on_us( self, midi_pitch, pulse_usec ):
|
||||||
return self.write( self._pitch_to_i2c_addr( midi_pitch ),
|
return self.write( self._pitch_to_i2c_addr( midi_pitch ),
|
||||||
TinyOpD['noteOnUsecOp'],
|
TinyOp.noteOnUsecOp.value,
|
||||||
list(self._usec_to_coarse_and_fine(pulse_usec)) )
|
list(self._usec_to_coarse_and_fine(pulse_usec)) )
|
||||||
|
|
||||||
def note_off( self, midi_pitch ):
|
def note_off( self, midi_pitch ):
|
||||||
return self.write( self._pitch_to_i2c_addr( midi_pitch ),
|
return self.write( self._pitch_to_i2c_addr( midi_pitch ),
|
||||||
TinyOpD['noteOffOp'],[0] ) # TODO: sending a dummy byte because we can handle sending a command with no data bytes.
|
TinyOp.noteOffOp.value,
|
||||||
|
[0] ) # TODO: sending a dummy byte because we can't handle sending a command with no data bytes.
|
||||||
|
|
||||||
def set_velocity_map( self, midi_pitch, midi_vel, pulse_usec ):
|
def set_velocity_map( self, midi_pitch, midi_vel, pulse_usec ):
|
||||||
pass
|
pass
|
||||||
@ -203,14 +239,15 @@ class Picadae:
|
|||||||
def get_velocity_map( self, midi_pitch, midi_vel, time_out_ms=250 ):
|
def get_velocity_map( self, midi_pitch, midi_vel, time_out_ms=250 ):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def set_pwm_duty( self, midi_pitch, duty_cycle_pct, enableFl=True ):
|
def set_pwm_duty( self, midi_pitch, duty_cycle_pct ):
|
||||||
return self.write( self._pitch_to_i2c_addr( midi_pitch ),
|
return self.write( self._pitch_to_i2c_addr( midi_pitch ),
|
||||||
TinyOpD['setPwmOp'],
|
TinyOp.setPwmOp.value,
|
||||||
[enableFl, int( duty_cycle_pct * 255.0 /100.0 )])
|
[ int( duty_cycle_pct * 255.0 /100.0 )])
|
||||||
|
|
||||||
def get_pwm_duty( self, midi_pitch, time_out_ms=250 ):
|
def get_pwm_duty( self, midi_pitch, time_out_ms=250 ):
|
||||||
return self.read_block( self._pitch_to_i2c_addr( midi_pitch ),
|
return self.block_on_picadae_read( self._pitch_to_i2c_addr( midi_pitch ),
|
||||||
TinyRegAddr.kPwmDutyAddr,
|
TinyRegAddr.kRdRegAddrAddr.value,
|
||||||
|
TinyRegAddr.kPwmDutyAddr.value,
|
||||||
[], 1, time_out_ms )
|
[], 1, time_out_ms )
|
||||||
|
|
||||||
def set_pwm_freq( self, midi_pitch, freq_div_id ):
|
def set_pwm_freq( self, midi_pitch, freq_div_id ):
|
||||||
@ -219,13 +256,14 @@ class Picadae:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def get_pwm_freq( self, midi_pitch, time_out_ms=250 ):
|
def get_pwm_freq( self, midi_pitch, time_out_ms=250 ):
|
||||||
return self.read_block( self._pitch_to_i2c_addr( midi_pitch ),
|
return self.block_on_picadae_read( self._pitch_to_i2c_addr( midi_pitch ),
|
||||||
TinyRegAddr.kPwmFreqAddr,
|
TinyRegAddr.kRdRegAddrAddr.value,
|
||||||
|
TinyRegAddr.kPwmFreqAddr.value,
|
||||||
[], 1, time_out_ms )
|
[], 1, time_out_ms )
|
||||||
|
|
||||||
def set_flags( self, midi_pitch, flags ):
|
def set_flags( self, midi_pitch, flags ):
|
||||||
return self.write( self._pitch_to_i2c_addr( midi_pitch ),
|
return self.write( self._pitch_to_i2c_addr( midi_pitch ),
|
||||||
TinyOpD['writeOp'],
|
TinyOp.writeOp.value,
|
||||||
[ 12, 14, flags ])
|
[ 12, 14, flags ])
|
||||||
|
|
||||||
def make_note( self, midi_pitch, atk_us, dur_ms ):
|
def make_note( self, midi_pitch, atk_us, dur_ms ):
|
||||||
@ -245,7 +283,6 @@ class Picadae:
|
|||||||
coarse = int( usec / (self.prescaler_usec*255))
|
coarse = int( usec / (self.prescaler_usec*255))
|
||||||
fine = int((usec - coarse*self.prescaler_usec*255) / self.prescaler_usec)
|
fine = int((usec - coarse*self.prescaler_usec*255) / self.prescaler_usec)
|
||||||
|
|
||||||
print(coarse,fine)
|
|
||||||
assert( coarse <= 255 )
|
assert( coarse <= 255 )
|
||||||
assert( fine <= 255)
|
assert( fine <= 255)
|
||||||
|
|
||||||
|
@ -276,6 +276,11 @@ class App:
|
|||||||
# form the command into a byte array
|
# form the command into a byte array
|
||||||
cmd_bV = bytearray( [ ord(op_code), i2c_addr, reg_addr, op_byteN ] + dataL )
|
cmd_bV = bytearray( [ ord(op_code), i2c_addr, reg_addr, op_byteN ] + dataL )
|
||||||
|
|
||||||
|
# s = ""
|
||||||
|
# for i in range(len(cmd_bV)):
|
||||||
|
# s += "%i " % (cmd_bV[i])
|
||||||
|
# print(s)
|
||||||
|
|
||||||
return (cmd_bV,None)
|
return (cmd_bV,None)
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,7 +4,8 @@
|
|||||||
serial_dev: "/dev/ttyACM0",
|
serial_dev: "/dev/ttyACM0",
|
||||||
serial_baud: 38400,
|
serial_baud: 38400,
|
||||||
i2c_base_addr: 21,
|
i2c_base_addr: 21,
|
||||||
prescaler_usec: 32,
|
prescaler_usec: 16,
|
||||||
|
serial_sync_timeout_ms: 10000,
|
||||||
|
|
||||||
key_mapL: [
|
key_mapL: [
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import os,sys,argparse,yaml,types,select,serial,logging,time
|
import os,sys,argparse,yaml,types,select,serial,logging,time
|
||||||
|
|
||||||
from picadae_api import Picadae
|
from picadae_api import Picadae
|
||||||
|
from picadae_api import Result
|
||||||
|
|
||||||
class PicadaeShell:
|
class PicadaeShell:
|
||||||
def __init__( self, cfg ):
|
def __init__( self, cfg ):
|
||||||
@ -27,6 +28,7 @@ class PicadaeShell:
|
|||||||
for k,d in self.parseD.items():
|
for k,d in self.parseD.items():
|
||||||
s = "{} = {}".format( k, d['help'] )
|
s = "{} = {}".format( k, d['help'] )
|
||||||
print(s)
|
print(s)
|
||||||
|
return Result()
|
||||||
|
|
||||||
def _do_write( self, argL ):
|
def _do_write( self, argL ):
|
||||||
return self.p.write(argL[0], argL[1], argL[2:])
|
return self.p.write(argL[0], argL[1], argL[2:])
|
||||||
@ -69,7 +71,7 @@ class PicadaeShell:
|
|||||||
|
|
||||||
def _syntaxError( self, msg ):
|
def _syntaxError( self, msg ):
|
||||||
print("Syntax Error: " + msg )
|
print("Syntax Error: " + msg )
|
||||||
return None
|
return Result()
|
||||||
|
|
||||||
def _exec_cmd( self, tokL ):
|
def _exec_cmd( self, tokL ):
|
||||||
if len(tokL) <= 0:
|
if len(tokL) <= 0:
|
||||||
@ -97,34 +99,46 @@ class PicadaeShell:
|
|||||||
|
|
||||||
result = func(argL)
|
result = func(argL)
|
||||||
|
|
||||||
return None
|
|
||||||
|
return result
|
||||||
|
|
||||||
def run( self ):
|
def run( self ):
|
||||||
|
|
||||||
# create the API object
|
# create the API object
|
||||||
self.p = Picadae( cfg.key_mapL, cfg.i2c_base_addr, cfg.serial_dev, cfg.serial_baud )
|
self.p = Picadae( cfg.key_mapL, cfg.i2c_base_addr, cfg.serial_dev, cfg.serial_baud, cfg.prescaler_usec )
|
||||||
|
|
||||||
print("'q'=quit '?'=help")
|
# wait for the letter 'a' to come back from the serial port
|
||||||
time_out_secs = 1
|
result = self.p.wait_for_serial_sync(timeoutMs=cfg.serial_sync_timeout_ms)
|
||||||
|
|
||||||
while True:
|
if not result:
|
||||||
|
print("Serial port sync failed.")
|
||||||
|
else:
|
||||||
|
print(result.value)
|
||||||
|
|
||||||
# wait for keyboard activity
|
print("'q'=quit '?'=help")
|
||||||
i, o, e = select.select( [sys.stdin], [], [], time_out_secs )
|
time_out_secs = 1
|
||||||
|
|
||||||
if (i):
|
while True:
|
||||||
# read the command
|
|
||||||
s = sys.stdin.readline().strip()
|
|
||||||
|
|
||||||
# tokenize the command
|
# wait for keyboard activity
|
||||||
tokL = s.split(' ')
|
i, o, e = select.select( [sys.stdin], [], [], time_out_secs )
|
||||||
|
|
||||||
# if this is the 'quit' command
|
if (i):
|
||||||
if tokL[0] == 'q':
|
# read the command
|
||||||
break
|
s = sys.stdin.readline().strip()
|
||||||
|
|
||||||
# execute the command
|
# tokenize the command
|
||||||
self._exec_cmd( tokL )
|
tokL = s.split(' ')
|
||||||
|
|
||||||
|
# if this is the 'quit' command
|
||||||
|
if tokL[0] == 'q':
|
||||||
|
break
|
||||||
|
|
||||||
|
# execute the command
|
||||||
|
result = self._exec_cmd( tokL )
|
||||||
|
|
||||||
|
if result.value:
|
||||||
|
print(result.value)
|
||||||
|
|
||||||
|
|
||||||
self.p.close()
|
self.p.close()
|
||||||
|
@ -21,12 +21,15 @@ AVRDUDE=avrdude
|
|||||||
# /usr/bin/avrdude -C/etc/avrdude/avrdude.conf -v -pattiny85 -cstk500v1 -P/dev/ttyACM0 -b19200 -Uflash:w:/tmp/arduino_build_108059/i2c.ino.hex:i
|
# /usr/bin/avrdude -C/etc/avrdude/avrdude.conf -v -pattiny85 -cstk500v1 -P/dev/ttyACM0 -b19200 -Uflash:w:/tmp/arduino_build_108059/i2c.ino.hex:i
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# lfuse=0xe2 = 8 Mghz
|
||||||
|
# lfuse=0xe1 = 16 Mghz
|
||||||
|
|
||||||
all:
|
all:
|
||||||
$(CC) $(CFLAGS) $(TARGET).c usiTwiSlave.c -o$(TARGET)
|
$(CC) $(CFLAGS) $(TARGET).c usiTwiSlave.c -o$(TARGET)
|
||||||
$(OBJ2HEX) -R .eeprom -O ihex $(TARGET) $(TARGET).hex
|
$(OBJ2HEX) -R .eeprom -O ihex $(TARGET) $(TARGET).hex
|
||||||
|
|
||||||
burn:
|
burn:
|
||||||
$(AVRDUDE) -p $(MCU) -P $(TTY) -C/etc/avrdude/avrdude.conf -v -c avrisp -b 19200 -U flash:w:$(TARGET).hex -U lfuse:w:0xe2:m -U hfuse:w:0xdd:m -U efuse:w:0xff:m
|
$(AVRDUDE) -p $(MCU) -P $(TTY) -C/etc/avrdude/avrdude.conf -v -c avrisp -b 19200 -U flash:w:$(TARGET).hex -U lfuse:w:0xe1:m -U hfuse:w:0xdd:m -U efuse:w:0xff:m
|
||||||
clean:
|
clean:
|
||||||
rm -f *.hex *.obj *.o
|
rm -f *.hex *.obj *.o
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
|
|
||||||
// This program acts as the device (slave) for the control program i2c/a2a/c_ctl
|
// This program acts as the device (slave) for the control program i2c/a2a/c_ctl
|
||||||
#define F_CPU 8000000L
|
#define F_CPU 16000000L
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <avr/io.h>
|
#include <avr/io.h>
|
||||||
@ -35,13 +35,15 @@
|
|||||||
// Opcodes
|
// Opcodes
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
kSetPwm_Op = 0, // Set PWM registers 0 {<enable> {<duty> {<freq>}}}
|
kSetPwm_Op = 0, // Set PWM registers 0 {<duty> {<freq>}}
|
||||||
kNoteOnVel_Op = 1, // Turn on note 1 {<vel>}
|
kNoteOnVel_Op = 1, // Turn on note 1 {<vel>}
|
||||||
kNoteOnUsec_Op = 2, // Turn on note 2 {<coarse> {<fine> {<prescale>}}}
|
kNoteOnUsec_Op = 2, // Turn on note 2 {<coarse> {<fine> {<prescale>}}}
|
||||||
kNoteOff_Op = 3, // Turn off note 3
|
kNoteOff_Op = 3, // Turn off note 3
|
||||||
kRead_Op = 4, // Read a value 4 {<src>} {<addr>} } src: 0=reg 1=table 2=eeprom
|
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>}}
|
kWrite_Op = 5, // Set write 5 {<addrfl|src> {addr} {<value0> ... {<valueN>}} addrFl:0x80 src: 4=reg 5=table 6=eeprom
|
||||||
kInvalid_Op = 6 // addrFl:0x80 src: 4=reg 5=table 6=eeprom
|
kSetMode_Op = 6, // Set the mode flags 6 {<mode>} 1=repeat 2=pwm
|
||||||
|
|
||||||
|
kInvalid_Op = 7 //
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -59,26 +61,29 @@ enum
|
|||||||
|
|
||||||
kTmr_Coarse_idx = 8, //
|
kTmr_Coarse_idx = 8, //
|
||||||
kTmr_Fine_idx = 9, //
|
kTmr_Fine_idx = 9, //
|
||||||
kTmr_Prescale_idx = 10, // Timer 0 clock divider: 1=1,2=8,3=64,4=256,5=1024 Default: 8 (32us)
|
kTmr_Prescale_idx = 10, // Timer 0 clock divider: 1=1,2=8,3=64,4=256,5=1024 Default: 8 (16us)
|
||||||
|
|
||||||
kPwm_Enable_idx = 11, //
|
kPwm_Duty_idx = 11, //
|
||||||
kPwm_Duty_idx = 12, //
|
kPwm_Freq_idx = 12, //
|
||||||
kPwm_Freq_idx = 13, //
|
|
||||||
|
|
||||||
kMode_idx = 14, // 1=repeat 2=pwm
|
kMode_idx = 13, // 1=repeat 2=pwm
|
||||||
kState_idx = 15, // 1=attk 2=hold
|
kState_idx = 14, // 1=attk 2=hold
|
||||||
kError_Code_idx = 16, // Error Code
|
kError_Code_idx = 15, // Error Code
|
||||||
kMax_idx
|
kMax_idx
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
kTmr_Repeat_Fl= 1,
|
kMode_Repeat_Fl = 1,
|
||||||
kTmr_Pwm_Fl = 2,
|
kMode_Pwm_Fl = 2,
|
||||||
kAttk_Fl = 1,
|
kAttk_Fl = 1,
|
||||||
kHold_Fl = 2
|
kHold_Fl = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define isInRepeatMode() ctl_regs[ kMode_idx ] & kMode_Repeat_Fl
|
||||||
|
#define isInPwmMode() ctl_regs[ kMode_idx ] & kMode_Pwm_Fl
|
||||||
|
|
||||||
// Flags:
|
// 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.
|
// 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
|
// 2=PWM: On timer timeout 1=PWM HOLD 0=Set HOLD
|
||||||
@ -93,15 +98,14 @@ volatile uint8_t ctl_regs[] =
|
|||||||
0, // 5 (0-255) Table Write Addr
|
0, // 5 (0-255) Table Write Addr
|
||||||
0, // 6 (0-255) EE Write Addr
|
0, // 6 (0-255) EE Write Addr
|
||||||
kReg_Wr_Addr_idx, // 7 (0-2) Write source
|
kReg_Wr_Addr_idx, // 7 (0-2) Write source
|
||||||
123, // 8 (0-255) Timer 0 Coarse Value
|
245, // 8 (0-255) Timer 0 Coarse Value
|
||||||
8, // 9 (0-255) Timer 0 Fine Value
|
25, // 9 (0-255) Timer 0 Fine Value
|
||||||
4, // 10 (1-5) 4=32us per tick
|
4, // 10 (1-5) 4=16us per tick
|
||||||
1, // 11 (0-1) Pwm Enable Flag
|
127, // 11 (0-255) Pwm Duty cycle
|
||||||
127, // 12 (0-255) Pwm Duty cycle
|
254, // 12 (0-255) Pwm Frequency (123 hz)
|
||||||
254, // 13 (0-255) Pwm Frequency (123 hz)
|
kMode_Repeat_Fl, // 13 mode flags 1=Repeat 2=PWM
|
||||||
0, // 14 mode flags 1=Repeat 2=PWM
|
0, // 14 state flags 1=attk 2=hold
|
||||||
0, // 15 state flags 1=attk 2=hold
|
0, // 15 (0-255) Error bit field
|
||||||
0, // 16 (0-255) Error bit field
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define tableN 256
|
#define tableN 256
|
||||||
@ -251,7 +255,7 @@ ISR(TIMER0_COMPA_vect)
|
|||||||
// fine mode
|
// fine mode
|
||||||
|
|
||||||
// If in repeat mode
|
// If in repeat mode
|
||||||
if(ctl_regs[kMode_idx] & kTmr_Repeat_Fl)
|
if(ctl_regs[kMode_idx] & kMode_Repeat_Fl)
|
||||||
{
|
{
|
||||||
uint8_t fl = ctl_regs[kState_idx] & kAttk_Fl;
|
uint8_t fl = ctl_regs[kState_idx] & kAttk_Fl;
|
||||||
|
|
||||||
@ -271,7 +275,7 @@ ISR(TIMER0_COMPA_vect)
|
|||||||
{
|
{
|
||||||
clear_attack();
|
clear_attack();
|
||||||
|
|
||||||
if( ctl_regs[kMode_idx] & kTmr_Pwm_Fl)
|
if( ctl_regs[kMode_idx] & kMode_Pwm_Fl)
|
||||||
{
|
{
|
||||||
TIMSK |= _BV(OCIE1B) + _BV(TOIE1); // PWM interupt Enable interrupts
|
TIMSK |= _BV(OCIE1B) + _BV(TOIE1); // PWM interupt Enable interrupts
|
||||||
}
|
}
|
||||||
@ -289,17 +293,13 @@ ISR(TIMER0_COMPA_vect)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void timer0_init()
|
void tmr0_init()
|
||||||
{
|
{
|
||||||
TIMSK &= ~_BV(OCIE0A); // Disable interrupt TIMER1_OVF
|
TIMSK &= ~_BV(OCIE0A); // Disable interrupt TIMER1_OVF
|
||||||
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); // Set the pre-scaler to the selected value
|
||||||
|
|
||||||
//tmr0_reset(); // set the timers starting state
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -341,7 +341,7 @@ void pwm1_init()
|
|||||||
// set on TCNT1 == 0 // happens when TCNT1 matches OCR1C
|
// set on TCNT1 == 0 // happens when TCNT1 matches OCR1C
|
||||||
// clr on OCR1B == TCNT // happens when TCNT1 matches OCR1B
|
// clr on OCR1B == TCNT // happens when TCNT1 matches OCR1B
|
||||||
// // COM1B1=1 COM1B0=0 (enable output on ~OC1B)
|
// // COM1B1=1 COM1B0=0 (enable output on ~OC1B)
|
||||||
TCCR1 |= 9; // 32us period (256 divider) prescaler
|
TCCR1 |= 10; // 32us period (512 divider) prescaler
|
||||||
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
|
GTCCR |= _BV(PSR1); // Set the pre-scaler to the selected value
|
||||||
|
|
||||||
@ -485,13 +485,13 @@ void on_receive( uint8_t byteN )
|
|||||||
switch( op_id )
|
switch( op_id )
|
||||||
{
|
{
|
||||||
case kSetPwm_Op:
|
case kSetPwm_Op:
|
||||||
for(i=0; i<stack_idx; ++i)
|
for(i=0; i<stack_idx && i<2; ++i)
|
||||||
ctl_regs[ kPwm_Enable_idx + i ] = stack[i];
|
ctl_regs[ kPwm_Duty_idx + i ] = stack[i];
|
||||||
pwm1_update();
|
pwm1_update();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kNoteOnUsec_Op:
|
case kNoteOnUsec_Op:
|
||||||
for(i=0; i<stack_idx; ++i)
|
for(i=0; i<stack_idx && i<3; ++i)
|
||||||
ctl_regs[ kTmr_Coarse_idx + i ] = stack[i];
|
ctl_regs[ kTmr_Coarse_idx + i ] = stack[i];
|
||||||
tmr0_reset();
|
tmr0_reset();
|
||||||
break;
|
break;
|
||||||
@ -501,8 +501,7 @@ void on_receive( uint8_t byteN )
|
|||||||
PORTB &= ~_BV(HOLD_PIN); // clear the HOLD pin
|
PORTB &= ~_BV(HOLD_PIN); // clear the HOLD pin
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case kSetReadAddr_Op:
|
||||||
case kRead_Op:
|
|
||||||
if( stack_idx > 0 )
|
if( stack_idx > 0 )
|
||||||
{
|
{
|
||||||
ctl_regs[ kRead_Src_idx ] = stack[0];
|
ctl_regs[ kRead_Src_idx ] = stack[0];
|
||||||
@ -515,6 +514,15 @@ void on_receive( uint8_t byteN )
|
|||||||
case kWrite_Op:
|
case kWrite_Op:
|
||||||
_write_op( stack, stack_idx );
|
_write_op( stack, stack_idx );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case kSetMode_Op:
|
||||||
|
if( stack_idx > 0)
|
||||||
|
{
|
||||||
|
ctl_regs[ kMode_idx ] = stack[0];
|
||||||
|
tmr0_reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -523,12 +531,10 @@ int main(void)
|
|||||||
{
|
{
|
||||||
cli(); // mask all interupts
|
cli(); // mask all interupts
|
||||||
|
|
||||||
|
|
||||||
DDRB |= _BV(ATTK_DIR) + _BV(HOLD_DIR) + _BV(LED_DIR); // setup PB4,PB3,PB1 as output
|
DDRB |= _BV(ATTK_DIR) + _BV(HOLD_DIR) + _BV(LED_DIR); // setup PB4,PB3,PB1 as output
|
||||||
PORTB &= ~(_BV(ATTK_PIN) + _BV(HOLD_PIN) + _BV(LED_PIN)); // clear output pins
|
PORTB &= ~(_BV(ATTK_PIN) + _BV(HOLD_PIN) + _BV(LED_PIN)); // clear output pins
|
||||||
|
|
||||||
|
tmr0_init();
|
||||||
timer0_init();
|
|
||||||
pwm1_init();
|
pwm1_init();
|
||||||
|
|
||||||
// setup i2c library
|
// setup i2c library
|
||||||
@ -542,10 +548,12 @@ int main(void)
|
|||||||
_delay_ms(1000);
|
_delay_ms(1000);
|
||||||
PINB = _BV(LED_PIN); // writes to PINB toggle the pins
|
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)
|
while(1)
|
||||||
{
|
{
|
||||||
//_delay_ms(1000);
|
|
||||||
|
|
||||||
if (!usi_onReceiverPtr)
|
if (!usi_onReceiverPtr)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user