github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/examples/usb-midi/main.go (about)

     1  package main
     2  
     3  import (
     4  	"machine"
     5  	"machine/usb/adc/midi"
     6  
     7  	"time"
     8  )
     9  
    10  // Try it easily by opening the following site in Chrome.
    11  // https://www.onlinemusictools.com/kb/
    12  
    13  const (
    14  	cable    = 0
    15  	channel  = 1
    16  	velocity = 0x40
    17  )
    18  
    19  func main() {
    20  	led := machine.LED
    21  	led.Configure(machine.PinConfig{Mode: machine.PinOutput})
    22  
    23  	button := machine.BUTTON
    24  	button.Configure(machine.PinConfig{Mode: machine.PinInputPullup})
    25  
    26  	m := midi.Port()
    27  	m.SetRxHandler(func(b []byte) {
    28  		// blink when we receive a MIDI message
    29  		led.Set(!led.Get())
    30  	})
    31  
    32  	m.SetTxHandler(func() {
    33  		// blink when we send a MIDI message
    34  		led.Set(!led.Get())
    35  	})
    36  
    37  	prev := true
    38  	chords := []struct {
    39  		name  string
    40  		notes []midi.Note
    41  	}{
    42  		{name: "C ", notes: []midi.Note{midi.C4, midi.E4, midi.G4}},
    43  		{name: "G ", notes: []midi.Note{midi.G3, midi.B3, midi.D4}},
    44  		{name: "Am", notes: []midi.Note{midi.A3, midi.C4, midi.E4}},
    45  		{name: "F ", notes: []midi.Note{midi.F3, midi.A3, midi.C4}},
    46  	}
    47  	index := 0
    48  
    49  	for {
    50  		current := button.Get()
    51  		if prev != current {
    52  			if current {
    53  				for _, note := range chords[index].notes {
    54  					m.NoteOff(cable, channel, note, velocity)
    55  				}
    56  				index = (index + 1) % len(chords)
    57  			} else {
    58  				for _, note := range chords[index].notes {
    59  					m.NoteOn(cable, channel, note, velocity)
    60  				}
    61  			}
    62  			prev = current
    63  		}
    64  		time.Sleep(100 * time.Millisecond)
    65  	}
    66  }