# Professor Cristiano Teixeira
# Sob Licença Apache 2.0

#Falso Theremin Versão 5.0 "Agora estéreo!""

#Objetivo: Simulação de um falso Themerin
#É possivel utilizar dois buzzers um com uma oitava grave
#e outro com uma oitava acima para poder criar melodias
#mais complexas.

import machine, time
from machine import Pin, PWM
frequency = 5000


# Configuração do pino do buzzer
buzzer1 = PWM(Pin(25), freq=1000, duty=512)
buzzer2 = PWM(Pin(26), freq=1000, duty=512)

# Frequências das notas musicais (em Hz)
B0 =  31 
C1 =  33
CS1 = 35
D1 =  37
DS1 = 39
E1 =  41
F1 =  44
FS1 = 46
G1 =  49
GS1 = 52
A1 =  55
AS1 = 58
B1 =  62
C2 =  65
CS2 = 69
D2 =  73
DS2 = 78
E2 =  82
F2 =  87
FS2 = 93
G2 =  98
GS2 = 104
A2 =  110
AS2 = 117
B2 =  123
C3 =  131
CS3 = 139
D3 =  147
DS3 = 156
E3 =  165
F3 =  175
FS3 = 185
G3 =  196
GS3 = 208
A3 =  220
AS3 = 233
B3 =  247
C4 =  262
CS4 = 277
D4 =  294
DS4 = 311
E4 =  330
F4 =  349
FS4 = 370
G4 =  392
GS4 = 415
A4 =  440
AS4 = 466
B4 =  494
C5 =  523
CS5 = 554
D5 =  587
DS5 = 622
E5 =  659
F5 =  698
FS5 = 740
G5 =  784
GS5 = 831
A5 =  880
AS5 = 932
B5 =  988
C6 =  1047
CS6 = 1109
D6 =  1175
DS6 = 1245
E6 =  1319
F6 =  1397
FS6 = 1480
G6 =  1568
GS6 = 1661
A6 =  1760
AS6 = 1865
B6 =  1976
C7 =  2093
CS7 = 2217
D7 =  2349
DS7 = 2489
E7 =  2637
F7 =  2794
FS7 = 2960
G7 =  3136
GS7 = 3322
A7 =  3520
AS7 = 3729
B7 =  3951
C8 =  4186
CS8 = 4435
D8 =  4699
DS8 = 4978
REST =   1

#Armazena os nomes das as notas em um vetor/tupla
toque = ("B0", 
"C1", "CS1", "D1", "DS1", "E1", "F1", "FS1", "G1", "GS1", "A1", "AS1", "B1", 
"C2", "CS2", "D2", "DS2", "E2", "F2", "FS2", "G2", "GS2", "A2", "AS2", "B2",
"C3", "CS3", "D3", "DS3", "E3", "F3", "FS3", "G3", "GS3", "A3", "AS3", "B3",
"C4", "CS4", "D4", "DS4", "E4", "F4", "FS4", "G4", "GS4", "A4", "AS4", "B4",
"C5", "CS5", "D5", "DS5", "E5", "F5", "FS5", "G5", "GS5", "A5", "AS5", "B5",
"C6", "CS6", "D6", "DS6", "E6", "F6", "FS6", "G6", "GS6", "A6", "AS6", "B6",
"C7", "CS7", "D7", "DS7", "E7", "F7", "FS7", "G7", "GS7", "A7", "AS7", "B7"
)

#Armazena as notas em um vetor/tupla
#são 12 notas em cada oitava
notas = (B0, C1, CS1, D1, DS1, E1, F1, FS1, G1, GS1, A1, AS1, B1, C2, CS2, D2, DS2, E2, F2, FS2, G2, GS2, A2, AS2, B2, C3, CS3, D3, DS3, E3, F3, FS3, G3, GS3, A3, AS3, B3, C4, CS4, D4, DS4, E4, F4, FS4, G4, GS4, A4, AS4, B4, C5, CS5, D5, DS5, E5, F5, FS5, G5, GS5, A5, AS5, B5, C6, CS6, D6, DS6, E6, F6, FS6, G6, GS6, A6, AS6, B6, C7, CS7, D7, DS7, E7, F7, FS7, G7, GS7, A7, AS7, B7)

nota1=0
nota2=0

#Função que faz a conversão de um valor
def map(valor, de_min, de_max, para_min, para_max):
    # Verifica se o valor está fora da faixa de entrada
    if valor < de_min:
        valor = de_min
    elif valor > de_max:
        valor = de_max
    
    # Calcula o valor mapeado
    de_variacao = de_max - de_min
    para_variacao = para_max - para_min
    
    valor_mapeado = int((valor - de_min) * para_variacao / de_variacao + para_min)
    
    return valor_mapeado

#Função que calcula a distância do ultrassom da direita
def distancia1():
    echo_timeout = echo_timeout=500*2*30
    trigger = Pin(02, Pin.OUT, pull=None)
    echo = Pin(04, Pin.IN, pull=None)
    trigger.value(0) 
    # Aguarda 5 milisegundos.
    time.sleep_us(5)
    trigger.value(1)
    # Aguarda 10 milisegundos.
    time.sleep_us(10)
    trigger.value(0)
    try:
        pulse_time = machine.time_pulse_us(echo, 1, echo_timeout)
    except OSError as ex:
        if ex.args[0] == 110: # 110 = ETIMEDOUT
            raise OSError('Out of range')
        raise ex  
  
    cms = (pulse_time / 2) / 29.1
    print ("Distância: ",cms, "cms")
    return cms

#Função que calcula a distância do ultrassom da direita
def distancia2():
    echo_timeout = echo_timeout=500*2*30
    trigger = Pin(17, Pin.OUT, pull=None)
    echo = Pin(16, Pin.IN, pull=None)
    trigger.value(0) 
    # Aguarda 5 milisegundos.
    time.sleep_us(5)
    trigger.value(1)
    # Aguarda 10 milisegundos.
    time.sleep_us(10)
    trigger.value(0)
    try:
        pulse_time = machine.time_pulse_us(echo, 1, echo_timeout)
    except OSError as ex:
        if ex.args[0] == 110: # 110 = ETIMEDOUT
            raise OSError('Out of range')
        raise ex  
  
    cms = (pulse_time / 2) / 29.1
    print ("Distância: ",cms, "cms")
    return cms
dmin = 8  #Distância Mínima
dmax = 56 #Distância Máxima

while True:
    d1 = int(distancia1())
    d2 = int(distancia2())
    if (d1 < dmin | d1 > dmax+8): 
        print("\n\nSilencio1!");
        buzzer1.duty(0)
    else: 
        ''' 
        O Mapeamento abaixo faz um regra de três entre
        a Distância e a escala de notas.
        +/- a cada 4 centimetros muda um semiton
        das notas entre 25 e 36 são as notas da terceira oitava
        para trabalhar com dois arduinos recomendo:
        deixar uma grave à esquerda e o outro arduino 
        à direita uma ou duas oitavas mais agudas,
        por exemplo entre 37 e 48
        '''
        buzzer1.duty(512)
        nota1=int(map(d1, dmin, dmax, 25, 36))
        print("\nNota1: ", nota1, ": ", (toque[nota1]))
        print("TOM1: ", notas[nota1])

    if (d2 < dmin | d2 > dmax+8): 
        print("\n\nSilencio2!");
        buzzer2.duty(0)
    else: 
        ''' 
        O Mapeamento abaixo faz um regra de três entre
        a Distância e a escala de notas.
        +/- a cada 4 centimetros muda um semiton
        das notas entre 25 e 36 são as notas da terceira oitava
        para trabalhar com dois arduinos recomendo:
        deixar uma grave à esquerda e o outro arduino 
        à direita uma ou duas oitavas mais agudas,
        por exemplo entre 37 e 48
        '''
        buzzer2.duty(512)
        nota2=int(map(d2, dmin, dmax, 37, 48))
        print("\nNota2: ", nota2, ": ", (toque[nota2]))
        print("TOM2: ", notas[nota2])

    buzzer1.freq(notas[nota1])
    buzzer2.freq(notas[nota2])
    time.sleep_ms(50)