I'm working on a modified version of the code, and hope to test it this weekend. I'll be driving the ISD1700 with a PIC16F684 and will post the final (working) code here. So far I am just checking all the commands against the datasheets.
I do have a couple observations.
The SetPlay command should only send SEVEN bytes. The END address is contained within TWO bytes (12 bits). That THIRD address byte (last byte sent) should be set to "0x00" as it is not supported in existing hardware. Same case for SetRecord.
I finally figured out your use of "While CmdError." Had me stumped for a while, then it clicked. That's pretty clever. Though it looks like in some cases it will be better to check the "RDY" status (depending on which command you are sending).
Also I did not realize that you can shift data into a byte using "status, c" carry bit in assembly. That is a very cool trick, indeed! Pretty much all of the other SPI examples I've found for PicBasic just used the Shiftout command which does not allow reading the Status bits.
For anyone interested, the original ISD1700 development kit made by Windbond (which cost me $270 from Digikey last year) does NOT support batch recording of sounds. You have to set the Start and End address manually and record one sound at a time. Very tedious and not usable other than basic function tests. However... there is a NEW ISD1700 development kit made by Nuvoton and it DOES support batch programming of wav files. So it can function as a decent production programmer. Unfortunately it's going to cost me another $270 - ouch. I called tech support at Nuvoton and they confirmed the new software is NOT compatible with the original Winbond development hardware.
You should also be aware that the Quadravox QV400D programmer never added support for the ISD1700 series. I still use it for programming ISD2560 chips, but they are starting to get expensive and much harder to find.
so someone would have to make himself friend with Winbond and suggest them an universal Gang device programmer
Not sure this worth it, look at current storage device pricing and add a higher level Microcontroller to it... NO way you're going to be over the Price of any single Winbond IC... not to mention you can update any part of your firmware and sound using a simple bootloading process.
Roman Black sounds almost the same as most Winbond solution and it's free, MP3 codec ICs are cheap, DsPIC are also cheaper... food for thought.
Steve
It's not a bug, it's a random feature.
There's no problem, only learning opportunities.
Requires porting of basic code but take a look at PIC iPod wav player.Not sure this worth it, look at current storage device pricing and add a higher level Microcontroller to it... NO way you're going to be over the Price of any single Winbond IC... not to mention you can update any part of your firmware and sound using a simple bootloading process.
Mono CD quality (16bit 44k) for the price of an SD card and holder,
a PIC18F4520, a few resistors for an R2 ladder, an audio amp and a speaker.
Or stereo 8bit 44k if preferred.
Up to 2 Gig's or 512 wav files.
Norm
Jerson done a FANTASTIC job while not having any hardware to test with!!These ISD chips are difficult to work with at a glance anyways...
I done more changing to the code I'm using by adding the 3rd byte to the status register and "singling out" the 2nd bit to check the status of the PLAY mode. With this bit, I can control the amplifier, which sound to play and when and so on...
More than adequate for the application I have![]()
This works so far to play back 4 sounds repeatedly. The volume setting via apc2 works also. Next I plan to get rid of the PAUSE delays and monitor status to determine when each sound finished playing.
Code:'DEMO PLAYER FOR ISD1700 'Code Version: 01 'Words Used = 354 'Revision Date: 8 Feb 2009 'PicBasic Pro Compiler version 2.50b 'Processor=PIC16F684 (WDT=ON, MCLR=INPUT, OSC=INTOSC) 'Modified from code posted by Jerson and Brenon 'Memory Reference: 'ISD17XX First Address = 0x010 'ISD1730 Max Address = 0x0FF 'ISD1760 Max Address = 0x1EF 'ISD1790 Max Address = 0x2DF DEFINE OSC 8 '************************************************************* '************************************************************* '******************** DEFINE VARIABLES *********************** '************************************************************* '************************************************************* temp_bit VAR BIT temp VAR BYTE spi_cnt var byte ' counter for SPI transfer bSPI var byte ' the byte being transferred on SPI s_addr VAR WORD ' Start Address e_addr VAR WORD ' End Address ISD_Data var byte[7] ' This array contains data to/from ISD SR0a var ISD_Data[0] SR0b var ISD_Data[1] SR1 var ISD_Data[2] ' only valid after ReadStatus isCmdErr var SR0a.0 ' 1=previous command failed/ignored isFull var SR0a.1 ' 1=memory full isPU var SR0a.2 ' 1=ISD powered up isEOM VAR SR0a.3 ' 1=EOM detected (clear by CLR_INT command) isINT var SR0a.4 ' 1=current operation completed (clear by CLR_INT command) isReady var SR1.0 ' 1=Ready to receive SPI command (only valid after ReadStatus) ' Some SPI commands can still be sent when isReady=0 '************************************************************* '************************************************************* '******************** PIN ASSIGNMENTS ************************ '************************************************************* '************************************************************* Symbol sensor = PORTA.0 ' Symbol miso = PORTA.3 'ISD1760 SPI MISO Symbol led1 = PORTC.1 ' Symbol led2 = PORTC.2 ' Symbol ss = PORTC.3 'ISD1760 SLAVE SELECT Symbol sclk = PORTC.4 'ISD1760 SPI CLOCK Symbol mosi = PORTC.5 'ISD1760 SPI MOSI '************************************************************* '************************************************************* '******************** INITIALIZATION ************************* '************************************************************* '************************************************************* initialize: CLEAR OSCCON = %01111000 CMCON0 = 7 'turn off comparators ANSEL = 0 PR2 = 35 'PWM Period (40K=49, 56K=35) (35 to 55) CCPR1L = 15 'PWM Duty Cycle (1 to 15) T2CON = 4 'Timer2 = ON; Prescale = 1:1 CCP1CON = 0 'PWM module off OPTION_REG = %11111111 'Turn off PortA weak pull-ups TRISA = %111111 'set PortA directions WPUA = %000000 'enable weak pull-ups PortA IOCA = %000000 'disable PORTA.0 Int On Change TRISC = %000000 'set PortC directions PORTA = %000000 PORTC = %000000 ' HIGH ss 'start with Slave Select HIGH HIGH sclk 'start with SPI Clock HIGH LOW MOSI 'start with MOSI LOW INPUT sensor LOW led1 LOW led2 start: 'Initialize the ISD GoSub isd_pu PAUSE 50 '50 mS Power Up Delay (per datasheet) GoSub isd_wr_apc 'set volume and config bits PAUSE 10 GoSub isd_clr_int 'clear interrupt and EOM '************************************************************* '************************************************************* '********************* MAIN PROGRAM ************************** '************************************************************* '************************************************************* main_loop: '(MAIN PROGRAM LOOP) PAUSE 2000 s_addr = $010 e_addr = $02b GOSUB isd_set_play PAUSE 2500 GOSUB isd_stop PAUSE 2000 s_addr = $02c e_addr = $048 GOSUB isd_set_play PAUSE 2500 GOSUB isd_stop PAUSE 2000 s_addr = $049 e_addr = $07c GOSUB isd_set_play PAUSE 4800 GOSUB isd_stop PAUSE 2000 s_addr = $07d e_addr = $093 GOSUB isd_set_play PAUSE 2000 GOSUB isd_stop GoTo main_loop '************************************************************* '************************************************************* '********************** SUBROUTINES ************************** '************************************************************* '************************************************************* isd_pu: LOW ss bSPI=$01 'Power Up Command GoSub isd_spi ISD_Data[0] = bSPI 'SR0a bSPI=$00 GoSub isd_spi ISD_Data[1] = bSPI 'SR0b HIGH ss RETURN '-------------------------------------------------------------------------- isd_wait_ready: GOSUB isd_rd_status IF isReady = 0 THEN isd_wait_ready RETURN '-------------------------------------------------------------------------- isd_set_play: LOW ss bSPI = $80 'Set Play Command (7 bytes) GoSub isd_spi ISD_Data[0] = bSPI 'SR0a bSPI = $00 GoSub isd_spi ISD_Data[1] = bSPI 'SR0b bSPI = s_addr.LowByte ' Start Address low byte. GoSub isd_spi ISD_Data[2] = bSPI 'SR0a bSPI = s_addr.HighByte ' Start Address high byte GoSub isd_spi ISD_Data[3] = bSPI 'SR0b bSPI = e_addr.LowByte ' End Address low byte GoSub isd_spi ISD_Data[4] = bSPI 'SR0a bSPI = e_addr.HighByte ' End Address high byte GoSub isd_spi ISD_Data[5] = bSPI 'SR0b bSPI = $00 ' Reserved Address - set to "0" GoSub isd_spi ISD_Data[6] = bSPI 'SR0a HIGH ss RETURN '-------------------------------------------------------------------------- isd_wr_apc: 'Write to APC Register using bits D2:D0 to set Volume LOW ss bSPI = $65 'Write APC2 GoSub isd_spi ISD_Data[0] = bSPI 'SR0a bSPI = %01000011 'Volume set by D2:D0 (000=Max) 'Output set by D7 (0=Aud, 1=Aux) GoSub isd_spi ISD_Data[1] = bSPI 'SR0b bSPI = %00000100 'PWM Speaker Output D8 (0=Enable, 1=Disable) GoSub isd_spi ISD_Data[2] = bSPI 'SR0a HIGH ss RETURN '-------------------------------------------------------------------------- isd_spi: ' shift SPI data out and into SPI byte FOR spi_cnt = 0 to 7 ' MOSI = bSPI.0 ' shift LSB of byte onto MOSI line LOW SCLK ' clock MISO data out to uC (Falling Edge) temp_bit = miso ' HIGH SCLK ' clock MOSI into ISD1700 (Rising Edge) bSPI = bSPI >> 1 ' shift SPI byte Right bSPI.7 = temp_bit NEXT spi_cnt RETURN '-------------------------------------------------------------------------- isd_clr_int: ' CLEAR INTERRUPT AND EOM BITS LOW SS bSPI=$04 'Clear Interrupt Command gosub isd_spi ISD_Data[0] = bSPI 'SR0a bSPI=$00 gosub isd_spi ISD_Data[1] = bSPI 'SR0b HIGH SS RETURN '-------------------------------------------------------------------------- isd_stop: ' Stop Immediately LOW ss bSPI=$02 'Stop Command gosub isd_spi ISD_Data[0] = bSPI 'SR0a bSPI=$00 gosub isd_spi ISD_Data[1] = bSPI 'SR0b HIGH ss RETURN '-------------------------------------------------------------------------- isd_pd: ' Stop Immediately LOW ss bSPI=$07 'Power Down Command gosub isd_spi ISD_Data[0] = bSPI 'SR0a bSPI=$00 gosub isd_spi ISD_Data[1] = bSPI 'SR0b HIGH ss RETURN '-------------------------------------------------------------------------- isd_rd_status: 'read status of ISD1700 LOW ss bSPI=$05 'Read Status Command gosub isd_spi ISD_Data[0] = bSPI 'SR0a bSPI=$00 gosub isd_spi ISD_Data[1] = bSPI 'SR0b bSPI=$00 gosub isd_spi ISD_Data[2] = bSPI 'SR1 HIGH ss RETURN '************************************************************* '************************************************************* End
I did some further testing. Seems the best way to determine when a sound has finished playing is to monitor the INT status bit. Just remember to clear the INT before each SET_PLAY.
The PLAY bit will not work as it does not get cleared until you change to another mode (i.e. RECORD).
The READY bit will not tell when the sound is completed playing, rather it tells you that the chip is ready to receive another SPI command (which can happen before the sound is complete when using SETPLAY).
I couldn't find how to edit the previous post, so here are the changed parts:
(obviously your start/end addresses will be different)
Code:mainloop: PAUSE 1000 s_addr = $049 e_addr = $07c GOSUB isd_set_play GOSUB isd_wait_int GoSub isd_clr_int PAUSE 1000 s_addr = $07d e_addr = $093 GOSUB isd_set_play GOSUB isd_wait_int GoSub isd_clr_int GoTo main_loop '-------------------------------------------------------------------------- isd_wait_int: GOSUB isd_rd_status IF isINT = 0 THEN isd_wait_int RETURN
thank you very much for the nice code.
I have tested your code and it is working proerly. I can play and erase the voices by using ISD_ERASE and ISD_PLAY function. However I couldn't record any voices. I am very glad if you can help me. I can nor record any voices in defined addresses. how can I do it?
Thanks everyone (including Jerson) for the code for these ISD devices. However we only have half of the issue resolved.
According to the code only "set_play" was included. How you gonna play something if it is not recorded?
What i am getting at is... in my original post.....
Show me a simple code to Record 5 messages using set_rec and play any of them back using Set_play... i.e. for the ISD17120
Thanks again.
There are 10 kinds of people. Those that know binary and those that do not.
Trying to understand how these devices work, I could not found a way to play e.g. the third message out of 10. How is the messages indexed? I mean if you record 10 messages, how can you know the position of each and how to play them?
Are these devices confussing or am I too dumb to get it? Doh...
Ioannis
dude... these are very difficult devices... if you were to take the previous version the 2500 series... they were addressed very easily through and address bus. this SPI interface is a real headache.Are these devices confussing or am I too dumb to get it? Doh...
my OLED is far simpler to write code for than these chips.
don't worry man this is exactly why i posted this thread.
There are 10 kinds of people. Those that know binary and those that do not.
Hang in there - it's not that bad. It's just that the ISD1700 has a TON of features and options so it's overwhelming to sort out the datasheets and find what you need.
As soon as I am able, I will post some more code examples (PicBasic Pro and Liberty BASIC). I have all the record and playback functions working fine using SetPlay and SetRecord. The PIC firmware (PBPro) translates serial commands from the PC (Liberty BASIC Windows app) and controls the ISD1700 for record, play, erase, etc.
Note: I use DEBUGIN so no UART or level shifter is required for the PC to PIC serial connection.
As far as addressing, for SetRecord and SetPlay you must know the Start and End address of each sound. To make addressing easier, I just divided the ISD memory into predefined "blocks" of 1,2 or 4 seconds. This way I always know the Start address of each sound, and I use the EOM function so I don't need to know the exact length of the sound during playback (it stops automatically when it hits the EOM marker even in SetPlay). So I can replace (re-record) any sound as long as the new sound fits within the block.
Tip: When you are using SetRecord, you must specify the Start and End address. But you can send a STOP command before the End address is reached and the ISD will place an EOM marker at that spot. If you enable the EOM function, playback will stop at the EOM regardless of the End address - even when you use SetPlay!! This is very cool, and it's what allowed me to use the pre-defined memory map without knowing the exact length of the sounds.
It's not the most efficient use of available memory, but it's simple and the software/firmware does not have to calculate length of each wav file and write locations to a table. The table is pre-defined. It works well for my application (Laser Tag) as I just need to trigger a few short sound effects, and my customers want to be able to replace the stock sound effects with their own custom sounds.
Jim
I found the problem ..
TRISC = %00000000
Now all is ok !
Bookmarks