#* ------------------------------------------------------------------------- *# # Sensors: prox.horizontal[0:4], rc5.command # Actuators: sound.freq, motor.right.target # Timers: # Other local events: # Externat events: # emit : GO, STOP # onevent: PROX #* ------------------------------------------------------------------------- *# #* sensor/note codes prox.horizontal[0] : note pitch bit 0 prox.horizontal[1] : note pitch bit 1 prox.horizontal[2] : parity bit (ALL bits) prox.horizontal[3] : note pitch bit 2 prox.horizontal[4] : note value (duration) specials: 00000 : do nothing 11111 : end (NB: fails checksum !!!) 00101 : reserved for future use ;) note pitch = SUM (sensor[i] * 2^(i+1)) ; 0 <= i <=2 (with parity bit removed !!!) note value : a partition can only use 2 different values (defined as LONGNOTE & SHORTNOTE) in {whole, half, quarter, ...} *# #* ------------------------------------------------------------------------- *# # CONSTS #* ------------------------------------------------------------------------- *# # detection distance var DETECT[5] = [DETECT0,DETECT1,DETECT2,DETECT3,DETECT4] # le clavier bien tempere ;) var SCALE[7] = [264,296,333,352,396,444,498] # There are relations between the folling values but I don't care; guessing should be fine # note values var SHORTNOTE = 15 # in 1/60 s var LONGNOTE = SHORTNOTE * 2 # very simple def var tempo = -120 # motor speed, only wuen 1! Thymio. When using 2 Thymios, tempo is set in the other robot # mode - careful : as these modes are exclusive, the program sometimes guess on !T1 or !T2. If another should be added, all these guesses must be rewritten var T1 = 1 # one real Thymio with real scrore var T2 = 2 # one real Thymio + 1 simulated Thymio which emits sensors/notes # RC5 var RC_GO = 53 # rc5 GO var RC_STOP = 87 #rc5 STOP var RC_1T = 1 # rc5 mode T1 var RC_2T = 2 # rc5 mode T2 #* ------------------------------------------------------------------------- *# # GLOBAL VARS #* ------------------------------------------------------------------------- *# var sensor[5] var note_pitch var note_value var chk_err = 0 # 1 = checksum error on read value var mode = T2 # default mode is 1 real + 1 simulated Thymio var playing = 0 # 1 = a score is playing #* ------------------------------------------------------------------------- *# # LOCAL VARS for subs #* ------------------------------------------------------------------------- *# var i var c #* ------------------------------------------------------------------------- *# # INIT #* ------------------------------------------------------------------------- *# # reset outputs call sound.system(-1) call leds.top(0,0,0) call leds.bottom.left(0,0,0) call leds.bottom.right(0,0,0) call leds.circle(0,0,0,0,0,0,0,0) #* ------------------------------------------------------------------------- *# # SUBS #* ------------------------------------------------------------------------- *# #* ------------------------------------ sub stop Pre: Post: program stops playing ------------------------------------ *# sub stop call sound.system(-1) playing = 0 if (mode == T1) then motor.right.target = 0 else emit STOP end #* ------------------------------------ sub ana2bin Pre: sensor[read values,...] Post: sensor[bits,...] based on DETECTi consts ------------------------------------ *# sub ana2bin for i in 0:4 do if (sensor[i] > DETECT[i]) then sensor[i] = 1 else sensor[i] = 0 end end #* ------------------------------------ sub checksum Pre: sensor[bits,...] Post: chk_err = 0 if OK chk_err = 1 if parity error or 11111 ------------------------------------ *# sub checksum chk_err = 0 c = sensor[0] # init with 1st element for i in 1:4 do # so start loop with 2nd c += sensor[i] end if (c == 5) then # special bits 11111 : end program chk_err = 1 # this is a cheat to avoid playing 1111 as a note callsub stop # WE CALL STOP WITHIN THIS SUB WITH THIS COMMAND ! (RC5 STOP in onevent) return elseif (c % 2) != 0 then # parity error chk_err = 1 end #* ------------------------------------ sub bin2dec Pre: sensor[bits,...] (with parity bit) Post: sets note_pitch & note_value ------------------------------------ *# sub bin2dec note_pitch = sensor[0] + sensor[1]*2 + sensor[3]*4 if (sensor[4] == 0) then note_value = SHORTNOTE #emit _DEGUG1 SHORTNOTE else note_value = LONGNOTE #emit _DEGUG1 LONGNOTE end #* ------------------------------------ sub play Pre: Post: ------------------------------------ *# sub play #emit _DEGUG1 note_pitch call sound.freq(SCALE[note_pitch - 1],note_value) #* ------------------------------------------------------------------------- *# # EVENTS #* ------------------------------------------------------------------------- *# #* ------------------------------------ REMOTE CONTROL ------------------------------------ *# onevent rc5 if (rc5.command == RC_STOP) and (playing == 1) then callsub stop elseif (rc5.command == RC_GO) then playing = 1 if (mode == T1) then motor.right.target = tempo else emit GO end elseif (rc5.command == RC_1T) and (playing == 0) # no mode change while playing then mode = T1 elseif (rc5.command == RC_2T) and (playing == 0) # no mode change while playing then mode = T2 end #* ------------------------------------ PROX or prox ------------------------------------ *# onevent PROX # mode T2 if (mode != T2) then return end sensor = event.args[0:4] callsub ana2bin callsub checksum if (chk_err == 1) then return end callsub bin2dec if (note_pitch == 0) then return end callsub play onevent prox # mode T1 if (mode != T1) then return end sensor = prox.horizontal[0:4] callsub ana2bin callsub checksum if (chk_err == 1) then return end callsub bin2dec if (note_pitch == 0) then return end callsub play #* ------------------------------------------------------------------------- *# # Sensors: # Actuators: # Timers: timer0 # Local events: timer0 # Externat events: # emit : PROX # onevent: GO, STOP #* ------------------------------------------------------------------------- *# #* ------------------------------------------------------------------------- *# # CONSTS #* ------------------------------------------------------------------------- *# # sensors / notes (solfege notation) # short var ut[5] = [DETECT0 +1,DETECT1 -1,DETECT2 +1,DETECT3 -1,DETECT4 -1] var re[5] = [DETECT0 -1,DETECT1 +1,DETECT2 +1,DETECT3 -1,DETECT4 -1] var mi[5] = [DETECT0 +1,DETECT1 +1,DETECT2 -1,DETECT3 -1,DETECT4 -1] var fa[5] = [DETECT0 -1,DETECT1 -1,DETECT2 +1,DETECT3 +1,DETECT4 -1] var sol[5]= [DETECT0 +1,DETECT1 -1,DETECT2 -1,DETECT3 +1,DETECT4 -1] var la[5] = [DETECT0 -1,DETECT1 +1,DETECT2 -1,DETECT3 +1,DETECT4 -1] var si[5] = [DETECT0 +1,DETECT1 +1,DETECT2 +1,DETECT3 +1,DETECT4 -1] # long var UT[5] = [DETECT0 +1,DETECT1 -1,DETECT2 -1,DETECT3 -1,DETECT4 +1] var RE[5] = [DETECT0 -1,DETECT1 +1,DETECT2 -1,DETECT3 -1,DETECT4 +1] var MI[5] = [DETECT0 +1,DETECT1 +1,DETECT2 +1,DETECT3 -1,DETECT4 +1] var FA[5] = [DETECT0 -1,DETECT1 -1,DETECT2 -1,DETECT3 +1,DETECT4 +1] var SOL[5]= [DETECT0 +1,DETECT1 -1,DETECT2 +1,DETECT3 +1,DETECT4 +1] var LA[5] = [DETECT0 -1,DETECT1 +1,DETECT2 +1,DETECT3 +1,DETECT4 +1] var SI[5] = [DETECT0 +1,DETECT1 +1,DETECT2 -1,DETECT3 +1,DETECT4 +1] # specials var silence[5] = [DETECT0 -1,DETECT1 -1,DETECT2 -1,DETECT3 -1,DETECT4 -1] var stop[5] = [DETECT0 +1,DETECT1 +1,DETECT2 +1,DETECT3 +1,DETECT4 +1] # unused: [DETECT0 -1,DETECT1 -1,DETECT2 +1,DETECT3 -1,DETECT4 +1] #* ------------------------------------------------------------------------- *# # GLOBAL VARS #* ------------------------------------------------------------------------- *# var playing = 0 var note[5] var index = 0 # score # deque not available in this FW #* var tempo = 500 # in ms var SCORE[14*5 + 5] = [ut,re,mi,fa,sol,la,si, UT,RE,MI,FA,SOL,LA,SI, stop] *# #* # we wish you a merry Xmas # SHORTNOTE = 15 var tempo = 270 # in ms var SCORE[40*5 + 5] = [UT, #1 FA,silence,fa,sol,fa,mi, #2 RE,silence,RE,silence,RE,silence, #3 SOL,silence,sol,la,sol,fa, #4 MI,silence,MI,silence,MI,silence, #5 LA,silence,la,si,la,sol, #6 FA,RE,ut,silence,ut, #7 RE,SOL,MI, #8 FA, #9 stop] *# #* # brother john # SHORTNOTE = 22 var tempo = 500 # in ms var SCORE[35*5 + 5] = [ut,re,mi,ut, ut,re,mi,ut, mi,fa,SOL, silence, mi,fa,SOL, silence, sol,la,sol,fa,mi,ut, sol,la,sol,fa,mi,ut, mi,ut,MI,silence,mi,ut,MI, stop] *# # we wish you a merry Xmas # SHORTNOTE = 15 var tempo = 270 # in ms var SCORE[40*5 + 5] = [UT, #1 FA,silence,fa,sol,fa,mi, #2 RE,silence,RE,silence,RE,silence, #3 SOL,silence,sol,la,sol,fa, #4 MI,silence,MI,silence,MI,silence, #5 LA,silence,la,si,la,sol, #6 FA,RE,ut,silence,ut, #7 RE,SOL,MI, #8 FA, #9 stop] #* ------------------------------------------------------------------------- *# # LOCAL VARS for subs #* ------------------------------------------------------------------------- *# var i #* ------------------------------------------------------------------------- *# # INIT #* ------------------------------------------------------------------------- *# #* ------------------------------------------------------------------------- *# # SUBS #* ------------------------------------------------------------------------- *# #* ------------------------------------ sub getnote Pre: there are at least 5 values @ SCORE[index] Post: note = SCORE[index] (5 values are copied) ------------------------------------ *# sub getnote for i in 0:4 do # copy 1 note ( = 5 DETECTs) note[i] = SCORE[index + i] end index += 5 #* ------------------------------------------------------------------------- *# # EVENTS #* ------------------------------------------------------------------------- *# #* ------------------------------------ GO ------------------------------------ *# onevent GO if (playing == 0) # no score is playing so start a new one; else ignore event then playing = 1 index = 0 timer.period[0] = tempo end #* ------------------------------------ STOP ------------------------------------ *# onevent STOP playing = 0 timer.period[0] = 0 #* ------------------------------------ TIMER0 ------------------------------------ *# onevent timer0 if (playing == 1) then callsub getnote emit PROX note end