Open sleepysunday1979 opened 3 years ago
First of all I think things are more visible if you print them as a true hexdump, with ASCII giving clues as to where things start/stop.
00000000: 50 54 43 46 54 02 00 00 01 00 00 00 09 00 00 00 PTCFT...........
00000010: 01 00 00 00 00 00 00 00 00 00 73 73 2D 74 65 73 ..........ss-tes
00000020: 74 31 30 30 10 00 00 09 10 00 00 01 10 00 00 09 t100............
00000030: 10 00 00 01 10 00 00 09 10 00 00 01 10 00 00 09 ................
00000040: 10 00 00 01 10 00 00 09 54 58 4A 31 40 00 00 00 ........TXJ1@...
00000050: 55 4B 90 BB 83 76 83 8A 83 41 83 93 83 76 82 C6 UK...v...A...v..
00000060: 55 53 90 BB 83 4C 83 83 83 72 83 6C 83 62 83 67 US...L...r.l.b.g
00000070: 82 F0 97 5A 8D 87 82 B3 82 B9 82 BD 83 4E 83 89 ...Z.........N..
00000080: 83 93 83 60 83 54 83 45 83 93 83 68 81 42 00 00 ...`.T.E...h.B..
00000090: 54 58 45 31 C8 00 00 00 61 62 63 64 65 66 67 68 TXE1....abcdefgh
000000A0: 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 ijklmnopqrstuvwx
000000B0: 79 7A 30 31 32 33 34 35 36 37 38 39 2E 61 62 63 yz0123456789.abc
000000C0: 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 defghijklmnopqrs
000000D0: 74 75 76 77 78 79 7A 30 31 32 33 34 35 36 37 38 tuvwxyz012345678
000000E0: 39 2E 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 9.abcdefghijklmn
000000F0: 6F 70 71 72 73 74 75 76 77 78 79 7A 30 31 32 33 opqrstuvwxyz0123
00000100: 34 35 36 37 38 39 2E 61 62 63 64 65 66 67 68 69 456789.abcdefghi
00000110: 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 jklmnopqrstuvwxy
00000120: 7A 30 31 32 33 34 35 36 37 38 39 2E 61 62 63 64 z0123456789.abcd
00000130: 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 efghijklmnopqrst
00000140: 75 76 77 78 79 7A 30 31 32 33 34 35 36 37 38 39 uvwxyz0123456789
00000150: 2E 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F .abcdefghijklmno
00000160: 45 44 54 42 D8 00 00 00 21 00 00 D2 04 14 00 0F EDTB....!.......
00000170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000180: 21 00 00 82 01 00 80 01 40 01 00 00 00 00 00 00 !.......@.......
00000190: 00 00 00 00 00 00 00 00 21 00 00 D2 04 14 00 0F ........!.......
000001A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001B0: 21 00 00 82 01 00 80 01 40 01 00 00 00 00 00 00 !.......@.......
000001C0: 00 00 00 00 00 00 00 00 21 00 00 D2 04 14 00 0F ........!.......
000001D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001E0: 21 00 00 82 01 00 80 01 40 01 00 00 00 00 00 00 !.......@.......
000001F0: 00 00 00 00 00 00 00 00 21 00 00 D2 04 14 00 0F ........!.......
00000200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000210: 21 00 00 82 01 00 80 01 40 01 00 00 00 00 00 00 !.......@.......
00000220: 00 00 00 00 00 00 00 00 21 00 00 D2 04 14 00 0F ........!.......
00000230: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000240: 50 50 52 4D 0C 00 00 00 00 00 00 00 00 00 00 00 PPRM............
00000250: B2 1D 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000260: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000270: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000290: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000002A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000002B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000002C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000002D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000002E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000002F0: 00 00 00 00 00 00 00 00 ........
The 'Construct' declaration allows for variable chunks, or different number of the elements. You can automatically fit data with the greedy
function, but in this case I'd be willing to guess that the 09
on the first line is the number of 'pedals' (as you call them - I would think that they are more 'slots' within one pedal configuration).
You have assigned the name effects
to the 09
byte, use that to declare the size of an array...
PTCF = Struct(
Const(b"PTCF"),
Padding(8),
"effects" / Int32ul,
Padding(10),
"name" / PaddedString(10, "ascii"),
"ids" / Array(this.effects, Int32ul)
)
Note you can use an array of another Struct
should there be chunks of more complicated/repeated data.
I just pushed some changes to decode_preset.py
which might work for you.
thanks mungewell! that works perfectly! tested on several patches with 5, 6, 7 and 9 slots. :)
i'll write that same fix into zoomzt2.py to test that it works there as well.
Cool, glad it worked.
Which bits of zoomzt2.py
don't work with the GCE-3?
hi there - so your zoomzt2 is working really nicely with the GCE-3 now.
I am just posting a video on how I can change mode to a B3N! Will work on the other changes later - I suspect we can use your -I mode to install except I think there is a bug? Shouldnt you also send the data as well as the filename to the upload?
WHAT IS MISSING?
Well I would love to show you what I am doing different to gather pedal info. I need to work on the patch format for the non-G1Four type pedals (G5n., G3n ...)
My guess (not tried) is it would be possible to inject your FLST_SQL.ZDT into a GCE-3. We know how to determine which model it is emulating. And I think I can see how to set the model now!
We can set parameters. We can set FX You can inject new ZD2. Not sure how these pedals will ever be able to accept expression pedal input. If someone knows Gadwin and can hint to port these changes to the ToneLib it would be fantastic (even better if there was a Pi version - hint).
@mungewell - to answer your question, i think what wasn't working with the zoom-zt2.py was user error. :/
tested a few things yesterday and it seems to be working as expected, mainly just with the config output. originally it wasn't outputting anything with the -s flag, now it is. so i suspect it was just me.
@shooking has done an immense amount of work with reverse engineering the gce so far, between both of your repos you've nearly cracked this thing!
i'm determined to try to get the expression pedal working, i might have a look at it today with the rotary encoder i have connected to my rig. i'll let you know of the outcome.
i can confirm that the pedal effects work on the gce-3 via usual parameter effect commands.
didn't get a chance to test with the rotary . . . i haven't quite got my head around the MSB + LSB settings for parameters yet.
but doing a quick test with mungewell's example for changing params got some positive results. code sample for an effect in slot 1 of a patch.
zoomIO = mido.open_ioport('ZOOM GCE-3 MIDI 1')
sxPedalHigh = mido.Message.from_bytes([0xF0, 0x52, 0x00, 0x6E, 0x64, 0x03, 0x00, 0x00, 0x02, 0x32, 0x00, 0x00, 0x00, 0x00, 0xF7], 100)
sxPedalLow = mido.Message.from_bytes([0xF0, 0x52, 0x00, 0x6E, 0x64, 0x03, 0x00, 0x00, 0x02, 0x19, 0x01, 0x00, 0x00, 0x00, 0xF7], 100)
zoomIO.send(sxPedalHigh)
time.sleep(1)
zoomIO.send(sxPedalLow)
time.sleep(1)
zoomIO.send(sxPedalHigh)
will test with a rotary soon. as soon as i get my head around the bit stuff. :/
That's pretty awesome information about the pedal, wonder if that'll work with regular pedals. We had been trying to get pedal working with the G1Four on #18
The bit stuffing is just that the bytes can not exceed 0x7f, so
127 = 0x007f
128 = 0x0100
I wrote an adapter for Construct which does this, if it's clearer in code. We could reuse this... https://github.com/mungewell/uno-synth-utils/blob/master/uno_synth.py#L15
ah, i saw that issue the other day. might be worth me opening it up again, and taking some photos of the circuitboard so you can have a look.
half the time i don't really know what i'm looking at . . . i'm a front-end developer, mostly, i just like taking things apart. i did think it was interesting that the board has a jtag connector.
In one of my YT I show the GCE working fine and accepting parameters etc"
When I look at what you are sending (@sleepysunday1979 )
sxPedalHigh = mido.Message.from_bytes([0xF0, 0x52, 0x00, 0x6E, 0x64, 0x03, 0x00, 0x00, 0x02, 0x32, 0x00, 0x00, 0x00, 0x00, 0xF7], 100)
sxPedalLow = mido.Message.from_bytes([0xF0, 0x52, 0x00, 0x6E, 0x64, 0x03, 0x00, 0x00, 0x02, 0x19, 0x01, 0x00, 0x00, 0x00, 0xF7], 100)
zoomIO.send(sxPedalHigh)
time.sleep(1)
zoomIO.send(sxPedalLow)
time.sleep(1)
zoomIO.send(sxPedalHigh)
that is sending 0x1 0x19 to FX1, P3 right? Not seeing why this is a pedal?
Regarding the GCE-3. I am just checking the "change mode" as I type It's working! But I need to cull the code. Conceptually it is: turn on editor/PC and a couple of other modes. Send MODEL.ZSP - you copy the particular firmware into this file - I guess like how one copies new FX to FLST_SEQ Bit more stuff Check num patches etc - @mungewell 7805 (I guess 05x128 0x78) crops up a lot - seems a familiar number - do you recall it? Using values obtained, load the patches. Cycle thru the ZD2 FX to get screen decode hand back new pedal.
Checked them in here: https://github.com/shooking/ZoomPedalFun/tree/main/GCE-3/InitialModeChangingExperiments Will work on checking if the models's data is same as other source I found.
TO DO: Start to work on checking if we can handle non "X1Four" patch formats (ie G3n, G5n). Merge later Mungewell code into what I am doing. Work out how to make my additional requirements clean with view to getting the zoomz2 to do it (specifically the "ask pedal to dump state into JSON ... Patch -> FX's with bitmaps".
I am loving where this collaboration is going - I think soon we will have remote control, either GUI touchscreen or physical hardware, of a GCE3 that can be switched into any available mode.
@shooking, correct, sorry not a physical pedal. but i wasn't sure if you'd tested the parameter changing of the pedal slots for the gce.
i guess was confirming that the pedal effects in the slots weren't locked for the gce, so the solution for the pedal is still via a pi. but the cost of a pi, an cheap wah/volume pedal and a gce is only marginally more than a g1four; and then you get all the other pedals emulated to boot.
i'm currently using this screen, but at the moment haven't got anything useful coming through from the gce, only a few tests on text and image output and have written a simple menu for it all. i like eink because it's so low power, for my purposes this doesn't need instant feedback to the millisecond, and lower power consumption is more a priority.
https://www.waveshare.com/2.13inch-touch-e-paper-hat.htm
in a pefect world, it would be good to modularise the working code for the gce so you could plug in any peripherals to it with a pi, and then just modify some code to get it up and running.
@mungewell - the other neat little thing i got working pretty quickly was headless recording from the gce to the pi zero, driven from a rotary push switch, just using pyaudio.
another little interesting discovery, triggering the looper works via midi as well. tested on the following modes:
g5n mode
lp-mono: 40s
lp-stereo: 20s
lp-mn2: 40s
lp2-st2: 20s
g3xn mode
lp-mono: 40s
lp-stereo: 20s
lp-mn2: 40s
lp2-st2: 20s
b3n mode
lp-mn2: 40s
lp-mono: 40s*
lp-stereo: 20s*
lp2-st2: 20s*
*not tested, assumed the same as other modes```
Excellent news. I see the FX but since u cannot work our how the features were supposed to work on real pedal I didn't explore more.
Dean - I think I gave your rights on the github. Can you kink in your page to the main Readme (and I will check where else to add it). Or let me know your github project so I can reference it please.
The wiki on my site should be open to all of you. Would love to get this info merged into someone wiki to make it easier to consume.
I still didn't get what you mean about pedal. There are two aspects of general interest 1 - can the pedal mechanism from an X pedal be intercepted / exposed or is it all happening in a DAC? 2 - clearly with our own DAC we can digitise then send input to any parameter we like. The Zoom itself also has P commands - pedal controllable inputs. I have never really understood that feature.
Does the looper controlled output also output via the headphones or you have to capture it into Pi? And ... well... capture a few in, use some buttons to toggle playback... via Pi. Have u just unlocked multi track looper ??
Looper outputs directly to the headphone port on the GCE. I actually didn't check whether the looper also outputs via USB to the pi. I suspect it does, just based on testing.
I'll forward you my repo shortly. It's still private because it's such a mess! It also doesn't add much at the moment, as all the commands are using your and mungewell's code. At the very least, it should help others set up their own little rig with any pi.
well I want to give credit where it is due. If you make an YT demo of the looper please send a link - I suspect it will be super popular. Like I said the real pedal is not very intuitive.
I like the idea of the ePaper. This is one of the "write once, dont need to power it" right? Hence the low power. I guess one big enough, or a few ganged together, to provide the feedback would be awesome. I have a ton of rotary encoders (got them cheap when I was going to make a full Miniak panel - then found my software was good enough). 9 knobs and some selector (FX1 .. n) would probably do it.
I have rebricked the GCE-3 a few times. Thank heavens for the firmware. Odd thing though. When I reinstall the firmware I always get my "pants" as first patch .. on a real pedal one can hold down to reset at bootup. I guess not on these GCEs.
I feel like we've totally hijacked mungewell's repo into a wishlist for the GCE! @mungewell any chance you can actually get your hands on one? Happy to donate to the cause. ;) They're 100 here down under, and about 60 pounds over the Commonwealth pond.
sure I would Paypal donate 50% no problems. I am also updating on my GitHub - started looking at the different patch formats by revisiting the B1X/G1X. I didnt realise the preamble (before PTCF) encodes the LSB/MSB/C0.
regarding the 0x7805 == 0x5 0x78 == 5 128 + 7 16 + 8 = 760 - this is the patch payload size right.
I notice @mungewell uses 760 in the decode_preset.py
With the other pedals the 09 decode needs a little assistance. It is no longer /10, %10 but related to the bank size according to the 6e 44 -> 63 43 output. I summarized what I mean here: https://github.com/shooking/ZoomPedalFun/wiki/ZoomPatchFormats
@shooking I'm not totally following your thoughts about '760'. I assume that you mean the padding
command here:
https://github.com/mungewell/zoom-zt2/blob/master/decode_preset.py#L63
This was included from observations, but is only really needed on re-encoding the presets (ie to bump size up-to known/preferred size). It can be change to any value, not sure if possible/how to tie it to the number of effect slots in the patch (ie to fx_count
).
That said the observed patched from the GCE-3 still seems to be set to 760 bytes in the examples I have seen... https://github.com/mungewell/zoom-zt2/issues/32#issuecomment-901457645
Note: 760 is the unpacked size, the midi blob will be longer with 8bit->7bit packing.
@sleepysunday1979 Can you share the Midi commands for controlling the looper?
You listed times/timing for both 'lp' and 'lp2' (in mono and stereo), are you suggesting that there are two loopers (pre and post FX, maybe) which both run together?
BTW the GCE-3 is $140 CND, but seems to be out of stock or special order. Not sure I want to dive further into yet another project ;-).
hi So I got a G3n at weekend. When I use zoomz2 as it I get a short read in the construct. When I interrogate the 0x44 sysex command, use that value (05 60 = 736) everything works.
So I assert the correct patch size is derived from:
pi@raspberrypi:~/Software/ZoomPedal $ more CheckBankSize.sh
export MIDI_DEV=`amidi -l | grep ZOOM | awk '{print $2}'`
amidi -p ${MIDI_DEV} -S "f0 52 00 6e 44 f7" -r temp.bin -t 1 ; hexdump -C temp.b
in
pi@raspberrypi:~/Software/ZoomPedal $ ./CheckBankSize.sh
30 bytes read
00000000 f0 52 00 6e 43 16 01 60 05 16 01 03 00 02 00 00 |.R.nC..`........|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 f7 |..............|
0000001e
See the 01 16 => 150 patches, 5 60 => 736 bytes and the 03 => 3 in a bank.
#ZPTC = Padded(760, Struct(
ZPTC = Padded(736, Struct(
Const(b"PTCF"),
works with the G3n.
I am still getting issues finding the LP-MONO, Rhythm etc FX.
pi@raspberrypi:~/Software/zoom-zt2/G3n $ grep ception !$
grep ception midi.log
INFO:root:Exception looking up FXID: 16 120 Loopertron 251658256 0xf000010
INFO:root:Exception looking up FXID: 16 112 Empty 234881040 0xe000010
INFO:root:Exception looking up FXID: 16 120 Empty 251658256 0xf000010
But I will work on this in the week, do some more decoding on the G3n then look inside see if I can be of help regarding how they interface the external expression pedal into the chip and how the FS1, 2, 3 and Scroll/stomp work.
Ok and the G3n has option to turn on / off external pedal
on: F0 52 00 6E 64 03 00 0A 0A 01 00 00 00 00 F7 off: F0 52 00 6E 64 03 00 0A 0A 00 00 00 00 00 F7
This is "received" by the Zoom but it doesnt seem to have visible effect when send back to it. Bit like say when one changes the 440Hz say - comes out of tuner mode but doesnt seem to stick. So maybe one has to do something first.
@sleepysunday1979 Well the GCE-3 came up on sale for under (the magic) $100 CDN... I now have one! ;-)
Now if we can unlock how to send the expression pedal input ...
I find these little GCE-3 quite cool. I am tempted to open mine up to see if there is a real line level audio out. The earphone jack is wrong level for an amp but the USB audio is pretty cool. I am a bit maxed out with real work at rhe moment but hope to get my mojo back.
I really like being able to setup one of many pedals with this thing for practice. Then I take the real G5n with me for the gig. Simples.
hi mungewell,
i've been talking to shooking, and we're both trying to get some comms happening with the zoom gce-3 and a pi, just wondering if your code can easily be adapted for it.
it seems to work, for the most part with scraping data from the gce, but when it comes to grabbing the patches - i just can't seem to get it to work.
this is actually a little above my paygrade, but i think it might be because the gce-3 can have up to 9 pedals in it, so the byte lengths change dramatically between 3 pedals and 9 in a preset.
jsut wondering if you might be able to shed some light on how to adapt your code a little to account for this. here's an example dump, that i can't get decode_presets working on easily.
50 54 43 46 54 02 00 00 01 00 00 00 09 00 00 00 01 00 00 00 00 00 00 00 00 00 73 73 2d 74 65 73 74 31 30 30 10 00 00 09 10 00 00 01 10 00 00 09 10 00 00 01 10 00 00 09 10 00 00 01 10 00 00 09 10 00 00 01 10 00 00 09 54 58 4a 31 40 00 00 00 55 4b 90 bb 83 76 83 8a 83 41 83 93 83 76 82 c6 55 53 90 bb 83 4c 83 83 83 72 83 6c 83 62 83 67 82 f0 97 5a 8d 87 82 b3 82 b9 82 bd 83 4e 83 89 83 93 83 60 83 54 83 45 83 93 83 68 81 42 00 00 54 58 45 31 c8 00 00 00 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 30 31 32 33 34 35 36 37 38 39 2e 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 30 31 32 33 34 35 36 37 38 39 2e 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 30 31 32 33 34 35 36 37 38 39 2e 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 30 31 32 33 34 35 36 37 38 39 2e 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 30 31 32 33 34 35 36 37 38 39 2e 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 45 44 54 42 d8 00 00 00 21 00 00 d2 04 14 00 0f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 21 00 00 82 01 00 80 01 40 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 21 00 00 d2 04 14 00 0f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 21 00 00 82 01 00 80 01 40 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 21 00 00 d2 04 14 00 0f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 21 00 00 82 01 00 80 01 40 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 21 00 00 d2 04 14 00 0f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 21 00 00 82 01 00 80 01 40 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 21 00 00 d2 04 14 00 0f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 50 50 52 4d 0c 00 00 00 00 00 00 00 00 00 00 00 b2 1d 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
i can, however, get it to work by pure brute force by editing the PTCF section to include 9 ids, and editing the EDTB to include those effects as well.PTCF = Struct( Const(b"PTCF"), Padding(8), "effects" / Int32ul, Padding(10), "name" / PaddedString(10, "ascii"), "id1" / Int3 2ul, "id2" / Int32ul, "id3" / Int32ul, "id4" / Int32ul, "id5" / Int32ul, "id6" / Int32ul, "id7" / Int32ul, "id8" / Int32ul, "id9" / Int32ul )
but doing it this way means it fails on presets that have less than 9 pedals.hoping you might have some ideas on how to get it working for different pedal combos! great little library you've made, and i've learnt a lot by digging around in it . . . obviously haven't quite learnt enough yet though!
cheers.