Anyone have a FV-1 plus microcontroller design which emulates EEPROM?

Started by Digital Larry, December 28, 2020, 05:14:11 PM

Previous topic - Next topic

Digital Larry

I really need an FV-1 platform which is capable of holding dozens of separate programs, if not more.  It's one thing to have a pedal which has 8 or 16 programs and allow the microcontroller to manage presets which amount to one of the available programs plus knob settings.  However I really need to have more programs available all the time as I don't want to constantly be loading 8 at a time like I'm doing currently.

The few projects (or products) I've seen combine a micro and the FV-1 but the storage for individual programs is still pretty small.  8 or 16.

I've read a number of people who claim to have achieved E-squared interface through the micro but I just want to find something that will work without having to spend months debugging it.

Another possibility would be to use the micro to program the E-squared whenever a bank switch was needed.  It would be a bit slower no doubt.

I have a couple of the old SKRM modules I could use... just add some input and output buffering, maybe a Teensy, 4 pots (3 control pots plus wet/dry mix) and an encoder with pushbutton for menu navigation.  Oh, yeah it needs an OLED of course.
Digital Larry
Want to quickly design your own effects patches for the Spin FV-1 DSP chip?
https://github.com/HolyCityAudio/SpinCAD-Designer

vigilante397

I've thought about doing something similar, but basically just have a handful of EEPROMs that are routed through solid-state relays or something controlled by a microcontroller, and that handles all the switching of effects. Whatever you're using for effect selection (rotary encoder, pushbuttons, etc) will go to the microcontroller, then it just triggers the appropriate relay to connect the corresponding EEPROM and send the FV-1 the address bits to choose the effect you want. If you have an I2C capable microcontroller it would be pretty easy to add an OLED display for easy navigation and fancy graphics.

Why haven't I done this already, you ask? Because I have yet to find a need for more than 8 effects at a time :P Kind of working on something similar right now, but not with FV-1. Using the ATMega328P because coding isn't really my thing, but if I'm in the Arduino IDE I can make things work :P
  • SUPPORTER
"Some people love music the way other people love chocolate. Some of us love music the way other people love oxygen."

www.sushiboxfx.com

niektb

Well, I've looked into it but the problematic part was finding a (cheap) Arduino-ish micro that has enough storage to hold the contents of multiple EEPROMs :)

deadastronaut

of no help here, but ive just made a pcb which uses the onboard fv-1 sounds, and 2 eeproms, for a total of 24 patches..with a toggle to select banks a/internal/b...just waiting on the pcbs..
and will be able to just plug in my pickit2 into the side and reprogram the eeproms ....kind of development pedal if you like.

i was sick of it on my breadboard and removing the eeprom everytime etc... so will make my experimenting with patches a lot easier.


anyway as you were....following.  :)
https://www.youtube.com/user/100roberthenry
https://deadastronaut.wixsite.com/effects

chasm reverb/tremshifter/faze filter/abductor II delay/timestream reverb/dreamtime delay/skinwalker hi gain dist/black triangle OD/ nano drums/space patrol fuzz//

free electron

I have done that in the past using PSoC4, there is a hardware block doing exactly that: EZI2C
https://www.cypress.com/documentation/component-datasheets/ezi2c-slave

The way i did it is to have the 512 byte blocks of FV-1 programs stored as an array in Flash, then point the EZI2C buffer (there's an  autogenerated API for that) to the new program i want to load and toggle any S0-2 pins to init the program reload. So in practice there is no need to use all the S program change inputs, only one or the Internal/External pin, anything that will initiate the reload. The actual program binaries were changed in the firmware by switching the data pointers.

I haven't tried it with an AVR. i'm not sure if the slave i2c implementation will be fast enough to ideally emulate an eeprom chip. With PSoCs, this block is made of logic fabric /cpld, all worked fine. Having an MCU really opens a few more options, like generating a variable clock for the DSP, PWMs for pot inputs.
Another potentially interesting idea would be to use an SD card to store all the hex (or converted to bin) files on a file system and load them from the card to RAM and then via i2c to FV-1. Obviously it would be slower, but perhaps more useful if having many patches.
A ~$15 PSoC5LP dev stick could do the job quite nicely. Ontop of that it could act as a USB midi interface for easy integration with other software.



Digital Larry

One of the designs I looked at was the Basestar, which actually seems pretty nice and solves some practical issues with the FV-1.  The guy who developed it said that the original Cypress CPU module was no longer available, but it looks like there's a form factor equivalent model that is in distribution.  I would build one of these if I could get past the E-squared issue.

https://github.com/hexeguitar/BasestarFV1

That one still defers the I2C programming of the E-squared to a 4 pin header rather than going anywhere near the micro.  I sent the guy a message to see if he has any PCBs left.

Realistically, I could see wanting 128 programs and 128 patches.  I started using SpinCAD Designer again after about 4 years of not thinking about the FV-1 at all.  I can whip out a bank of 8 programs in about 30 to 60 minutes and have a few of them be really good.  I'm always refining the patches a bit so it would be a huge time saver to just be able to update them directly over USB.  The biggest drawback to the FV-1 is just these few programs IMO.  I know that for a commercial pedal product that is not an issue. 

But SpinCAD lets you work so fast compared to any other non-graphical method, that I start trying to push the limits of what can be jammed into 128 instructions, even if they sound strange or don't make total sense or do some things "wrong".  So my FV-1 sounds include a handful of normal sounding reverbs, delays, modulations, etc. and then a whole bunch of strange sounding things that I don't think I've ever really heard before.
Digital Larry
Want to quickly design your own effects patches for the Spin FV-1 DSP chip?
https://github.com/HolyCityAudio/SpinCAD-Designer

free electron

That would be me :)
Sorry i haven't had time to reply to your email yet.
I still have a few Basestrar PCBs left , but the other module you mentioned (cy8ckit-043) will not work with it. Different MCU, different pinout, they are not really compatible.

I thought about redesigning the board to use the MCU directly instead of the module, but i don't use FV-1 too often these days. Not after getting a stereo IR convolver + stereo reverb running on Teensy4 with only 25% cpu load.

I did not include a programmer in the Basestar design because of an hack that allows to use a cheap FX2LP board directly in the SpinAsm as a programmer. I did most of the coding directly in the  SpinAsm, so it was more convenient for me. Also the goal was to make a dev board, the number of patches stored onboard wasn't ontop of the list. Rather something to develop programs on and then move them to the final hardware. Giving that i'm not sure the Basestar dev board would deliver what you are after.



ElectricDruid

What's "E squared"?

I haven't got any code for it, so I can't help directly, but it can't be that hard to connect the FV-1's I2C to a uP with enough onboard program memory to store a whole ton of FV-1 programs. They're only 128bytes, after all, so 128 programs is 16K - there are plenty of uPs with 16K of programmable storage. Then the uP deals with the programs, flips one of the "S" program select lines on the FV-1, sends it the I2C data. On the face of it, it's pretty simple. Although having some know-working code is always simpler still!



free electron


Digital Larry

Quote from: free electron on December 29, 2020, 11:00:35 AM
That would be me :)
Sorry i haven't had time to reply to your email yet.
I still have a few Basestrar PCBs left , but the other module you mentioned (cy8ckit-043) will not work with it. Different MCU, different pinout, they are not really compatible.
I thought you looked familiar!
Ah.  Too bad.
I see that some places sell the 049, a bit more expensive and only from the UK that I can see:
https://www.ebay.com/sch/i.html?_from=R40&_trksid=p2334524.m570.l1313&_nkw=cy8ckit-049&_sacat=0&LH_TitleDesc=0&_osacat=0&_odkw=cy8ckit-04
But... it would save a lot of time!

Quote from: free electron on December 29, 2020, 11:00:35 AM
I thought about redesigning the board to use the MCU directly instead of the module, but i don't use FV-1 too often these days. Not after getting a stereo IR convolver + stereo reverb running on Teensy4 with only 25% cpu load.
Yeah, I'm playing with an Elk Pi board and working my way towards writing VSTs using C++ and/or Faust that will run on it.  There's also the Mod Dwarf coming out that looks good.  I think it uses LV2 format plugins.  If it weren't for SpinCAD making algorithm development so easy I probably wouldn't care as much.  I did some experiments earlier this year on the ESP-32 which looks way more powerful than the FV-1 on paper, but it couldn't do some things that I know would have been easy on the FV-1.

Quote from: ElectricDruid on December 29, 2020, 01:25:29 PM
What's "E squared"?

I haven't got any code for it, so I can't help directly, but it can't be that hard to connect the FV-1's I2C to a uP with enough onboard program memory to store a whole ton of FV-1 programs. They're only 128bytes, after all, so 128 programs is 16K - there are plenty of uPs with 16K of programmable storage. Then the uP deals with the programs, flips one of the "S" program select lines on the FV-1, sends it the I2C data. On the face of it, it's pretty simple. Although having some know-working code is always simpler still!

E-squared is EEPROM.  Leastwise that's what we used to call it back in those pre-internet days.

My concern was more about getting some reference  code to perform that function so I wouldn't have to develop it from low level.  The Cypress chips with the configurable peripherals look pretty cool in fact.  I'd read some threads by people who had apparently done it, but I wasn't sure there was a standard approach known to work with the FV-1.  I have been out of the hardware game for a long time, so the feature on the Cypress chip actually took me by surprise a bit.  So that one has a I2C peripheral block that works as an I2C slave.

Looking at the Teensy 4, (which is way smaller than the Cypress SoC sticks) it incorporates "FlexIO" similar to Cypress which of course supports I2C, so of course it supports I2C slave mode... NOT.  https://community.nxp.com/t5/S32K/How-to-emulating-I2C-bus-slave-mode-by-using-FlexIO/m-p/931569

I could probably compromise... use just 32 programs, 4 24LC32s, or 64... I probably wouldn't really use 128.  I just want a workspace to collect good ones so being able to tag and move them would also be a good feature.
Digital Larry
Want to quickly design your own effects patches for the Spin FV-1 DSP chip?
https://github.com/HolyCityAudio/SpinCAD-Designer

potul

I don't have any working piece of code, but I investigated a little in the past as I am interested in something like this. I was planning to use an Atmega328 and program it using Arduino IDE.

Summary of my findings:

-Atmega can work as an I2C slave using Wire, but you need to ensure it does not go into clock stretching. Otherwise the FV1 is not able to get it.
-From some application note I understood AVRs at 8Mhz cannot handle I2C rates higher than 100Khz without using clock streching. FV1 uses 250Khz I2C when clocked at 32Khz.
-Someone at Spinsemi forum was able to succeed by slowing down the FV1 clock during the program load. Basically the Atmega is also providing clock to FV1, so it is in control of it.
-I was planning to test an Atmega running at 20Mhz to see if it's able to make it, but never put it into run.

There is the additional problem of how to store the programs in Flash memory in an easy  way to allow loading of new programs....
I like the idea someone posted to use an SDCard... this could allow to copy hex or bin files into the SDCard from a PC easily, and read them from the uC.



ElectricDruid

Quote from: free electron on December 29, 2020, 01:33:49 PM
It's 512 bytes for one program. Instructions are 32bits long.

Aww, 'course they are! Silly me!  :icon_redface:

64K's still not out of bounds though, by any stretch.

phstomp

Hi,

I managed to get EEPROM emulation to work on atmega328. It took
about 7 attempts with oscilloscope traces to finally get it. TWI did not work
because it is too slow. The interrupt from TWI peripheral takes too long
to arrive to be able to respond in time for the FV-1.

The approach that I took was to initiate patch change from atmega328 by
toggling the FV-1 pin S0 (pin 16) and then wait in a busy loop counting I2C
clock cycles and sending the data at correct moments. The code is attached
below (GPL v. 3.0).

I have been working on an Arduino based FV-1 multi effect pedal for guitar.
I recently got the second version of PCB from China and I'm in process of testing it.
I went with SMD this time because the board got very crowded for THT parts.
Here are a couple of pictures from the first PCB prototype:








Features:
- atmega328 with Arduino UNO bootloader, programming directly from Arduino IDE
- 80 FV-1 algorithms (29 reverbs, 21 delays, 30 modulation effects currently)
- 8 saved presets (algorithm + 3 parameters, Volume and Mix)
- Volume and mix are done by digital potentiometers, position saved on preset.
- OLED screen.

Hardware:
- Analog dry Audio path
- Current consumption approx. 80 mA
- Atmega328p processor at 8MHz.
- DS1881 digital potentiometer.
- SSD1331 OLED screen.
- True bypass + patch select footswitch.
- No EEPROM chip.

Software:
- Runs on atmega328p, programmed with Arduino IDE (FTDI programming header)
- FV-1 algorithms as header files, compressed with lightweight compression
method (https://excamera.com/sphinx/article-compression.html), thus making
it possible to fit 80 algorithms to the 32k memory of atmega328p (8.5k code,
23.5k algorithms currently).
- No EEPROM chip, instead the atmega328p is used to emulate an EEPROM
and send the algorithm to FV-1.
- Parameter values from atmega328 to FV-1 communicated using filtered PWM.
- Custom UI with modified SSD1331 OLED screen library
(http://www.technoblogy.com/show?2EA7) with each preset having a different
colour scheme.





/*  Copyright 2020 Perttu Haimi
 
    This file is part of FVduino.

    FVduino is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    FVduino is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with FVduino.  If not, see <https://www.gnu.org/licenses/>.
*
*
*/


void send_algo()
{
  // Copy FV-1 algorithm from PROGMEM to ram buffer.
  // Progmem is too slow in the send loop.
  // Since we will anyway have to copy from PROGMEM,
  // it makes sense to compress the algorithms and get
  // space savings (almost 2x).
 
  uint8_t algo = patch_data[current_patch].algorithm;
  decompress(algo_buffer, (prog_uchar *)pgm_read_word(&(algodata[algo].prog_addr)));

  // Set up everything to be ready
  const uint8_t sda_mask = (1 << PIND5);
  const uint8_t clk_mask = (1 << PIND6);
  uint8_t prev_clk = clk_mask;

  DDRD &= ~(clk_mask);   // clk pin as input
  DDRD &= ~(sda_mask);   // sda pin as input
  PORTD &= ~(sda_mask);  // SDA pin is pulled low or floated up
                         // -> we need to set pin low only once.
                         //    Toggling is done by setting pin to
                         //    input (let float high) or output (pull low).
                         //    FV-1 internal pullups are ok (tested).

  uint16_t pos = 0;
  uint8_t curr_byte = algo_buffer[pos]; 
  uint8_t bit_mask = 0b10000000;
  uint8_t clk_count = 0;

  // Overclock (3.3V 16 MHz)
  clock_prescale_set(clock_div_1);

  // Undivided attention for FV-1 requests
  noInterrupts();

  // Notify FV-1 of patch change by toggling the notify pin
  PIND = _BV(4);   // Toggle pin 4
 
  while(clk_count < 37)              // Handle the header
  {
    uint8_t clk = PIND & clk_mask;

    if(!clk && prev_clk) {           // scl went down
     
      switch(clk_count)
      {
        case 8:
        case 17:
        case 26:
        case 36:
          DDRD  |= sda_mask;         // sda pin as output send ACK - pull sda pin low
          break;
        default:
          DDRD &= ~(sda_mask);       // sda pin as input
          break;   
      }     
      clk_count++;
    }
    prev_clk = clk;
  }

  clk_count = 0;
  while(pos < 512)                   // Send the data
  {
    uint8_t clk = PIND & clk_mask;
   
    if(!clk && prev_clk) {           // scl went down

      if(clk_count != 8) {           // Sending byte
       
        if (curr_byte & bit_mask) {
          DDRD &= ~(sda_mask);       // Send 1 = Let High (sda pin as input)
        } else {
          DDRD  |= sda_mask;         // Send 0 = Pull Low (sda pin as output)
        }       
        bit_mask >>= 1;
        clk_count++;
       
      } else {                       // Let reciever reply
       
        DDRD &= ~(sda_mask);         // Release (sda pin as input)
        clk_count = 0;
        bit_mask = 0b10000000;
        pos++;
        curr_byte = algo_buffer[pos];     
      }
    }
    prev_clk = clk;
  }

  interrupts();

  // Restore 8 MHz
  clock_prescale_set(clock_div_2);
}







potul

Great, this is very close to what we need...

Some questions from my side:

-How are you clocking the atmega? I see that in your piece of code you are "overclocking" it to 16Mhz. Are you using a crystal?
-Are you storing the algorithms as arrays in progmem? So, do you need to reprogram the atmega to add new patches?
-If I understand it correctly, you are bit-banging the I2C slave response, right? Do you know what is the FV1 sending as a header during the first 36 clock cycles?


phstomp

Thanks. I'm clocking atmega 8 MHz at 3.3 V, using 16 MHz crystal
and clock divide 2. This is just for power savings, and I have 3.3V
on board for the OLED screen and FV-1 anyway.

The algoritm sending will not work at 8MHz though,
thats why I'm going to 16 MHz temporarily (overclocking at 3.3V).
If you use 16 MHz at 5V, then you can leave out the clock changes.

Yes, the algorithms are in progmem. They are in header
files and everything needs to be recompiled if adding new patches.

Yes, it is a tight bit banging loop. The FV-1 sends the slave device
ID and the address that it wants to read from in the header.
FV-1 is direcly wired to the atmega pins PD5 and PD6, so no need to
check the ID. Also, the read address can be ignored, because FV-1 will
anyway be sent the algorithm that is currently selected in user interface.


potul

Thanks for the replies... I'm thinking on getting something similar but reading hex files directly from an SD card instead of progmem. This would allow me to copy new hex files into the SDcard from my PC easily. I want to have a simple workflow to debug/test new FV1 programs.




phstomp

I think, as long as you read the whole FV-1 program to a 512 byte
RAM buffer from the SD card before sending it to FV-1, it should work.
In the loop, there is no time to read SD or to do any other calculation.

The wiring that the code assumes is:

FV-1 SCK (pin 14) -> atmega PD6 (Arduino pin 6)
FV-1 SDA (pin 15) -> atmega PD5 (Arduino pin 5)
FV-1 S0 (pin 16) -> atmega PD 4 (Arduino pin 4) (I'm using 100k pull down resistor)
FV-1 S1 (pin 17) -> Ground
FV-1 S2 (pin 18) -> Ground

potul

Quote from: phstomp on December 30, 2020, 10:28:59 AM
I think, as long as you read the whole FV-1 program to a 512 byte
RAM buffer from the SD card before sending it to FV-1, it should work.
In the loop, there is no time to read SD or to do any other calculation.
This was my thought as well. Loading the full program in to RAM before triggering the change in FV1.

Digital Larry

The plot thickens.  This is all very interesting.

@phstomp let me know if you'd want to sell one of those to me.  While I'm tempted to try to design everything as some long term project, I think I need to er.... focus on the most important things!  Which is another way of saying I might never finish such a project, and what I really want to do is develop and use the algorithms.

While we're just talking about what we need and why.

Features:
- atmega328 with Arduino UNO bootloader, programming directly from Arduino IDE
- 80 FV-1 algorithms (29 reverbs, 21 delays, 30 modulation effects currently)
Wow, great!  I could live with 80, though I'd want to be able to put my own in.

- 8 saved presets (algorithm + 3 parameters, Volume and Mix)
Only 8?  That would drive me nuts.

- Volume and mix are done by digital potentiometers, position saved on preset.
Cool! Can you do full wet?  Can you do a 6 dB analog boost (e.g. when you do a trem patch you sometimes want to boost it a bit to retain overall level)?

- OLED screen.
Cool!

I'd consider:
a) USB interface.  I don't even want to mess with shlepping SD cards in and out.
b) aux EEprom for storage instead of SD card (to be combined with USB interface to allow fast, in place loading of patches from PC).  How big do they make them?

DL

Digital Larry
Want to quickly design your own effects patches for the Spin FV-1 DSP chip?
https://github.com/HolyCityAudio/SpinCAD-Designer

phstomp

Quote from: potul on December 30, 2020, 11:28:31 AM
This was my thought as well. Loading the full program in to RAM before triggering the change in FV1.
[/quote]

Ok, let me know how it goes.