diff --git a/backend/driver/main.go b/backend/driver/main.go index d067577..f6d2901 100644 --- a/backend/driver/main.go +++ b/backend/driver/main.go @@ -4,7 +4,8 @@ import ( "log" httphandler "modularMidiGoApp/backend/httpHandler" midiOutputPipeline "modularMidiGoApp/backend/midiUtility/midiOutputPipeline" - usbUtility "modularMidiGoApp/backend/usbUtility" + + //usbUtility "modularMidiGoApp/backend/usbUtility" "strings" ) @@ -12,7 +13,7 @@ import ( // - Starts HTTP handler func main() { go midiOutputPipeline.MidiWriter() - go usbUtility.ESP32MidiListener(0, midiOutputPipeline.MidiOutChannel) + //go usbUtility.ESP32MidiListener(0, midiOutputPipeline.MidiOutChannel) go func() { routes := []httphandler.Route{ @@ -21,6 +22,7 @@ func main() { httphandler.MidiTester, httphandler.MidiPortList, httphandler.WritePinConfig, + httphandler.StartNormalMode, // Add more routes } port := parsePort(LoadHTTPconf()) diff --git a/backend/espConfigUtility/writePinConf.go b/backend/espConfigUtility/writePinConf.go index 3f6bd38..c2e6bba 100644 --- a/backend/espConfigUtility/writePinConf.go +++ b/backend/espConfigUtility/writePinConf.go @@ -1,10 +1,12 @@ package espconfigutility import ( + "bytes" "encoding/json" "fmt" "os" "path/filepath" + "strconv" getvalues "modularMidiGoApp/backend/getValues" usbUtility "modularMidiGoApp/backend/usbUtility" @@ -26,7 +28,6 @@ type Multiplexer8bit struct { } func WritePinConfig() error { - usbUtility.StopESP32MidiListener() fmt.Println("Writing pin configuration...") mux, err := readConfFile() if err != nil { @@ -36,23 +37,24 @@ func WritePinConfig() error { fmt.Printf("Loaded %d multiplexers from config file.\n", len(mux)) - // Marshal the data and write it to the USB - for i, m := range mux { - fmt.Printf("Processing multiplexer #%d: %+v\n", i, m) - jsonData, err := json.Marshal(m) - if err != nil { - fmt.Printf("Error marshaling multiplexer #%d: %v\n", i, err) - return err - } + var configString bytes.Buffer + configString.WriteString("MUX_COUNT:" + strconv.Itoa(len(mux)) + ";") - if err := usbUtility.WriteToUSB(jsonData); err != nil { - fmt.Printf("Error writing to USB for multiplexer #%d: %v\n", i, err) - return err + for i, m := range mux { + configString.WriteString(fmt.Sprintf("MUX%d:%d,%d,%d,%d,%d", + i+1, m.Id, m.PinA, m.PinB, m.PinC, m.SerialIOpin)) + for _, pin := range m.Pins { + configString.WriteString("," + strconv.Itoa(pin)) } + configString.WriteString(";") + } - fmt.Printf("JSON data for multiplexer #%d: %s\n", i, string(jsonData)) + if err := usbUtility.WriteToUSB(configString.String()); err != nil { + fmt.Printf("Error writing to USB: %v\n", err) + return err } + fmt.Printf("Config data sent: %s\n", configString.String()) fmt.Println("Pin configuration write completed.") return nil } @@ -83,4 +85,4 @@ func readConfFile() ([]Multiplexer8bit, error) { fmt.Println("Config file successfully decoded.") return muxConfig.Multiplexers, nil -} +} \ No newline at end of file diff --git a/backend/httpHandler/handler.go b/backend/httpHandler/handler.go index a3e377c..085acd3 100644 --- a/backend/httpHandler/handler.go +++ b/backend/httpHandler/handler.go @@ -15,6 +15,14 @@ type Route struct { Handler http.HandlerFunc } +var StartNormalMode = Route{ + Path: "/startNormalMode", + Handler: func(w http.ResponseWriter, r *http.Request) { + go usbUtility.ESP32MidiListener(0, midiOutputPipeline.MidiOutChannel) + fmt.Fprint(w, "Normal mode started") + }, +} + var TestCallRoute = Route{ Path: "/testCall", Handler: func(w http.ResponseWriter, r *http.Request) { diff --git a/backend/usbUtility/usb_listener.go b/backend/usbUtility/usb_listener.go index e3e4734..6bf8a5f 100644 --- a/backend/usbUtility/usb_listener.go +++ b/backend/usbUtility/usb_listener.go @@ -5,6 +5,7 @@ import ( "fmt" "log" midiOutputPipeline "modularMidiGoApp/backend/midiUtility/midiOutputPipeline" + "sync" "time" "go.bug.st/serial" @@ -16,10 +17,12 @@ type USBPortsList struct { SelectedUSBDevice string `json:"selected_usb_device"` } +var usbMutex = &sync.Mutex{} var stopChan = make(chan struct{}) func StopESP32MidiListener() { close(stopChan) + fmt.Println("ESP32MidiListener stop signal sent.") } func ESP32MidiListener(channel uint8, outputChan chan<- midiOutputPipeline.MidiCCMessage) { @@ -36,13 +39,15 @@ func ESP32MidiListener(channel uint8, outputChan chan<- midiOutputPipeline.MidiC return default: if err := listenToESP32(channel, outputChan); err != nil { - log.Printf("ESP32 connection error: %v", err) - log.Println("Retrying in 5 seconds...") + fmt.Printf("ESP32 connection error: %v", err) + fmt.Println("Retrying in 5 seconds...") select { case <-time.After(5 * time.Second): continue + case <-stopChan: + fmt.Println("ESP32MidiListener stopping...") return } } @@ -51,6 +56,8 @@ func ESP32MidiListener(channel uint8, outputChan chan<- midiOutputPipeline.MidiC } func listenToESP32(channel uint8, outputChan chan<- midiOutputPipeline.MidiCCMessage) error { + usbMutex.Lock() + defer usbMutex.Unlock() // Get the selected USB device deviceName, err := GetSelectedUSBDevice(FilePath) if err != nil { @@ -75,19 +82,6 @@ func listenToESP32(channel uint8, outputChan chan<- midiOutputPipeline.MidiCCMes log.Printf("Successfully connected to ESP32 on %s", deviceName) - // Wait for ESP32 to be ready for mode selection - modeSelectReader := bufio.NewReader(port) - port.SetReadTimeout(30 * time.Second) - for { - line, err := modeSelectReader.ReadString('\n') - if err != nil { - return fmt.Errorf("error reading from USB device: %w", err) - } - if line == "SELECT_MODE\n" || line == "SELECT_MODE\r\n" { - log.Println("ESP32 ready for mode selection") - break - } - } //send mode selection command if _, err := port.Write([]byte("BROADCAST_MODE\n")); err != nil { return fmt.Errorf("failed to write mode selection to USB device: %w", err) @@ -134,6 +128,7 @@ func processMidiData(data []byte, channel uint8, outputChan chan<- midiOutputPip // Process pairs of bytes (CC number, value) for i := 0; i < len(data); i += 2 { + ccNumber := data[i] value := data[i+1] @@ -157,6 +152,8 @@ func processMidiData(data []byte, channel uint8, outputChan chan<- midiOutputPip } func WriteToUSB(data interface{}) error { + usbMutex.Lock() + defer usbMutex.Unlock() // Get the selected USB device deviceName, err := GetSelectedUSBDevice(FilePath) if err != nil { @@ -186,20 +183,6 @@ func WriteToUSB(data interface{}) error { return fmt.Errorf("unsupported data type for writing to USB device") } - //Wait for ESP32 to be ready for mode selection - reader := bufio.NewReader(conn) - conn.SetReadTimeout(30 * time.Second) - for { - line, err := reader.ReadString('\n') - if err != nil { - return fmt.Errorf("error reading from USB device: %w", err) - } - if line == "SELECT_MODE\n" || line == "SELECT_MODE\r\n" { - log.Println("ESP32 ready for mode selection") - break - } - } - //send mode selection command if _, err := conn.Write([]byte("FLASH_MODE\n")); err != nil { return fmt.Errorf("failed to write mode selection to USB device: %w", err) diff --git a/backend/usbUtility/usb_ports.json b/backend/usbUtility/usb_ports.json index fcb996a..4a3dddf 100644 --- a/backend/usbUtility/usb_ports.json +++ b/backend/usbUtility/usb_ports.json @@ -1,136 +1,132 @@ { "available_usb_devices": [ { - "name": "QT_Py_ESP32-S3__4M_Flash__2M_PSRAM_", - "device_path": "/dev/ttyACM0" + "device_path": "/dev/ttyS0", + "name": "ttyS0" }, { - "name": "ttyS0", - "device_path": "/dev/ttyS0" + "device_path": "/dev/ttyS1", + "name": "ttyS1" }, { - "name": "ttyS1", - "device_path": "/dev/ttyS1" + "device_path": "/dev/ttyS10", + "name": "ttyS10" }, { - "name": "ttyS10", - "device_path": "/dev/ttyS10" + "device_path": "/dev/ttyS11", + "name": "ttyS11" }, { - "name": "ttyS11", - "device_path": "/dev/ttyS11" + "device_path": "/dev/ttyS12", + "name": "ttyS12" }, { - "name": "ttyS12", - "device_path": "/dev/ttyS12" + "device_path": "/dev/ttyS13", + "name": "ttyS13" }, { - "name": "ttyS13", - "device_path": "/dev/ttyS13" + "device_path": "/dev/ttyS14", + "name": "ttyS14" }, { - "name": "ttyS14", - "device_path": "/dev/ttyS14" + "device_path": "/dev/ttyS15", + "name": "ttyS15" }, { - "name": "ttyS15", - "device_path": "/dev/ttyS15" + "device_path": "/dev/ttyS16", + "name": "ttyS16" }, { - "name": "ttyS16", - "device_path": "/dev/ttyS16" + "device_path": "/dev/ttyS17", + "name": "ttyS17" }, { - "name": "ttyS17", - "device_path": "/dev/ttyS17" + "device_path": "/dev/ttyS18", + "name": "ttyS18" }, { - "name": "ttyS18", - "device_path": "/dev/ttyS18" + "device_path": "/dev/ttyS19", + "name": "ttyS19" }, { - "name": "ttyS19", - "device_path": "/dev/ttyS19" + "device_path": "/dev/ttyS2", + "name": "ttyS2" }, { - "name": "ttyS2", - "device_path": "/dev/ttyS2" + "device_path": "/dev/ttyS20", + "name": "ttyS20" }, { - "name": "ttyS20", - "device_path": "/dev/ttyS20" + "device_path": "/dev/ttyS21", + "name": "ttyS21" }, { - "name": "ttyS21", - "device_path": "/dev/ttyS21" + "device_path": "/dev/ttyS22", + "name": "ttyS22" }, { - "name": "ttyS22", - "device_path": "/dev/ttyS22" + "device_path": "/dev/ttyS23", + "name": "ttyS23" }, { - "name": "ttyS23", - "device_path": "/dev/ttyS23" + "device_path": "/dev/ttyS24", + "name": "ttyS24" }, { - "name": "ttyS24", - "device_path": "/dev/ttyS24" + "device_path": "/dev/ttyS25", + "name": "ttyS25" }, { - "name": "ttyS25", - "device_path": "/dev/ttyS25" + "device_path": "/dev/ttyS26", + "name": "ttyS26" }, { - "name": "ttyS26", - "device_path": "/dev/ttyS26" + "device_path": "/dev/ttyS27", + "name": "ttyS27" }, { - "name": "ttyS27", - "device_path": "/dev/ttyS27" + "device_path": "/dev/ttyS28", + "name": "ttyS28" }, { - "name": "ttyS28", - "device_path": "/dev/ttyS28" + "device_path": "/dev/ttyS29", + "name": "ttyS29" }, { - "name": "ttyS29", - "device_path": "/dev/ttyS29" + "device_path": "/dev/ttyS3", + "name": "ttyS3" }, { - "name": "ttyS3", - "device_path": "/dev/ttyS3" + "device_path": "/dev/ttyS30", + "name": "ttyS30" }, { - "name": "ttyS30", - "device_path": "/dev/ttyS30" + "device_path": "/dev/ttyS31", + "name": "ttyS31" }, { - "name": "ttyS31", - "device_path": "/dev/ttyS31" + "device_path": "/dev/ttyS4", + "name": "Alder Lake PCH UART" }, { - "name": "Alder Lake PCH UART", - "device_path": "/dev/ttyS4" + "device_path": "/dev/ttyS5", + "name": "ttyS5" }, { - "name": "ttyS5", - "device_path": "/dev/ttyS5" + "device_path": "/dev/ttyS6", + "name": "ttyS6" }, { - "name": "ttyS6", - "device_path": "/dev/ttyS6" + "device_path": "/dev/ttyS7", + "name": "ttyS7" }, { - "name": "ttyS7", - "device_path": "/dev/ttyS7" + "device_path": "/dev/ttyS8", + "name": "ttyS8" }, { - "name": "ttyS8", - "device_path": "/dev/ttyS8" - }, - { - "name": "ttyS9", - "device_path": "/dev/ttyS9" + "device_path": "/dev/ttyS9", + "name": "ttyS9" } ], "selected_usb_device": "/dev/ttyACM0" diff --git a/configMaker/main.go b/configMaker/main.go new file mode 100644 index 0000000..7e37148 --- /dev/null +++ b/configMaker/main.go @@ -0,0 +1,105 @@ +package main + +import ( + "encoding/json" + "html/template" + "log" + "net/http" + "strconv" +) + +// MultiplexerConfig represents the configuration for a single multiplexer. +type MultiplexerConfig struct { + ID int `json:"id"` + Pins []int `json:"pins"` + PinA int `json:"pinA"` + PinB int `json:"pinB"` + PinC int `json:"pinC"` + SerialIOpin int `json:"serialIOpin"` +} + +// PinConfig represents the overall pin configuration for all multiplexers. +type PinConfig struct { + Multiplexers []MultiplexerConfig `json:"multiplexers"` +} + +func handleRoot(w http.ResponseWriter, r *http.Request) { + tmpl, err := template.ParseFiles("templates/index.html") + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + tmpl.Execute(w, nil) +} + +func handleGenerate(w http.ResponseWriter, r *http.Request) { + if err := r.ParseForm(); err != nil { + http.Error(w, "Failed to parse form", http.StatusBadRequest) + return + } + + muxCountStr := r.FormValue("mux-count") + muxCount, err := strconv.Atoi(muxCountStr) + if err != nil { + http.Error(w, "Invalid number of multiplexers", http.StatusBadRequest) + return + } + + config := PinConfig{} + + for i := 0; i < muxCount; i++ { + muxIDStr := r.FormValue("mux-" + strconv.Itoa(i) + "-id") + muxID, _ := strconv.Atoi(muxIDStr) + + pinAStr := r.FormValue("mux-" + strconv.Itoa(i) + "-pinA") + pinA, _ := strconv.Atoi(pinAStr) + + pinBStr := r.FormValue("mux-" + strconv.Itoa(i) + "-pinB") + pinB, _ := strconv.Atoi(pinBStr) + + pinCStr := r.FormValue("mux-" + strconv.Itoa(i) + "-pinC") + pinC, _ := strconv.Atoi(pinCStr) + + serialIOpinStr := r.FormValue("mux-" + strconv.Itoa(i) + "-serialIOpin") + serialIOpin, _ := strconv.Atoi(serialIOpinStr) + + muxPins := make([]int, 8) + for j := 0; j < 8; j++ { + pinValueStr := r.FormValue("mux-" + strconv.Itoa(i) + "-io-" + strconv.Itoa(j)) + muxPins[j], _ = strconv.Atoi(pinValueStr) + } + + mux := MultiplexerConfig{ + ID: muxID, + Pins: muxPins, + PinA: pinA, + PinB: pinB, + PinC: pinC, + SerialIOpin: serialIOpin, + } + config.Multiplexers = append(config.Multiplexers, mux) + } + + jsonData, err := json.MarshalIndent(config, "", " ") + if err != nil { + http.Error(w, "Failed to generate JSON", http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "application/json") + w.Write(jsonData) +} + +func main() { + http.HandleFunc("/", handleRoot) + http.HandleFunc("/generate", handleGenerate) + + // Serve static files + fs := http.FileServer(http.Dir("./static")) + http.Handle("/static/", http.StripPrefix("/static/", fs)) + + log.Println("Starting server on :8080") + if err := http.ListenAndServe(":8080", nil); err != nil { + log.Fatalf("Failed to start server: %v", err) + } +} diff --git a/configMaker/templates/index.html b/configMaker/templates/index.html new file mode 100644 index 0000000..f89ca4f --- /dev/null +++ b/configMaker/templates/index.html @@ -0,0 +1,246 @@ + + +
+ + +