# Modified for HB0110
#
# picoslidertoy_midi_sliders_code.py -- turn picoslidertoy into MIDI controller
# 2024 - @todbot / Tod Kurt - github.com/todbot/picoslidertoy
#
# based off of "picotouch_test.py":
# picotouch_test.py -- Testing for tiny capsense controller using Pico,
# 2021 - @todbot / Tod Kurt - github.com/todbot/picotouch
#
# To use:
#
# 1. Install needed libraries:
#   circup install adafruit_midi
# 2. Copy over files in this directory to CIRCUITPY:
#   cp circuitpython/midi_sliders/* /Volumes/CIRCUITPY/
#

import time
import board
import touchio
import busio
import usb_midi
import adafruit_midi
from adafruit_midi.control_change import ControlChange
from adafruit_midi.note_on import NoteOn
from adafruit_midi.note_off import NoteOff

from touchslider import TouchWheel, TouchSlider

# midi cc and note definitions
midi_ccs = [ 7, 10, 4, 2, 7, 10 ]
#midi_ccs = [ 73, 1, 72, 74, 71 ]
midi_notes = [ 34, 35, 36, 37,  38, 39, 40, 41,  24 ]  # FIXME
midi_chan = 1
base_note = 36
scale_mixolydian   = (0, 2, 4, 5, 7, 9, 10, 12, 14, 16)
scale_minor        = (0, 2, 3, 5, 7, 8, 10, 12, 14, 15)
scale_major        = (0, 2, 4, 5, 7, 9, 11, 12, 14, 16)
scale_fifths       = (0, 5, 7, 12, 17,19,24,29,31,36,41,43)
scale = scale_fifths

fader1_pins = (board.GP0, board.GP1, board.GP2)
fader2_pins = (board.GP5, board.GP4, board.GP27)
fader3_pins = (board.GP9, board.GP10, board.GP21)
fader4_pins = (board.GP15, board.GP11, board.GP18)
rotary1_pins = (board.GP13, board.GP14, board.GP12)
rotary2_pins = (board.GP6, board.GP7, board.GP8)
pad_pins = (board.GP28, board.GP3, board.GP26, board.GP22,
            board.GP20, board.GP19, board.GP17, board.GP16)

# set up the touch controls
sliders = (
    TouchSlider(fader1_pins),
    TouchSlider(fader2_pins),
    TouchSlider(fader3_pins),
    TouchSlider(fader4_pins),
    TouchWheel(rotary1_pins, offset=0.25),
    TouchWheel(rotary2_pins, offset=0.25),
)
pads = [touchio.TouchIn(pin) for pin in pad_pins]

# set up midi out
midi = adafruit_midi.MIDI(midi_out=usb_midi.ports[1], out_channel=midi_chan-1)

# used to keep track of which note pads are currently pressed
pad_state = [False] * len(pads)

while True:
    for i, slider in enumerate(sliders):
        pos = slider.pos()
        if pos is not None: 
            cc_val = int((1-pos) * 127)
            midi.send(ControlChange(midi_ccs[i], cc_val))
            print("slider:%d: %1.2f cc:%d ccval:%d" % (i,pos,midi_ccs[i],cc_val))

    for i, pad in enumerate(pads):
        v = pad.value
        if pad_state[i] != v:
            n = base_note + scale[i]
            msg = NoteOn(n, 127) if v else NoteOff(n,0)
            midi.send(msg)
            pad_state[i] = v
            print("pad:%d: note:" % i, msg)

    #time.sleep(0.01)
