Shop OBEX P1 Docs P2 Docs Learn Events
Multi-channel waveform generator using propeller ? — Parallax Forums

Multi-channel waveform generator using propeller ?

Wolfgang EbersbachWolfgang Ebersbach Posts: 10
edited 2010-03-06 19:04 in Propeller 1
Dear all,

I have to design an multi-channel waveform generator, more specific an emulator for human body biopotential signals.
The challenge here is, that I need several (target: 10) channels that output an arbitrary signal completely independent, this includes at the same time. Each of the channels may be triggered at any time and must then output one arbitrary signal.
The arbitrary signals do exist as real sampled data 12 bits wide with 10ks/sec. Each sample is about 6k-values big.

Now there are three different possible solutions:
1) Use one uC per channel (and one DAC) to be independent.
2) Use one really fast uC and 10 DACs and handle the 10 channels one after each other, creating the illusion of independence by an sufficient fast uC
3) Use two propellers, each of which uses 5 cogs to produce 5 output signals (via PWM and lowpass filter instead an DAC). Or even one propeller, as each cog has 2 timers...

Solutions 1) and 2) are too expensive. Furthermore, with solution 1) you will have trouble realizing relations between channels and updating the sample data via e.g. serial port...

OK, the case seems clear: Propeller makes it easy because of the many cogs... BUUUUT ! Each sample is some kBytes big, too much for a cog's memory.
And here comes the big questionmark:

Does anyone have a good idea how I can read an external memory in such a way that each cog can read at ANY time from this memory? Note ANY time includes the possibility that several cogs want to read different memory locations at the same time...
I am also willing to use more than one physical memory chip, if that helps.

As I understand from this picture:
http://www.parallax.com/Portals/0/Images/Prod/P/PropellerBlock-L.jpg
each cog can at any time (even several cogs at the same time) access:
the 32 IO pins
32 bits data bus
16 bits address bus
32 bits system counter
. but only the 32 IO Pins can be physicaly accessed to connect memory.

As each cog has 512x32 its RAM, if I think in bytes, i have 2kBytes per cog. It would be sufficient to have 8 Bits sample resolution, but I do still need more than 2 kBytes per cog.

So, up to now I had no really good idea how to solve the problem. Maybe use the 512x32 bits cog-ram as a buffer that is filled from an external Flash memory in regular intervals ?

like this:
each sample is around 6k-values, let them be 8 Bits each. And I have 10 channels like that.

Then, I could use 5 cogs to do:

do
if (trigger_input = 1)
read 8 BIts from COG RAM // (or better, shift off the RAM to have some sort of FIFO)
set PWM to this value
else
set PWM to 0 // (no output signal )
wait (to match samplerate of 10ks/sec) 1/samplerate - the 2 instructions above
repeat

each, and one cog to do:

for N = 0 to 5 to
read 32 bits from Flash (4X8 bits)
write them to cogRam No. N
next

and one cog to handle serial comm with PC or smilar to update external Flash with new / other sample data.

This way I maybe could create an 5 channel module. By stacking more than one of those, I maybe can get my 10 channels.

What do you think ? Any ideas ?


With best regards,
an "until now Atmel AVR user"...

Comments

  • MagIO2MagIO2 Posts: 2,243
    edited 2010-03-04 21:04
    The counters don't help very much. There are better PWM drivers available which support 8 or even 32 PWM channels per COG.
    As your sample rate is 10k samples per second your PWM has to be fast, so I'd try the PWMx8 from Phil. So, you'd need 2 COGs for PWM.
    The data transfer rate is 10k samples * 12 bit = 120kbit/sec. Divided by 8 (let's be wasteful and use 2 bytes to store one 12 bit value) 160kbit/sec / 8 bit = 20kByte per second.

    That's nothing for an SD card driver! Even if you have to load 20kB x 10 = 200kB per second.

    So, use one more COG for the SD card and one which manages that the right data is available at the right time.

    Makes 4 COGs all in all. You can start thinking about some goodies for your project ;o)
  • rokickirokicki Posts: 1,000
    edited 2010-03-04 21:34
    One thing about the SD card, though: what is the allowed latency between trigger and samples? Reading an SD card *can* introduce a nontrivial latency (although on reads it is probably exceedingly rare). The specification *allows* (I think) up to 1/2 or 1sec between a readblock is issued
    and the data is returned.

    A large EEPROM may well be a better choice and can almost certainly meet your I/O rate without troubles, even interleaving all the streams.

    (This from the SD guy.)
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2010-03-04 21:34
    Wolfgang,
    It's good that you see that you can use the cog's counters as they are very good for generating analog signals using DUTY-CYCLE modulation with an RC filter. The reason that PWM is mentioned is simply because many loads and drivers cannot handle the 80Mhz DCM frequency directly. But of course you are actually interested in the analog waveform so the DCM mode is the perfect solution as there are two per cog and each cog can easily read in samples and feed the two channels.

    Now as to storing the samples there are certainly a number of ways of doing this but the question comes to mind, can the samples be compressed so that they can all be stored in hub RAM? If they can then the rest is trivial.

    Alternatively the SD card option was mentioned or in fact even a small SPI DataFlash chip as they are fast, cheap and can hold several megabytes. You would need a cog devoted to reading the samples for all the channels and placing them in hub memory. That would now take up one cog for samples and 5 cogs for 10 DAC channels leaving you two cogs. If one cog is used for serial communications then you still have the other cog for the overall main control program.

    I would try keep it as simple and efficient as possible but the next step might be two Propeller chips if that was necessary but I can see no reason why the above solution won't work.

    BTW, Welcome to the Propeller forum Wolfgang!

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    *Peter*

    Post Edited (Peter Jakacki) : 3/4/2010 10:06:18 PM GMT
  • AribaAriba Posts: 2,690
    edited 2010-03-05 02:10
    Here are my toughts:

    Hold the samples in an external Memory, like an SD card, or a serial Flash or RAM (perhaps also the EEPROM is fast enough).

    Use a buffer of 1 kByte in HubRam (MainMemory) for every channel and a cog to fill the buffers when needed.

    Use 5 cogs which do 2 channels each. They read it's two 1k Buffer from HuBRam and signal to the Filler-cog when the next
    1 kB should be filled in.
    A counter in the DUTY mode is a good DAC for such an application.

    The 5 channel-cogs must be programmed in Assembly, for the filler-cog Spin my be fast enough. The external memory access
    needs a fast driver in Assembly which occupies another cog, so 7 cogs are in use.

    Buffer handling:
    Fill the whole 1 k buffer while a channel is waiting for a trigger. After the Trigger when the half buffer is read out, fill this first half
    with the next 512 bytes from external menory. When the whole buffer is read, wrap around and read from the begin of the buffer. The filler cog then must fill the second half with the next 512 bytes ... an so on until the whole sample is done.

    Andy
  • Wolfgang EbersbachWolfgang Ebersbach Posts: 10
    edited 2010-03-06 07:52
    Hi to all,

    @MagIO12: I don' want the PWM signal itself; I need analog but I wanted to save the external DAC's and use PWM and a lowpass instead. You are of course right, the PWM's have to run at at least 50 kHz or so to produce an reasonable analog signal with 5kHz. On the propeller's block diagram, the clock can be up to 80 MHz. So IF the PWM can run at clock speed, even at 10 Bits resolution the PWM should be able to do about 80 khz.

    @all : External Memory: Of course I need external Memory. And of course the data rate of the memory itself is not an issue, my issue was if, and how, I can "distribute" the different sample data from the one memory to the 5 cogs fast enough and without creating a phase error in the output signals. You see, the 10 channels have to be really independent. It is possible that zwo (or more) of them are triggered at the very same moment. In this case, the corresponding outputs also should start in the very same moment.
    SD Card seems a little overkill for a few kByte of data. And it should be simple, cheap and bullet proof. Thus I prefer a little serial (spi or i2c) flash.
    2 PWM per cog: I know, but in this case these two channels would not be independent as the were "served" from one cog. What I would get is 2X5 channels, not 10 single ones.
    Anyhow, I can just use two propellers, that's no problem. And still cheaper than 10 DAC's.

    @Peter Jakacki : Hmm, I am from Germany, but in my understanding "PWM" is "PulseWithModulation", thus take a fixed frequency square and modulate (=change) the pulse width = the duty cycle, because frequency is fixed.
    This seems to be the same as "DCM" which I understand as "DutyCycleMode", aka PWM.
    Or did I miss something ?
    The samples may be compressable, but I have no idea how to uncompress in the cog, as I am an hardware engineer smile.gif. Besides that, this seems a little code-overkill for this purpose, which in principle reduces to: push a sequence of bytes to 5 different PWM counter registers in the right order and time.

    @Ariba: Yes, these where the questions: Is it doable this way, will it be fast enough ?
    So, I need to program the cogs in Assembly ? Hmm, last time I did this was around 1988. Sounds like "back to the good old times". Anyhow, I will try.

    So, thanks to all, I will order some propellers to start with. And I will presumably plague this forum with more detailed questions, most likely regarding spin and assembly, as the project has to run at the beginning of april...

    Oh yes, the missing info: Latency from trigger moment to start of sample output is allowed to be up to 20 microseconds (which is the minimal latency seen in real world), but difference between channels should be as low as possible. Ideally zero.

    With best regards,
    Wolfgang
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2010-03-06 08:48
    Wolfgang,

    The duty mode generates 12.5ns pulses but you vary the frequency up to 80MHz. So 1Hz would generate a single 12.5ns pulse per second, 40MHz would be 40 million 12.5ns pulses per second which in this mode is the only time you will see a square wave and is 50% duty cycle. PWM has a fixed frequency and variable on/off times. Perhaps I should have said Duty Modulated rather than the term DCM which seems to be used interchangeably with term PWM. So ok, we say DM which is quite suitable for generating analog waveforms with a simple 1st order RC filter. If your sample rates across the 10 channels remains the same than there is no problem with sharing a cog with two channels. However 2 Propeller chips will guarantee completely independent operation of each channel.

    Using an SPI Flash chip will ensure the latency is very low for each channel and they can transfer at a much higher rate than an I2C EEPROM. You might need this speed if you have one cog slaving away filling the buffers for all 10 channels. I would use double buffers as we do in playing back audio in that while one buffer is being read from the other buffer is being filled. So this is not much different from when we play audio samples from SD or SPI Flash which I have quite some experience with.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    *Peter*
  • Wolfgang EbersbachWolfgang Ebersbach Posts: 10
    edited 2010-03-06 14:14
    Hi Peter,

    yes it is like playing audio samples, but on 10 channels at once and triggered by an trigger input.
    I will build the hardware (propeller, SPI Flash and RC lowpass's) on a prototypeboard as soon as I get the parts and ask more questions when it comes to programming smile.gif
  • JRetSapDoogJRetSapDoog Posts: 954
    edited 2010-03-06 19:04
    Your project reminded me just a bit of Clock Loop's V2.0 BlackBox·quad-Propeller·audio sequencer of the links below.· I don't think it's directly related (it's generates frequencies in the audio range, obviously), but·perhaps something·about it·could serve as a code or prototyping example, and it was on CrunchGear the other day.

    Pls. just ignore this post if it's way off base (i.e., unrelated).· I haven't looked into either project at this point.


Sign In or Register to comment.