Jump to content
Why become a member? ×

SamIAm

⭐Supporting Member⭐
  • Posts

    1,277
  • Joined

  • Last visited

  • Days Won

    6

Everything posted by SamIAm

  1. 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
  2. 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
  3. 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
  4. 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
  5. I would also consider a MIDI pedalboard as the Stomp/Boss/Dwarf all have just three footswitches on them. S'manth x
  6. 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
  7. 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
  8. 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
  9. 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
  10. Only having used multi-fx units (Zoom now Dwarf) I wonder is this unusual? S'manth x
  11. 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
  12. 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
  13. 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
  14. 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
  15. 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
  16. 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
  17. 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
  18. 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
  19. An overview/review of the MOD Dwarf and the AIDA-X is a neural model player plugin.
  20. 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
  21. 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
  22. 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
  23. Only in the clickDetect mode. In the non clickDetect I will fire the 'pressed' event as soon as the the debounce code reports the button is pressed, ditto for the 'released' event ... I would hope that the debounce settle time will not add more than about 10ms or so (Of course I'll need to see how quickly the switches I've got do actually take to settle). (I've just noticed that my state diagram did not reflect this correctly, I've fixed it) The system will be doing a number of decoupled things including. Detecting button state changes Sampling the expression pedal changes (via ADC) Sending out MIDI messages Checking for MIDI messages. I don't intend on doing any MIDI hub stuff at present, but I intend to use the Dwarf buttons to select/load snapshots/pedalboards. It is possible to configure things (using one of the MIDI plugins) so that a different MIDI message is sent from the Dwarf each time and I intend on using this to reconfigure the Trampa. Reading/sending HTTP messages for the web configuration interface. Periodic updating the OLED displays to allow for scrolling of long text content. I'm using the FreeRTOS kernel to provide threading, I'm not sure yet if I'll run one per category (one button thread, one display thread) or one thread per individual input/output device ... the latter has the appeal that once I've created a deviceobject and kicked it off running I can pretty much forget about it and having to do my own interleaving/scheduling of checking this, that and the other. S'manth x
  24. Some progress made on detecting button presses. I found a nifty algorithm to debounce presses (it uses an integration approach). After a lot of reading it seems that detecting presses using interrupts is generally not considered a good idea, so I am now having a background timer fire a "button tick" every 5ms that will check button state, seems to be working. I think I've got a state machine sorted for the buttons, this will be run (for each button) when the "button tick" occurs. A button can be configured in one of two ways: clickDetect OFF A button will simply react to a press and release. There should be minimal (a few ms) delay in doing so. This will be suitable for tap tempo/looper type situations where the latency needs to be as low as possible. A button can be configured to be latching- alternate press/release activity will alternately send a message A or message B when pressed (And optionally message A1 & B1 upon release). non-latching - the same message will be sent every time it is pressed (optionally a differnet message when released) clickDetect ON A button will be able to detect single/double (even triple if desired) clicks and send a suitable singleClick/doubleClick/etc message when it has decided which situation applies. The button needs to wait a short time (configurable) after a release before it decides that no more clicks are going to happen. I'm going to try about 0.3 seconds initially and see how it goes. Whilst not a huge delay (Hopefully responsive enough for changing snapshots or perhaps even turning on/off 'pedals') I suspect it will not be great for time sensitive uses (Hence the clickDetect OFF mode). A button in theis mode can also detect if it is held down for a longer time (say 0.6s) and send a hold message and if it continues to be held down it will periodically send a repeat message, I see this as useful for scrollowing through patches/pedalboards between songs. I'd appreciate those of you with a technical bent letting me know of any issues/gaffs you can see. S'manth x
  25. Overkill perhaps, but it would do the job. https://www.amazon.co.uk/Cubilux-Bidirectional-4-Channel-Headphones-Subwoofer-6-35mm/dp/B0B45MZG1J/ S'manth x
×
×
  • Create New...