Go Down

Topic: How to Controll Nuvoton ISD1760 Chip? (Read 6073 times) previous topic - next topic

ryo23

Hello, 

I am a newbie of Arduino and this forum. I have been trying to work with Nuvoton ISD COBO 1760 and Arduino Duemilanove.
I found the read-only forum (1) http://arduino.cc/forum/index.php/topic,37348.0, I thought this was awesome, but it seemed not to work. Next, I found this thread - (2) http://arduino.cc/forum/index.php/topic,52509.0.html

I tried the code in these threads. I used the code of  thread  (1) for the header and sample program, and  thread  (2) for the definition of ISD1700 class.

I fixed the code a little.

//#include "WProgram.h"
#include "Arduino.h"

But it wouldn't work. All I got were "Not_RDY".

In push button mode it works well. I can record with the on board mic. and I can play them, and the forward function also works well.

I upload the photo of my trying system. Is there anyone who help me?
And any suggestion welcomes.

Thanks in advance.

ryo23


cr0sh


I solved myself, thank you! :)


Well - that's great, but etiquette suggests that you post what you did to fix the problem here, so that others who may have this problem in the future may learn from your example...
I will not respond to Arduino help PM's from random forum users; if you have such a question, start a new topic thread.

ryo23

Sorry for being too late to upload my codes. I hadn't noticed above message.
How did I fix the problem:
The document said "It needs at least 500 nsec between the SS pin is set LOW and transmitting the clock." So I added "delay(WAIT_TIME)" after "digitalWrite(SLAVESELECT, LOW). I think WAIT_TIME=1(ms) is OK, because it is greater than 500ns.

How to connect the audio line:
Connect PC's audio output to the Arduino's AnaIn and Gnd pins. The stereo mini plug must convert into the monoral mini plug.

How to control:
Control Arduino by the Arduino 1.0's serial montor.
0 - initialize.
1 - erasing test with specifying the address.
2 - recording test with specifying the address.
3 - playback test with specifying the address.
l - clear interupt.
y - play
r - rocord
f - forward
z - erase all
e - erase
s - reset
a - set the apc resister as "mic in".
b - set the apc resister as "analog in".

How to record:
1)Firstly, erase whole memories by "z" key.
2)Switch to line input by "b" key. You will hear sound.
3)Start recording by "r" key. Stop recording by "p" key.
4)Playback it by "y" key.
How to "set-record":
1)Firstly, erase whole memories by "z" key.
2) "1" key - erase memories from start_address to end_address.
3) "2" key - record on the memories from start_address to end_address.
4) "3" key - playback between start_address and end_address.

ryo23

Code: [Select]
//define pins
#define DATAOUT     11   //mosi
#define DATAIN 12   //miso
#define SPICLOCK    13   //sck
#define SLAVESELECT 10   //ss

//opcodes
#define PU    0x01
#define STOP  0x02
#define RESET 0x03
#define CLR_INT     0x04
#define RD_STATUS   0x05
#define RD_PLAY_PTR 0x06
#define PD    0x07
#define RD_REC_PTR  0x08
#define DEVID 0x09
#define PLAY  0x40
#define REC   0x41
#define REC_LED   0x51//record with LED on
#define ERASE 0x42
#define G_ERASE     0x43
#define RD_APC 0x44
#define WR_APC1     0x45
#define WR_APC2     0x65
#define WR_NVCFG    0x46
#define LD_NVCFG    0x47
#define FWD   0x48
#define CHK_MEM     0x49
#define EXTCLK 0x4A
#define SET_PLAY    0x80
#define SET_REC     0x81
#define SET_REC_LED    0x91//set record with LED on
#define SET_ERASE   0x82

#define WAIT_TIME 10//waiting time (ms) after SS=LOW at least 500ns
#define WAIT_TIME2 100

int start_adress = 0x010;//test address to record
int end_adress = 0x024;//20unit

void setup() {
 pinMode(DATAOUT, OUTPUT);
 pinMode(DATAIN, INPUT);
 pinMode(SPICLOCK, OUTPUT);
 pinMode(SLAVESELECT, OUTPUT);
 
 initialize();
}

void initialize()
{
  byte clr;
   
 digitalWrite(SLAVESELECT, HIGH); //disable device
 digitalWrite(SPICLOCK, HIGH); //SCLK
 digitalWrite(DATAOUT, LOW); //MOSI
 
 SPCR = B01111111; //data lsb, clock high when idle, samples on falling
 clr = SPSR;
 clr = SPDR;
 delay(10);

 //start serial
 Serial.begin(9600);
 Serial.println("Sketch is starting up");

 pu();
 clear_int();
}

void loop()
{
   char c;
   boolean f;
   boolean rec_fg = false;
   boolean play_fg = false;
   
  if(Serial.available())
   {
      c = Serial.read();
     switch(c)
     {
        case '0':
          initialize();
          break;
        case '1':
          set_erase(start_adress, end_adress);
          break;
        case '2':
          set_rec(start_adress, end_adress);
          rec_fg = true;
          break;
        case '3':
          set_play(start_adress, end_adress);
          play_fg = true;
          break;
        case 'l':
          clear_int();
          break;
        case 'y':
          play();
          play_fg = true;
          break;
        case 'r':
          rec();
          rec_fg = true;
          break;
        case 'f':
          fwd();
          break;
        case 'z':
          eraseAll();
        break;
        case 'e':
          erase();
        break;
        case 'p':
          stop();
          break;
        case 's':
          reset();
          break;
        case 'a':
          write_apc(true, false, 7);//mic in & no moniter on recording
          break;
        case 'b':
          write_apc(false, false, 7);//analog in & no moniter on recording
          break;
        case 'c':
          Serial.println(read_apc(), BIN);//read apc
        break;  
        case 'd':
          Serial.println(read_status(), BIN);//read status
     }
   }
     
   if(play_fg == true)
   {
     ready_play_wait();
     play_fg = false;
   }
   if(rec_fg == true)
   {
     ready_rec_check();
     rec_fg = false;
   }
}

void pu()//power up
{
 digitalWrite(SLAVESELECT, LOW);
 delay(WAIT_TIME);
 spi_transfer(PU); // power up
 spi_transfer(0x00); // data byte
 digitalWrite(SLAVESELECT, HIGH);
 delay(WAIT_TIME2);
 
 Serial.println("power up end");
}

void clear_int()// clear interupt
{
  digitalWrite(SLAVESELECT, LOW);
  delay(WAIT_TIME);
  spi_transfer(CLR_INT); // clear interupt and eom bit
  spi_transfer(0x00); // data byte
  digitalWrite(SLAVESELECT, HIGH);
  delay(WAIT_TIME2);
  Serial.println("clear int end");
}

void reset()// reset
{
 digitalWrite(SLAVESELECT, LOW);
 delay(WAIT_TIME);
 spi_transfer(RESET); // resett
 spi_transfer(0x00); // data byte
 digitalWrite(SLAVESELECT, HIGH);
 delay(WAIT_TIME2);
 
 Serial.println("reset end");
}

void play()
{
 digitalWrite(SLAVESELECT, LOW);
 delay(WAIT_TIME);
 spi_transfer(PLAY); // play
 spi_transfer(0x00); // data byte
 digitalWrite(SLAVESELECT, HIGH);
 delay(WAIT_TIME2);
 
 Serial.println("play start");
}

void stop()
{
 digitalWrite(SLAVESELECT, LOW);
 delay(WAIT_TIME);
 spi_transfer(STOP); // stop
 spi_transfer(0x00); // data byte
 digitalWrite(SLAVESELECT, HIGH);
 delay(WAIT_TIME2);
 
 Serial.println("stop end");
}

void rec()
{
  uint8_t data[2] = {0xFF,0xFF};
 
 digitalWrite(SLAVESELECT, LOW);
 delay(WAIT_TIME);
 //spi_transfer(REC);// record
 data[0] = spi_transfer(REC_LED);// record with LED on
 data[1] = spi_transfer(0x00); // data byte
 digitalWrite(SLAVESELECT, HIGH);
 
 delay(WAIT_TIME2);
}

void set_erase(int starta, int enda)
{
 digitalWrite(SLAVESELECT, LOW);
 delay(WAIT_TIME);
 spi_transfer(SET_ERASE); // clear interupt and eom bit
 spi_transfer(0); // data byte

 spi_transfer(starta & 255); // data byte start
 spi_transfer(starta >> 8); // data byte last 3 bits
 spi_transfer(enda & 255); // data byte stop
 spi_transfer(enda >> 8); // data byte last 3 bits
 spi_transfer(0); // data byte blank
 digitalWrite(SLAVESELECT, HIGH);  
 delay(WAIT_TIME2);
 
 Serial.println("set erase end");
}

void set_play(int starta, int enda)
{
 digitalWrite(SLAVESELECT, LOW);
 delay(WAIT_TIME);
 spi_transfer(SET_PLAY); // clear interupt and eom bit
 spi_transfer(0); // data byte

 spi_transfer(starta & 255); // data byte start
 spi_transfer(starta >> 8); // data byte last 3 bits
 spi_transfer(enda & 255); // data byte stop
 spi_transfer(enda >> 8); // data byte last 3 bits
 spi_transfer(0); // data byte blank
 digitalWrite(SLAVESELECT, HIGH);  
 delay(WAIT_TIME2);
 
 Serial.println("set play end");
}

void set_rec(int starta, int enda)
{
 digitalWrite(SLAVESELECT, LOW);
 delay(WAIT_TIME);
 //spi_transfer(SET_REC); // clear interupt and eom bit
 spi_transfer(SET_REC_LED);//set record with LED on
 spi_transfer(0); // data byte

 spi_transfer(starta & 255); // data byte start
 spi_transfer(starta >> 8); // data byte last 3 bits
 spi_transfer(enda & 255); // data byte stop
 spi_transfer(enda >> 8); // data byte last 3 bits
 spi_transfer(0); // data byte blank
 digitalWrite(SLAVESELECT, HIGH);  
 delay(WAIT_TIME2);
 
 Serial.println("set rec end");
}


ryo23

Code: [Select]
void erase()
{
  digitalWrite(SLAVESELECT, LOW);
  delay(WAIT_TIME);
  spi_transfer(ERASE);// erase
  spi_transfer(0x00); // data byte
  digitalWrite(SLAVESELECT, HIGH);
  delay(WAIT_TIME2);
 
  Serial.println("erase end");
}

void eraseAll()
{
  digitalWrite(SLAVESELECT, LOW);
  delay(WAIT_TIME);
  spi_transfer(G_ERASE);// g_erase
  spi_transfer(0x00); // data byte
  digitalWrite(SLAVESELECT, HIGH);
  delay(WAIT_TIME2);
 
  Serial.println("erase all end");
}

void fwd()
{
  digitalWrite(SLAVESELECT, LOW);
  delay(WAIT_TIME);
  spi_transfer(FWD); // forward
  spi_transfer(0x00); // data byte
  digitalWrite(SLAVESELECT, HIGH);
  delay(WAIT_TIME2);
 
  Serial.println("forward end");
}

void ready_play_wait()
{
  byte byte1;
  byte byte2;
  byte byte3;

  while(byte3 << 7 != 128)
  {
    digitalWrite(SLAVESELECT, LOW);
    delay(WAIT_TIME);
    byte1 = spi_transfer(RD_STATUS); // clear interupt and eom bit
    byte2 = spi_transfer(0x00); // data byte
    byte3 = spi_transfer(0x00); // data byte
    digitalWrite(SLAVESELECT, HIGH);
    delay(WAIT_TIME2);
  }
 
  delay(100);
 
  Serial.println("play end");
}

void ready_rec_check()
{
  byte byte1;
  byte byte2;
  byte byte3;

  while(byte3 << 7 == 128)
  {
    digitalWrite(SLAVESELECT, LOW);
    delay(WAIT_TIME);
    byte1 = spi_transfer(RD_STATUS); // clear interupt and eom bit
    byte2 = spi_transfer(0x00); // data byte
    byte3 = spi_transfer(0x00); // data byte
    digitalWrite(SLAVESELECT, HIGH);
    delay(WAIT_TIME2);
  }
 
  delay(100);
 
  Serial.println("rec start");
}

char spi_transfer(volatile char data)
{
  SPDR = data;           // Start the transmission
  while (!(SPSR & (1 << SPIF)))     // Wait for the end of the transmission
  {
  };
  return SPDR;           // return the received byte
}

//flag : false=analog in/true=mic in
//flag2 : false=no monitor on recording / true=monitor on recording
//vol : volume max=7 min=0
void write_apc(boolean flag, boolean flag2, int vol)
{
    uint16_t d[12];
    for(int i = 0; i < 12; i++)
    {
      d = 0x00;
    }
    if(flag == true)
      d[6] = 0x01;
    if(flag2 == true)
      d[3] = 0x01;
     
    int vv = 7 - vol;
     
    d[0] = vv & 0x01;
    d[1] = vv & 0x02;
    d[2] = vv & 0x04;
   
    uint16_t apc =  (d[0] | d[1] << 1 | d[2] << 2 | d[3] << 3 | d[4] << 4 | d[5] << 5 | d[6] << 6 | d[7] << 7 | d[8] << 8 | d[9] << 9 | d[10] << 10 | d[11] << 11);
     
    digitalWrite(SLAVESELECT, LOW);
    delay(WAIT_TIME);
    spi_transfer(WR_APC2); // write apc register 2
    spi_transfer(apc & 0xFF); // data byte start
    spi_transfer(apc >> ; // data byte last 3 bits

    digitalWrite(SLAVESELECT, HIGH);
   
    delay(WAIT_TIME2);
   
    Serial.println("write apc end");
}

uint16_t read_apc()
{
  uint16_t apc;
  uint8_t data[4] = {0xFF,0xFF,0xFF,0xFF};
 
  digitalWrite(SLAVESELECT, LOW);
  delay(WAIT_TIME);
  data[0] = spi_transfer(RD_APC); // read apc register
  data[1] = spi_transfer(0);
  data[2] = spi_transfer(0);
  data[3] = spi_transfer(0);
  digitalWrite(SLAVESELECT, HIGH);
 
  delay(WAIT_TIME2);
 
  apc = word(data[3], data[2]);
 
  Serial.println("read apc end");
 
  return apc;
}
 
uint16_t read_status(void)
{
  uint16_t sr1;
  uint8_t data[3] = {0xFF,0xFF,0xFF};
 
  digitalWrite(SLAVESELECT, LOW);
  delay(WAIT_TIME);
  data[0] = spi_transfer(RD_STATUS); // read status register
  data[1] = spi_transfer(0);
  data[2] = spi_transfer(0);
  digitalWrite(SLAVESELECT, HIGH);
 
  delay(WAIT_TIME2);
 
  sr1 = word(data[2], 0xFF);
  return sr1;
}

berreizeta


Hi ryoru,

In:

 for(int i = 0; i < 12; i++)
    {
      d = 0x00;
    }


d = char, byte, int ??.....

In:

    spi_transfer(apc >> ; // data byte last 3 bits


missing : (apc >>  ?¿?;


Thanks.
Ger.

bradski58

I know this is an old thread but thought I'd share my experience and unique solution in case anyone is considering using the ISD17xx.

After battling with the SPI for more time than I care to admit, I had an important realization.

SPI operation seems at best intermittent.  Some commands work all of the time (DEVID), some work some of the time (RD_PTR).  The device seems to work fine in manual mode, with the switches.

Since the switch inputs are just looking for logic levels, I thought about driving them directly with the Arduino.  There already was a common ground.  I rewired my board, putting in 10k resistors in series for a bit of isolation/protection and ran digital lines to the switch inputs.  I chose 10k since the inputs have 600k pullups, and 10k should have negligible effect on a logic low.  I have not tried it but am confident that no resistors are required.

The system now works perfectly!

No bit bashing or SPI library/SPI configuration/time delays/flag checking required.  I wrote simple functions that sends logic low for 100 ms to appropriate switch inputs to activate each desired function.

The only functionality lost with this approach is that my message handling structure needs to know how many messages are recorded in the circular memory array after power is applied.  I plan on using a dedicated location in FLASH to store this value.

Asserting the RESET line gets you to a known condition (PLAY & REC PTRS at last message) so you can then use FWD to advance through the circular array.

I've also found that many boards are available with this chip on it at very affordable prices so it is a good option for adding voice output to any system.

Save yourself a lot of frustration by ignoring the SPI interface and just wire into the switch inputs.  The internal pullups and debouncing make it virtually foolproof.


alto777

I know this is an old thread but thought I'd share my experience... in case anyone is considering using the ISD17xx.
...
Couldn't have put it better myself, so I didn't. ;)

I posted on "programming questions" as it was sorta a compiler thing of general interest maybe, but my point can be reiterated harmlessly here I hope.

BTW I love and approve of hijacking buttons if it can do what you need. But I think the fear people might have of SPI should be overcome.

The "ready_play_wait()" routine from above is flawed. It has a certain chance of failing to wait at all. byte3 is tested before it is received from the chip. All you needa do is change the while to a do/while.

I think this might have caused some heads to ache.

Here's a general ready_wait that works. No need for any delay(), but it does just waste time waiting.

Code: [Select]

void ready_wait()
{
  int counter;
  byte byte3;
 
  counter = 0;
  do {
    counter++;
    digitalWrite(SLAVESELECT, LOW);
    spi_transfer(RD_STATUS);
    spi_transfer(0x00);
    byte3 = spi_transfer(0x00);
    digitalWrite(SLAVESELECT, HIGH);
  } while (byte3 << 7 != 128);

//  Serial.println(counter);
//  delay(100);
}



alto777

Go Up