def tone(self,who,val,unused=None,force=False): # who is 'M','A','B','C','D','TR' if force or val != self.preset.currentDict[who][1]: State.printT('TONE:\t' + str(who) +'\t' + str(val)) trVal = 'Off' toneVal = '0' if who =='TR': trVal = str(val-1) if val else 'Off' targ = 'M' toneVal = None elif who == 'M': targ = who trVal = None toneVal = str(val-1) if val else 'Off' self.mEval.set(1,val) else: targ = who trVal = '0' if val else 'Off' toneVal = str(val-1) if val else 'Off' if trVal != None: #self.outgoing.append("a.set('%s',State.ToneRange,State.l%s)"%(targ,trVal)) self.set(targ,State.ToneRange,eval('State.l%s'%trVal)) if toneVal != None: #self.outgoing.append("a.set('%s',State.Tone,State.l%s)"%(targ,toneVal)) self.set(targ,State.Tone,eval('State.l%s'%toneVal)) self.preset.currentDict[who][1] = val return True return False
def update(self,name, att, state=State.connectionUpdateOnly): """ To call update(...) on name, att, state >>> update('A',State.Inverter,State.l2) To call update(...) on connections >>> update(('A',0),('B',1)) this method sets up the call to doSettingMasking which makes the member variable assignments --- Note that there is a procedural difference between updating a Vol, Tone,ToneRang, Inverter setting, and updating a connection setting. In the former case, the non-affecting attributes are maintained. In the latter case, all the connection settings are reset prior to updating. Examples: If we had 'A', Vol, l3 already, then we set 'A', Inverter, 1, then both the vol and inverter settings are maintained. But if we have some connections and we add are starting a new one then the previous ones are erased. However, if we have already started adding connections, then the previous NEW ones are maintained. """ if state == State.connectionUpdateOnly: self.doSettingMasking(connectionsDict[(name,att)],[]) else: # all states can be 'State.lOff', ie None ! onOff = not state == State.lOff (setting, masking) = BitMgr.baseFunc(onOff, name, att, state) State.printT(setting,masking) # this is ok! # for a.set('A',State.Inverter,State.l0) # ((4, 0), (4, 3)) ((4, 240),) self.doSettingMasking(setting,masking)
def pb0Func(self): if self.sequencing: State.printT('pb0Func:\tstepping the sequence...') #State.debug and input('Press Return:') return self.doNextSeq() else: return false
def loadConf(self, conf): try: #res = self.doParse(conf[self.conf.vocab.configKeys[7]]) self.doParse(conf[self.conf.vocab.configKeys[7]]) """ for e in res: #print(e) self.outgoing.append(e) """ for key in self.preset.currentDict.keys(): self.preset.currentDict[key] = conf[key] except Exception as e: print (e) self.doParse(self.conf.presetConf.defaultConfDict[self.conf.vocab.configKeys[7]]) for key in self.conf.presetConf.defaultConfDict.keys(): self.preset.currentDict[key] = self.conf.presetConf.defaultConfDict[key] self.preset.currentDict[self.conf.vocab.configKeys[0]] = 'DEFAULT PRESET' self.tone('TR',self.preset.currentDict['TR'][1],force=True) for c in ['A','B','C','D','M']: self.vol(c,self.preset.currentDict[c][0],force=True) self.tone(c,self.preset.currentDict[c][1],force=True) self.lcdMgr.loadConf() self.trem(self.preset.currentDict[self.conf.vocab.configKeys[8]]) self.vib(self.preset.currentDict[self.conf.vocab.configKeys[9]]) self.tracking(self.preset.currentDict[self.conf.vocab.configKeys[10]]) State.printT(self.outgoing)
def doConfHelper(self,cf): return True # TO BE FIXED self.reset() State.printT('loading conf: ' + str(cf)) self.loadConf(self.preset.presets[cf]) return True
def off(self,whatIndex,on): """ turn on or off the control given by the whatIindex """ self.aVec[whatIndex] = on if self.aVec[whatIndex]: self.ctrl.doInit() State.printT( ('Vibrato' if whatIndex else 'Tremolo')+':\t' + str(self.aVec[whatIndex]))
def doTrem(self): if not self.aVec[0]: return State.printT('Tremolo Level:\t',self.tremoloLevel) #print('Push: M Vol %s'%self.vVec[self.tremoloLevel]) irq_state = disable_irq() self.volEnQueueable.push(self.targCoilID,self.vVec[self.tremoloLevel]) enable_irq(irq_state) self.tremoloLevel ^= 1
def doVib(self): if not self.aVec[1]: return State.printT('Vibrato Level:\t',self.vibratoLevel) #print('Push: M Tone %s'%self.tVec[self.vibratoLevel]) irq_state = disable_irq() self.toneEnQueueable.push(self.targCoilID,self.tVec[self.vibratoLevel]) enable_irq(irq_state) self.vibratoLevel ^= 1
def pb0Func(self): if self.sequencing: State.printT('pb0Func:\tstepping the sequence...') #State.debug and input('Press Return:') return self.doNextSeq() else: return False # tracking disabled State.printT('pb0Func:\ttoggling tracking...') #State.debug and input('Press Return:') return self.toggleTracking()
def printConfigs(self,setting,masking): """ A little helper routing to print setting and masking to stdout for user information. To print only the config vectors, call: >>> b.printConfigs(None, []) """ for (reg,mask) in masking: State.printT("masking: ", ["{0:d}".format(reg), "{0:08b}".format(mask)]) State.printT('setting: ' + str(setting))
def update(self,bitArray): # send the data bits to the shift register # unset the latch self.stcp.low() # send the bits for r in bitArray: self.spi.send(r) #### COMMENT NEXT LINE FOR Off-Board TESTS! State.printT("send:\t{0:#b}".format(r)) # turn on the latch self.stcp.high()
def vol(self,who,val,unused=None,force=False): # who is 'M','A','B','C','D' if force or val != self.preset.currentDict[who][0]: State.printT('VOL:\t' + str(who) +'\t' + str(val)) #print("a.set('%s',State.Vol,State.l%s)"%(who,(str(val) if val !=0 else 'Off'))) #self.outgoing.append("a.set('%s',State.Vol,State.l%s)"%(who,(str(val)))) # if val !=0 else 'Off'))) self.set(who,State.Vol,eval('State.l%s'%str(val))) self.preset.currentDict[who][0] = val if who == 'M': self.mEval.set(0,val) return True return False
def doInit(self, loopDelay=5): """ sets the base value so that gravity is cancelled out from the initial postion loopDelay is the time in ms between attempts to read the accelerometer. """ self.baseVal=0 init=False while not init: delay(loopDelay) init,self.baseVal = self.readA() self.lastActionTime = millis() State.printT('Initialized!')
def pb(self,who,unused=None,unusedA=None): if ((pyb.millis() - self.pbTime) < State.pbBounceDelay): self.pbTime = pyb.millis() State.printT('PB BOUNCE!! delta millis:\t' + str(pyb.millis() - self.pbTime)) return False State.printT('PB delta millis:\t' + str(pyb.millis() - self.pbTime)) self.pbTime = pyb.millis() whoFuncs = ( # this either steps the seq or toggles splitpot tracking if not sequencing (self.pb0Func,), # pb 0 # either step sequence or toggle tracking if not sequencing # this is the one saves the preset, (self.turnOnYellowLed, self.saveCurrentConfAsPreset), # pb 1 # Tremolo (self.toggleTrem,), # pb 2 # Vibrato (self.toggleVib,), # pb 3 (self.lcdMgr.onLeftButton,), # pb 4 (self.lcdMgr.onRightButton,)) # pb 5 State.printT('PB:\t' + str(who)) res = False for f in whoFuncs[who]: res = f() or res State.printT('pb returning: ' +str(res)) return res # True if who in [2,3] else False
def doWork(self,twoBytes): V = twoBytes & 0xFF K = (twoBytes>>8) & 0xFF mask = 0x80 res = False State.printT('Work:\tK:\t' + bin(K) + '\tV:\t'+ hex(V)) #print('X:\tK:\t' + bin(K) + '\tV:\t'+ hex(V)) for i in range(5): if K & (mask>>i): who = App.targVec[min(i,3)][K & 0b111] val = (0xFF & V) if (V & 0xFF)<128 else (V & 0XFF)-256 res = self.setVec[i](who,val,K&0B11111000) or res break return res
def processQ(self): #State.printT('processQ') work = self.q.pop() worked = False while (work != None): worked = self.doWork(work) or worked work = self.q.pop() if worked: State.printT('worked!') self.x() self.gcd=False elif not self.gcd: State.printT('GC!') gc.collect() # time to do this is 5ms self.gcd=True
def inc(self,who,val,what): # updated version works with updated top byte INC | VOL + M,A,B,C,D # we need to find if its vol or tone then to which coil then call the appropriate methods volMask = 0B10000 toneMask = 0B1000 newVal = 0 sFunc = None State.printT('INC:\t%s\t%s\t%d'%('Vol' if (what & volMask) else 'Tone', who,val)) if what & volMask: sFunc = self.vol newVal = max(0,(min(self.preset.currentDict[who][0] + val,5))) elif what & toneMask: sFunc = self.tone newVal = max(0,(min(self.preset.currentDict[who][1] + val,5))) return sFunc(who,newVal)
def pb(self,who,unused=None,unusedA=None): whoFuncs = ( # this one toggles splitpot tracking,currently is used for debugging (self.toggleTracking,self.displayCurrentConf), # pb 0 # this is the one saves the preset, (self.saveCurrentConfAsPreset,), # pb 1 # Tremolo (self.toggleTrem,), # pb 2 # Vibrato (self.toggleVib,), # pb 3 (self.lcdMgr.onLeftButton,), # pb 4 (self.lcdMgr.onRightButton,)) # pb 5 State.printT('PB:\t' + str(who)) res = False for f in whoFuncs[who]: res = f() or res return res # True if who in [2,3] else False
def validateAndApplyLCDInput(self,confString): try: #res = self.doParse(confString.strip()) self.doParse(confString.strip()) """ for e in res: #print(e) self.outgoing.append(e) """ #self.sendX() self.x() self.preset.currentDict[self.conf.vocab.configKeys[7]]=confString.strip() State.printT("applied LCD input:\t" +confString.strip()) State.printT(self.preset.currentDict) return True except Exception as e: print (e) return False
def loadConfig(self,confName): """ loads a predefined configuration. Arg 0 : the name of the conf to load, for lookup in configDict Note: - this resets next bitMgr config and each coils next config before beginning since there is no 'addition' of settings here - it also resets all the coils connection and vtri values prior to executing. """ self.bitMgr.reset(BitMgr.allRegEndPoints, curBool=False, nexBool=True) for coil in self.coils.values(): coil.resetNext() for expr in mapReplace('self', configDict[confName]): State.printT('Evalutating:\t' + expr) eval(expr , globals(),{'self':self}) self.x()
def pb(self,who,unused=None,unusedA=None): whoFuncs = ( # this either steps the seq or toggles splitpot tracking if not sequencing (self.pb0Func,), # pb 0 # either step sequence or toggle tracking if not sequencing # this is the one saves the preset, (self.turnOnYellowLed, self.saveCurrentConfAsPreset), # pb 1 # Tremolo (self.toggleTrem,), # pb 2 # Vibrato (self.toggleVib,), # pb 3 #(self.lcdMgr.onLeftButton,), # pb 4 #(self.lcdMgr.onRightButton,)) # pb 5 ) State.printT('PB:\t' + str(who)) res = False for f in whoFuncs[who]: res = f() or res State.printT('pb returning: ' +str(res)) return res # True if who in [2,3] else False
def noTrackingUpdate(self): """ takes nbReadings reads, then avgs them and maps the result to the appropriate range and returns it. returns None if no valid value read """ nbReadings = State.splitPotNoTrackingNbReadings vADC = 0 for i in range(nbReadings): v=self.adc.read() if v<self.cutOff or (v>self.ranges[0][1] and v<self.ranges[1][0]) or v>self.ranges[1][1]: #print(v) return None vADC += v delay(1) vADC = round(vADC/nbReadings) #print(vADC) for i in range((1 if self.isToneRange else 0),2): # 2 splits if not ToneRange, only second split if ToneRange if vADC >= self.ranges[i][0] and vADC<=self.ranges[i][1]: State.printT('VADC= ' +str(vADC) + " tuple: " +str((i,self.rMaps[i].v(vADC)))) return (i,self.rMaps[i].v(vADC))
def toFile(self, file = None): """ this will write the presets to a file, if a file argument is provided it is used and it updates the instance filePath otherwise the current instance filePath is used """ if file: self.filePath = file with open(self.filePath, 'w') as csvfile: writer = csv.CSV.Writer(csvfile) #print(self.header) writer.writeRow(self.header) for p in self.presets.keys(): rowDict = self.confDict2RowDict(p,self.presets[p]) #print(rowDict) rawRow = [rowDict[k] for k in self.header] #print(rawRow) writer.writeRow(rawRow) State.printT( "Wrote file:\t" + self.filePath) print( "Wrote file:\t" + self.filePath)
def __init__(self,pyGuitarConf,fileName=None): # the fileName is used to load a presets file, if one exists, # if not, one is created self.conf = pyGuitarConf self.presets = {} if fileName==None: self.filePath = self.conf.LocalConf.presetDir +\ self.conf.LocalConf.dirSeparator + \ self.conf.LocalConf.presetFileName else: self.filePath = fileName State.printT ("creating preset instance from:\t" + self.filePath) print("creating preset instance from:\t" + self.filePath) try: #print(self.filePath) with open(self.filePath, 'r') as csvfile: # from official csv module, not used on pyboard! # reader = csv.DictReader(csvfile,fieldnames = self.conf.Vocab.headings,delimiter=',') # self.header = reader.next() # the next lines refer to my version of the csv reader reader = csv.CSV.Reader(csvfile) self.header = next(reader) for row in reader: if len(row)>2: self.rowDict2confDict(row) if len(self.presets) ==0: raise Exception("read failure") except Exception as e: print('reading csv file threw exception: ', type(e), 'Args: ', e.args) State.printT( "error reading preset file! Creating new one!") print( "error reading preset file! Creating new one!") self.createDefaultPresets() self.currentDict = {} #print(self.presets) #print(self.presets[(0,0)]) for k in self.presets[(0,0)].keys(): self.currentDict[k] = self.presets[(0,0)][k] self.seq=Preset.Sequencer(self.presets,pyGuitarConf.vocab.configKeys[12])
def doSettingMasking(self,setting,masking): """ This helper method applies the masking, by AND, then applies the setting by left shifting a 1 the setting times, then OR it with the other non masked settings. The configs are printed to stdout after assignment. 2015 06 07 update to handle settings which are tuples of tuples... created the little helper, updated logic """ def settingHelper(settingTup): self.cnConfig[BitMgr.nex][settingTup[0]] |= pow(2,settingTup[1]) # end of helper to handle tuples of tuples in settings. for (reg,mask) in masking: State.printT('Reg:\t'+str(reg)) self.cnConfig[BitMgr.nex][reg] &= mask if setting: if (tuple == type(setting[0])): for tup in setting: settingHelper(tup) else: settingHelper(setting) #self.cnConfig[BitMgr.nex][setting[0]] |= pow(2,setting[1]) self.printConfigs(setting,masking)
def lcdSetLine(self, lineNb, line): State.printT('Setting LCD Line:\t%d\t"%s"'%(lineNb, line)) self.lcd.setLn(lineNb, line)
def showConfig(self): State.printT(self.bitMgr)
def displayCurrentConf(self): State.printT(self.preset.currentDict)
def toggleTracking(self): self.preset.currentDict[self.conf.vocab.configKeys[10]] ^= 1 # 0 if self.preset.currentDict[self.conf.vocab.configKeys[10]] else 1 self.spa.track(self.preset.currentDict[self.conf.vocab.configKeys[10]]) self.set(State.pb,State.Red,State.l0 if self.preset.currentDict[self.conf.vocab.configKeys[10]] else State.lOff) State.printT('Tracking:\t%d'%self.preset.currentDict[self.conf.vocab.configKeys[10]]) return True # False
def tracking(self,onOff): self.preset.currentDict[self.conf.vocab.configKeys[10]] = 1 if onOff else 0 self.spa.track(self.preset.currentDict[self.conf.vocab.configKeys[10]]) self.set(State.pb,State.Red,State.l0 if self.preset.currentDict[self.conf.vocab.configKeys[10]] else State.lOff) State.printT('Tracking:\t%d'%self.preset.currentDict[self.conf.vocab.configKeys[10]]) return False