Jump to content
Why become a member? ×

SamIAm

⭐Supporting Member⭐
  • Posts

    1,278
  • Joined

  • Last visited

  • Days Won

    6

Everything posted by SamIAm

  1. HX Stomp here on BC for £320 ... I'm sure it won't last long! S'manth x
  2. Thanks @tauzero, COBOL & FORTRAN are two I've never really used; LISP et al are well outside my experience. PICK is my most esoteric! Pascal/C/C++/C#/TS is my area of ... playing. S'manth x
  3. @rwillett I'm not sure the midi actually needs a seperate thread ... however: Even printf seems to be thread unsafe. midi is provided by TinyUSB and I'm not sure what goes on in its depths. Gut! (lol) My first proper tooth cutting on multithreading was in the early 90s, a DOS based, TUI C application (financial trading system) to use a pre-emptive multi-threading library ... lots of issues to deal with, but it worked in the end! I just feel that having midi in its own thread is safer. I have also rethought things and I'm going to get the buttons to just add events to the Q and let an event processor figure out what to do (OSC ... maybe one day), this seems to lend itself to dealing with interactions between multiple buttons (Two pressed at once). That online PICO emulator looks pretty cool! S'manth x
  4. So that was not straightforward! Following the second post did not achieve the desired effect, I had to scavange the net for tweaks to actually get the debugger configured correctly. And then ... it kept crashing, after more digging I found that I needed to be using a slightly different version of the FreeRTOS kernel ... one that has thread safe breakpoint support. However, debugging is now working (and pretty funky!) and I was able to fix my refactored code so can now successfully detect button presses and fire button events. I have a button class that instantiates a thread to process just that button (this will make it super easy to add more buttons if I want). Next step will be to get the different button objects to dump requests to send a midi message into a thread safe queue which I will process in a single midi send thread. S'manth x
  5. So today I will be eating that frog My frog is getting debugging working on my mac/pico development system. My initial dev setup was achieved by following this very useful post https://blog.smittytone.net/2021/02/02/program-raspberry-pi-pico-c-mac/ And my frog will be eaten using a similar approach https://blog.smittytone.net/2021/02/05/how-to-debug-a-raspberry-pi-pico-with-a-mac-swd/ S'manth x
  6. So ... Achieved button presses->button events->MIDI messages such that I could have ditched my MVave chocolate ... result! BUT ... refactoring (Restructuring it to a better design) broke it all I've now got a compiling but non-operational, codebase based on a thread per button, nicely encapsulated ... but not working! I fear it is time for me to bite the bullet of getting the proper debugging tool working ... thankfully a week off work (mostly to attend the RCN nursing congress in Brighton) will let me spend some time sorting this (I hope!) S'manth x
  7. SamIAm

    Oldman Feedback

    Purchased a Subzero IEM from Brian. Super comms; item arrived well wrapped, as advertised and very quickly (I goofed and sent my old postcode so it took a few days this end for me to collect it from old residence) Could not have been better, many thanks B! S'manth x
  8. I would also consider a MIDI pedalboard as the Stomp/Boss/Dwarf all have just three footswitches on them. S'manth x
  9. I asked on the MOD forum about the number of AIDA-X simultaneously. Their lead techie suggested that 4 (if in parallel) is possible, two in series would likely be pushing it (The MOD has 4 cores and I think that the way plugins can be alloted to a core is dependent on series/parallel routing). The Dwarf does have a plugin called a Portal (Like in the game!) that is used to connect different plugins in series but allows them to be shared amongst the cores, this may allow the higher number. I might have a play later on my unit and see ... S'manth x
  10. Like the various IR plugins (amp/cab/reverb) on the Dwarf, the AIDA-X lets you load several on the device and switch back and forth as you desire. It would mean more effort modelling but ... Does your Capo and other F/X pedals allow for storage/retrieval of different setting snapshots? (I've not played with real pedals but I gather some have this capability) S'manth x
  11. No millionaire, I've tried various Zooms, HX FX and HX Stomp but have landed on the MOD Dwarf. Sub £500 and insanely powerful. They recently incorporated neural modelling capabilities. A good overview of how it works starts at 3:00. S'manth x
  12. I guess the only way is to try. And Thomann do say ... I first bought a Dwarf from Thomann last year but after three weeks, despite loving it, felt I could not justify the cost (As I was still in the process of building a clone based on a Raspberry Pi & HiFiBerry Audio interface) and they took it back no problems. I then ran up against significant noise issues with my build and stumbled across an offer I could not refuse on a Dwarf in new condition here on BC. S'manth x
  13. Only having used multi-fx units (Zoom now Dwarf) I wonder is this unusual? S'manth x
  14. Sadly yes! I'm wondering if a CC interface is worth incorporating. I've also been browsing the MOD codebase to see if it might be possible to interrogate plugins, it seems that this is only possible at present via the MOD-UI, but I think I could do some http API calls from Trampa to achieve this ... S'manth x
  15. My plan is to use in in addition to the three footswitches on the Dwarf. I'm not sure the Line6 would do the trick. Trampa will have a TRS input for an expression pedal (I've a SONICAKE passive device), after I've got the footswitches sending MIDI (Hopefully just a few hours of playing away) I'll turn to getting that working. In my POC I got it to work so I don;t imagine it will be a lot of effort, even if I incorporate a mapping algorithm (like Morningstar) to allow selection of lin.log mapping of the ADC input to the MIDI value I send. Definately an issue! It is possible to send a MIDI message when the Dwarf loads a new configuration or settings snapshot and I intend to capture this to change the Trampa setup. Trampa will display the state it thinks is the case on the OLEDs, but this may fall out of sync with the Dwarf ... I am exploring if it is possible (either via midi message or other API to determine the actual state of a Dwarf plugin, to allow 100% accurate representation) Ther is a recent new plugin for the Dwarf, which can display on the LCD display state change (based on MIDI messages) that will ease this problem a bit. COOL!!! At present, I managed to get USB and MIDI working over the same USB connection and thus far the simple debugging I've needed works. It is possible (I gather) to run a proper debugger using a second PICO to allow stepping/breakpoints/etc but whilst I've got a PICO wired up to allow this I've not yet plunged into getting it working. Excellent! I cut my teeth on multithreaded C++ in the early 90s (And even got to work with one of the gang of four in 1997!) I'm not doing anything too sophisticated from an OO perspective, but I find it helps me encapsulate/decouple things nicely. Go on ... FreeRTOS FTW! lol Thank you! I will S'manth x
  16. Excellent! I guess BC dark mode does not display the code well ... but not to worry (nor about coding) Once I've got a basic version operational I'll be sharing it via github (Including compiled code) so that others can hopefully enjoy Trampa too. I'll be sharing the github link here when it's ready. S'manth x
  17. Whilst the Dwarf is really sturdy and suits my needs for a multil f/x box (I can use input1 for my bass, input2 for another band members guitar/ukulele and generate a drum track using its midi and drum synth plugins) I see what you mean about the fx loop. It is possible (as I think was mentioned elsewhere) to use Bass->Input1->Internal Signal Chain A->Output1->external f/x chain->Input2->Internal Signal Chain B->Output2->Amp(etc), it would be very nice to have one or two dedicated f/x loops like the GT-100 core or even the single send/return of the HX Stomp. Having said that, I don't have any seperate pedals ... ALL of my f/x run in the Dwarf, so my pedalboard is tiny! And using the AIDA-X neural modelling plugin I hope to be able to drop in models of some of the external pedals that I might want ... an octaver that tracks really low notes being an example. S'manth x
  18. Time to share the sophistication (not!) of the wiring so far. Pushbutton at the top is used in conjunction with the onboard BOOTSEL button to reset the PICO into USB Flash mode, to flash the PICO one simply copies a file to the USB drive, it then reboots running the code. The four pushbuttons at the bottom are the footswitches. A USB cable plugged into the connector on the left carries the MIDI over USB to the host device (Laptop/Dwarf multi-fx unit/etc) as well as supplying power to the PICO. It also carries serial output from the PICO to a terminal emulator I use for simple debugging. S'manth x
  19. Yes, it's part of my button class /* --.-- | ,---.,---.,-.-.,---.,---. | | ,---|| | || |,---| ` ` `---^` ' '|---'`---^ | (C) 2023 Samantha-uk https://github.com/samantha-uk/trampa Adapted from debounce.c https://www.kennethkuhn.com/electronics/debounce.c /****************************************************************************** debounce.c written by Kenneth A. Kuhn version 1.00 This is an algorithm that debounces or removes random or spurious transistions of a digital signal read as an input by a computer. This is particularly applicable when the input is from a mechanical contact. An integrator is used to perform a time hysterisis so that the signal must persistantly be in a logical state (0 or 1) in order for the output to change to that state. Random transitions of the input will not affect the output except in the rare case where statistical clustering is longer than the specified integration time. The following example illustrates how this algorithm works. The sequence labeled, real signal, represents the real intended signal with no noise. The sequence labeled, corrupted, has significant random transitions added to the real signal. The sequence labled, integrator, represents the algorithm integrator which is constrained to be between 0 and 3. The sequence labeled, output, only makes a transition when the integrator reaches either 0 or 3. Note that the output signal lags the input signal by the integration time but is free of spurious transitions. real signal 0000111111110000000111111100000000011111111110000000000111111100000 corrupted 0100111011011001000011011010001001011100101111000100010111011100010 integrator 0100123233233212100012123232101001012321212333210100010123233321010 output 0000001111111111100000001111100000000111111111110000000001111111000 I have been using this algorithm for years and I show it here as a code fragment in C. The algorithm has been around for many years but does not seem to be widely known. Once in a rare while it is published in a tech note. It is notable that the algorithm uses integration as opposed to edge logic (differentiation). It is the integration that makes this algorithm so robust in the presence of noise. ******************************************************************************/ #include "button.h" Button::Button(int id, ButtonConfig* buttonConfig, uint pin) { _id = id; _buttonConfig = buttonConfig; _pin = pin; } void Button::init(void) { gpio_init(_pin); gpio_set_dir(_pin, GPIO_IN); gpio_pull_up(_pin); } bool Button::pressed() { /* Step 1: Update the integrator based on the input signal. Note that the integrator follows the input, decreasing or increasing towards the limits as determined by the input state (0 or 1). */ if (gpio_get(_pin) == 1) { if (_integrator > 0) _integrator--; } else if (_integrator < INTEGRATOR_MAX) _integrator++; /* Step 2: Update the output state based on the integrator. Note that the output will only change states if the integrator has reached a limit, either 0 or MAXIMUM. */ if (_integrator == 0) _pressed = false; else if (_integrator >= INTEGRATOR_MAX) { _integrator = INTEGRATOR_MAX; /* defensive code if integrator got corrupted */ _pressed = true; } return _pressed; } void Button::setState(ButtonState state) { // write_serial("Button[%d] from [%d]->[%d]\r\n", _id, _state, state); _state = state; } void Button::check(void) { // Get the debounced current debounced pressed state of the button bool isPressed = pressed(); // bool isPressed = gpio_get(_pin); // Process the state machine for the button switch (_state) { case ButtonState::IDLE: if (isPressed) { // Capture the time _buttonPressedTime = get_absolute_time(); // Reset _clickCount _clickCount = 0; // should we send a PRESS event if (!_buttonConfig->_clickDetect) fireEvent(ButtonEvent::PRESS); // Change to PRESSED state setState(ButtonState::PRESSED); } break; case ButtonState::PRESSED: if (!isPressed) { // The button is now released if (_buttonConfig->_clickDetect) { // We ARE detecting clicks // Capture the time _buttonReleasedTime = get_absolute_time(); // Change to RELEASED state setState(ButtonState::RELEASED); } else { // We ARE NOT detecting clicks fireEvent(ButtonEvent::RELEASE); // Reset _clickCount _clickCount = 0; // Change to IDLE state setState(ButtonState::IDLE); } } else { // The button is still pressed // If we are detecting clicks and the time since _buttonDownTime is // longer than _holdDelay if (_buttonConfig->_clickDetect && absolute_time_diff_us(_buttonPressedTime, get_absolute_time()) >= _buttonConfig->_holdDelay) { fireEvent(ButtonEvent::HOLD); // Capture the time _buttonRepeatTime = get_absolute_time(); // Change to HOLD state setState(ButtonState::HOLD); } } break; case ButtonState::RELEASED: if (isPressed) { // The button is pressed // Capture the time _buttonPressedTime = get_absolute_time(); // Increment _clickCount _clickCount++; // Change to PRESSED state setState(ButtonState::PRESSED); } else { // The button is still releasaed // check to see if _clickDelay has passed since we entered RELEASED // state if (absolute_time_diff_us(_buttonReleasedTime, get_absolute_time()) >= _buttonConfig->_clickDelay) { // _clickDelay time has passed so we report the number of clicks fireEvent(ButtonEvent::CLICK); // Reset _clickCount _clickCount = 0; // Change to IDLE state setState(ButtonState::IDLE); } } break; case ButtonState::HOLD: // If the button is now released // _clickCount is used to indicate if any single clicks preceeded the hold // These are used as "shifts" to potentially alter the behaviour of // hold/repeat events. if (!isPressed) { // The button is now released fireEvent(ButtonEvent::HOLD_RELEASE); // Reset _clickCount _clickCount = 0; // Change to IDLE state setState(ButtonState::IDLE); } else { // The button is still pressed // If time down is longer than _repeatDelay if (absolute_time_diff_us(_buttonRepeatTime, get_absolute_time()) >= _buttonConfig->_repeatDelay) { fireEvent(ButtonEvent::REPEAT); // Reset _buttonHoldTime _buttonRepeatTime = get_absolute_time(); } } break; } } void Button::fireEvent(ButtonEvent event) { // Check to make sure that we have a cbFunction if (_buttonConfig->cbButtonEvent) { _buttonConfig->cbButtonEvent(_id, event, _clickCount, _latched); } if (_buttonConfig->_latching) _latched = !_latched; } ButtonConfig::ButtonConfig() {} S'manth x
  20. So button logic code written and checked. Flashed the PICO and nothing worked in any logical way 😖 Checked the code again ... and then again. Removed the debounce logic ... same thing. But then I realised that I had the state wrong for my button. My code was looking for active HIGH and the button is configured as active LOW ... D'oh! After correcting this, it now seems to work as intended ... well pleased Welcome to minicom 2.8 OPTIONS: Compiled on Oct 24 2022, 11:16:41. Port /dev/tty.usbmodemTrampa1, 16:36:52 Press Meta-Z for help on special keys Button[1]- Press Button[1]- Release Button[2]- Press Button[2]- Release Button[3]- Click Button[3]- Click Button[3]- DoubleClick Button[3]- TripleClick Button[3]- Hold Button[3]- Repeat Button[3]- Repeat Button[3]- Repeat Button[3]- Repeat Button[3]- Hold Release Button[3]- Hold(Shifted) Button[3]- Repeat(Shifted) Button[3]- Repeat(Shifted) Button[3]- Repeat(Shifted) Button[3]- Repeat(Shifted) Button[3]- Hold(Shifted) Release Button[4]- Click Button[4]- Hold(Shifted) Button[4]- Repeat(Shifted) Button[4]- Repeat(Shifted) Button[4]- Repeat(Shifted) Button[4]- Hold(Shifted) Release Press and Release are instant! Click (Single/Double/Triple) are detected about 0.2s after the last release. The shifted Hold (etc) are triggered by a short click followed by a hold ... so in all I am able to get 5 different actions from one button (if it is configured as clickDetect ON). I want to add some logic to detect simulataneous presses of adjacent buttons, but first I'm going to add in the "Let's send a MIDI CC message" based on the events raised. S'manth x
  21. Being a short scale fiver player ... I'd pop round to GAK (20 minutes on the bus) and grab one of their in stock Ibanez TMB-35s and a £30 strap. (I'm assuming the venue will provide a cable!) S'manth x
  22. An overview/review of the MOD Dwarf and the AIDA-X is a neural model player plugin.
  23. I've just got some crude timings and it appears that a scan of my 4 buttons comes in at under 10us when they are quiescent and no higher than about 75us when I'm pressing them. edit: I've just realised most of this increase is probably due to me serial printing when the button is pressed! S'manth x
  24. Sound thinking. I am using FreeRTOS to prempetively multithread. Each button object has its own thread with a wait 5ms then check the button kinda logic, so I would not anticipate any stacking up of latency as you describe. I've not (and I'm not totally sure how I could without falling foul of Heisenberg) timed how long it takes the code to read the button state and run the simple FSM, but my gut says it is likely to be really fast (and I've some performance tuning ideas I could implement if needed.) Having said all that, I've not a lot of experience with microcontrollers so ... hic sunt dracones! 🤣 S'manth x
  25. I did come across a s/w debounce that handles parallel inputs and the PICO does have a read all GPIO pins at once function, but I steered away from that approach simply because it seems cleaner (tho admittedly not as effecient) to have a single button object per GPIO pin. I had considered h/w debouncing, but I'm using SPST switches and I got the impression that the approaches to debounce these in h/w still require about 20ms to reach a steady output signal (This sorta makes sense at a gut level too, regardless of how you debounce something, you need it to stop bouncing to do so), so it didn't seem worth bothering. S'manth x
×
×
  • Create New...