Shop OBEX P1 Docs P2 Docs Learn Events
Interrupt Driven Pitch Generator (Pitch VP) — Parallax Forums

Interrupt Driven Pitch Generator (Pitch VP)

YendorYendor Posts: 288
edited 2008-08-10 21:43 in General Discussion
·
Something that can be considered cool, obnoxious, and useful all in one!
·
Here is my ‘proof of concept’, yet simple·program for generating monophonic musical tones using a Piezo speaker through an interrupt.·
·
I’m sure there are some variants out there, but hopefully someone may find this helpful or put a smile on their face.
·
Pitch accuracy will be based on the interrupt time and the clock cycles.· I’ve enclosed a spreadsheet that will generate the SX/B·pitch table based on the desired·SX Clock and Interrupt rate, as well as·some idea on the accuracy of the pitches, so that some analysis can be made.·· Also, note that Piezo speakers also have a limited bandwidth, so not all pitches will be audible
·
The pitches are based on MIDI note numbers (0-127), as well as the MIDI·Baud Rate.· Feel free to use the Excel spreadsheet to come up with the pitch table for your clock & interrupt.·20MHz and 50MHz would probably be best.

Hook up the Piezo as described in FREQOUT or SOUND examples in the SX/B help file.

The Code:
  • A data table is required (256 bytes).· Can always scale back the table, as necessary.·
  • Purposely simplistic. ·Improvements that can be made using arrays, assembly, bit flags, and using a lookup table for the tones/durations,
  • Had the issue using the “Load” directive, so I put all the constants in the main file.
·The Spreadsheet (PitchTables_v1.xls)
  • Helps to visualize pitch variances with different levels of interrupts and clock speeds
  • Generate the pitch table to put in your SX/B Code
  • Can be used to give some idea of how accurate the pitches would be.· Most people start to hear pitch variations at +/- 12 cents, so you can use the spreadsheet as a guideline for your end goals.· Accuracy is highlighted in red using conditional formatting, if beyond +/- 12 cents.
  • Spreadsheet Inputs (Green)
········ SX Clock Frequency
········ RTCC Prescaler
········ And either the RATE or CYCLES of your interrupt, depending on your preference
o······ Right now the CYCLES (Cell D4) is copied over from Cell E3, but that’s just for calculation verification.
  • Spreadsheet Calculations (Yellow)
········ The interrupt values is calculated, and then put in either Cell G3 or G4 into Cell H4 (interrupt time).
········ Then if you want, you can put your Bit Period Counter in to calculate the baud rate.
  • The rest of the columns give the calculations to get to the counter for the frequency
  • The ‘Rounded’ Column is the value that you use in your pitch table.
  • Copy Column M and paste it into your program for your table, based on your values.
  • The grayed rows (row 6-7) are not supported.· I just put them in to get an ‘A’ reference, for the Pitch Frequency.
Once the pitches are defined, I simply incorporated Jon Williams interrupt driven Delay_MS subroutine for the duration.
·
Hope this helps, and have fun!
·
Rodney
·

Post Edited (Yendor) : 8/6/2008 4:12:01 AM GMT

Comments

  • JonnyMacJonnyMac Posts: 9,215
    edited 2008-08-06 04:13
    That's pretty neat. I wonder, especially since the ISR code is small, if you could make it polyphonic by using, say, three different tone generators and summing the outputs through resistors? -- and as your ISR runs at 8 uS you could easily make it MIDI compatible (I'm betting you planned for that).
  • YendorYendor Posts: 288
    edited 2008-08-06 04:45
    Thanks Jon - always glad to hear your feedback!

    Yes, was thinking about 2-3 voice polyphony, too, and was going to attempt that later this week - just seems a matter of tackling appropriate resistor values.
    ·MIDI compatibly is exactly what I had in mind, as I did this as a development 'helper' to send out note events to this subroutine instead of a MidiOut/TxByte routine (so I don't have to hook up my synth's each time I'm working on it).

    Post Edited (Yendor) : 8/6/2008 4:52:04 AM GMT
  • JonnyMacJonnyMac Posts: 9,215
    edited 2008-08-06 16:46
    This project has such appeal to me that I went ahead and tried it on my PDB -- polyphony works! Yahoo!

    My program is a clone of yours with the addition of two more tone generators and VP UART and handler code. It's running on a PDB using a simple resistor summing circuit for the tone output pins. The PDB amplifier has a filter circuit as shown for SOUND and FREQOUT in the SX/B help file; this helps smooth off the "rough edges" of the square wave output. The addition of an EEPROM would allow for a lot of song data, just in time for holiday decoration projects.

    [noparse][[/noparse]Edit] Updated the PLAY_NOTE subroutine -- it's still compatible with Rodney's PlayPitch subroutine but now allows the selection of no timing (tone generator started but not stopped) and allows the user to select which tone generator (of 3) to use. By updating PLAY_NOTE the START_TGEN subroutine could be eliminated to save a bit of code space.

    [noparse][[/noparse]Edit] Fixed "gotcha" in UART buffer check (thanks, Zoot)

    Post Edited (JonnyMac) : 8/8/2008 4:32:04 AM GMT
  • BeanBean Posts: 8,129
    edited 2008-08-06 23:13
    Cool Jon.
    I'd love to hear a polyphonic version of stairway to heaven.

    Bean.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    "A government big enough to give you everything you want, is big enough to take away everything you·have."·· Thomas Jefferson

    "It is our choices, Harry, that show what we truly are, far more than our abilities."·Dumbledore from Harry Potter

    www.iElectronicDesigns.com

    ·
  • JonnyMacJonnyMac Posts: 9,215
    edited 2008-08-07 20:00
    Here's another take on Rodney's original program; this moves the note timing into the interrupt as well so you can simply start a note and move on to something else. Ultimately, I'd like to add a note buffer so that you could queue up a few notes to play while your foreground is doing something else.

    Note: I recalculated the pitch values based on a 4 uS interrupt cycle for better accuracy, and used a slightly different strategy than Rodney. My pitch calculations are based on a standard formula for converting MIDI note values to frequency. My Excel file is attached, too.
  • ZootZoot Posts: 2,227
    edited 2008-08-08 01:34
    Great thread.

    JonnyMac -- one thing I noticed in your Polyphonic program (and perhaps others where you've included this VP?) is this line for checking if the serial VP buffer is full:

        JB    rxBufCnt.4, RX_Done                   ' (2/4) skip if buffer is full
    
    



    Which seems to imply a 16 byte buffer; this program has an 8-byte buffer. Wouldn't this be correct?

        JB    rxBufCnt.3, RX_Done
    
    



    ??

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST

    1uffakind.com/robots/povBitMapBuilder.php
    1uffakind.com/robots/resistorLadder.php
  • JonnyMacJonnyMac Posts: 9,215
    edited 2008-08-08 04:25
    You're absolutely right -- copy and paste error on my part; thanks for the catch. I'll fix and re-post.
  • YendorYendor Posts: 288
    edited 2008-08-08 22:12
    Oh sure Jon, steal what little thunder I can create, but I'm glad you're exited about it!· ;o)

    Looks like you've been busy, too!

    That's great you got polyphony working (I'm jealous!)!·

    I'm going to resist peaking to see what I can come up with and compare.· I agree that some buffer (maybe two) are needed for the notes.· One for Duration and the other for what note is waiting (see Tempo/BPM Post).

    I'm using the Piezo Schematic from the SX/B file, so it's doesn't sound too bad.···

    Did you use an R2R Ladder to combine the bits?· Was the sound consistant?

    Not sure if you've thought about this, but here's a suggestion to save some song space.

    Think of a song as a program·of repeatitive·information.· So simply break the song down into 'subroutines'!

    For example:
    A Song is comprised of several Elements:
    • Intro
    • Verse
    • Pre-Chorus
    • Chorus
    • Bridge
    • Solo/Break
    • Outro

    And with each part you can have a sequence
    • Verse 1:
      • Sequence 1
      • Ending 1
      • Ending 2
    • Verse 2:
      • Sequence 1
      • Sequence 2
    • Chorus
    Each sequence is a Pattern:
    • Sequence 1
      • Pattern repeated·4 times
    Then it's simply another table: number of elements, address, number of repeats.

    MySong: 3,Verse1,1,Verse2,1,Chorus,2

    Verse1: 4,Sequence1,1,Ending1,1,Sequence1,1,Ending2

    Verse2: 2,Sequence1,4,Sequence2,1

    Chorus: 2, Sequence1,1,Sequnce2,1

    Sequence1: 1,Pattern1,10

    Sequence2: 1,Pattern2,4

    Ending1: 1,Pattern3,1

    Ending2: 1,Pattern4,1

    etc..

    Then just generate song files, and load them up with an 'Load' function.· Something like what Bean did on his MMVG driver. But, shhh, let's not tell the RIAA about this...

    And Ooops!· You're right! Middle C (Note 60), is C4, not C5...So I'm an octave off.· I guess that's better than being off by one jack!· Thanks for catching this!

    Good catch Zoot!· I knew this was an issue, but haven't dug into the details, so I just used the normal way for now.

    Finally thanks for the supporting comments!·

    Rodney
  • JonnyMacJonnyMac Posts: 9,215
    edited 2008-08-08 22:51
    Since the three outputs are driven I summed them through 1K resistors and connected the combined output to the amp circuit on on the PDB -- sounds surprisingly good and I'm now thinking of doing a music Christmas decoration project for my November column. Thanks, Rodney!
  • ZootZoot Posts: 2,227
    edited 2008-08-08 23:08
    Rodney -- the introductory comments in Jon's SX/B program has the simple summing circuit (1k resistors to each out pin, other end of all 3 resistors tied together into amp/piezo.

    In looking at your song schema, may I suggest that you check out some of the excellent materials relating to storage and playback of music for the Stamp. There are a number of good examples in the WAM book by Parallax (chapter 8, http://parallax.com/Portals/0/Downloads/docs/books/edu/Wamv2_2.pdf). In particular there is a good article about parsing text ringtones. It would be easy enough to store music scores on an external EEPROM and play them back.

    See also my (Stamp-based) code for reading scores from external memory and delivering on the fly for some I2C EEPROMS samples. http://forums.parallax.com/showthread.php?p=619826.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST

    1uffakind.com/robots/povBitMapBuilder.php
    1uffakind.com/robots/resistorLadder.php


    Post Edited (Zoot) : 8/8/2008 11:14:44 PM GMT
  • YendorYendor Posts: 288
    edited 2008-08-10 14:10
    Cool Jon,

    In your column - would love to see if you can work in an EEPROM for the music, too.

    I'm thinking about hacking an FC-4, myself! [noparse]:o[/noparse])

    Thanks for the links Zoot! I'll check it out...·

    As my end goal is MIDI, I'm just trying to code a·"Note-Duration" scheme on different 'tracks', if you will, and not worry about Note-Off events.

    Thanks!

    Rodney

    Post Edited (Yendor) : 8/10/2008 2:15:54 PM GMT
  • JonnyMacJonnyMac Posts: 9,215
    edited 2008-08-10 15:09
    I have a piece of code working with three tone generators that have built-in timing. What I'm trying to do now, though, is reduce the timing to a single byte (using your tix clock to drive it) so that I can simplify buffering the note data for each tone generator.
  • YendorYendor Posts: 288
    edited 2008-08-10 20:29
    Jon,

    Did you try increasing the PPQN in the spreadsheet, that I mentioned in the Tempo/BPM Thread?

    Also, I still have some experimenting to do, but it seems that the data table for the clock can be eliminated to an algorithm if you use only even tempos.

    Rodney
  • JonnyMacJonnyMac Posts: 9,215
    edited 2008-08-10 21:43
    I haven't had a chance to look at that spreadsheet yet; have some other projects that are pressing at the moment.
Sign In or Register to comment.