odd integer printing problem

I have a counter in a wait routine. If it counts high enough, I expected it to wrap around and take on a negative value or wrap all the way around, you know.

My output was confusing. Basically, Serial.println passed an "int" type printed an extremely large value.

When I tried to make a tiny example for you all, it did not do the same thing. It is now down to uncommenting a few lines which should make no difference, yet "fix" the problem.

I hear you asking to see the code. Unfortunately you might not be able to run it, as it is hooked up to an ISD1760 break out board. But here we go:

This code

/*
  original code from this thread
  http://forum.arduino.cc/index.php?topic=38867.0

  powers up the 1700
  plays from the current pointer on the chip memory
  waits until the sample is done
  forwards to next recording

  loops

  here with an improved ready_wait()
*/

//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 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_ERASE   0x82

void setup() {
  byte clr;
  pinMode(DATAOUT, OUTPUT);
  pinMode(DATAIN, INPUT);
  pinMode(SPICLOCK, OUTPUT);
  pinMode(SLAVESELECT, OUTPUT);

  digitalWrite(SLAVESELECT, HIGH); //disable device

  SPCR = B01111111; //data lsb, clock high when idle, samples on falling

  clr = SPSR;
  clr = SPDR;
  delay(10);

  Serial.begin(9600);

  digitalWrite(SLAVESELECT, LOW);
  spi_transfer(PU); // power up
  spi_transfer(0x00); // data byte
  digitalWrite(SLAVESELECT, HIGH);
  delay(100);

  digitalWrite(SLAVESELECT, LOW);
  spi_transfer(CLR_INT); // clear interupt and eom bit
  spi_transfer(0x00); // data byte
  digitalWrite(SLAVESELECT, HIGH);

  Serial.println("...setup");
}

unsigned char once = 1;

void loop() {
  if (once) {
    once--;

    int start = 219;
    int endx = 272;

    digitalWrite(SLAVESELECT, LOW);
    spi_transfer(SET_PLAY);  /* not so fast */
    spi_transfer(0);

    spi_transfer(start & 0xff);
    spi_transfer(start >> 8);

    spi_transfer(endx & 0xff);
    spi_transfer(endx >> 8);
    spi_transfer(0);

/*  spi_transfer(start % 256);
    spi_transfer((int) start / 256);

    spi_transfer(end % 256);
    spi_transfer((int) end / 256);
    spi_transfer(0);
*/
    digitalWrite(SLAVESELECT, HIGH);

    ready_wait();
    Serial.println("done.");
  }
}


void ready_wait()
{
  int counter, aCopy;
  long int longCounter;
  byte byte3;

  counter = 0;
  longCounter = 0;
  do {
 //   delay(1);
    counter++;
    longCounter++;
    digitalWrite(SLAVESELECT, LOW);
    spi_transfer(RD_STATUS);
    spi_transfer(0x00);
    byte3 = spi_transfer(0x00);
    digitalWrite(SLAVESELECT, HIGH);
  } while (byte3 << 7 != 128);

  Serial.println(" WORKS");

  Serial.println(counter);

// uncomment these two lines and the above Serial.println prints a number between +/- 32K

  aCopy = counter;
  Serial.println(aCopy);
  Serial.println(longCounter);
}

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
}

produces this output

...setup
 WORKS
-31535
-31535
34001
done.

and this code, identical except for printing "DOESN'T" and commenting out two subsequent lines of code

/*
  original code from this thread
  http://forum.arduino.cc/index.php?topic=38867.0

  powers up the 1700
  plays from the current pointer on the chip memory
  waits until the sample is done
  forwards to next recording

  loops

  here with an improved ready_wait()
*/

//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 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_ERASE   0x82

void setup() {
  byte clr;
  pinMode(DATAOUT, OUTPUT);
  pinMode(DATAIN, INPUT);
  pinMode(SPICLOCK, OUTPUT);
  pinMode(SLAVESELECT, OUTPUT);

  digitalWrite(SLAVESELECT, HIGH); //disable device

  SPCR = B01111111; //data lsb, clock high when idle, samples on falling

  clr = SPSR;
  clr = SPDR;
  delay(10);

  Serial.begin(9600);

  digitalWrite(SLAVESELECT, LOW);
  spi_transfer(PU); // power up
  spi_transfer(0x00); // data byte
  digitalWrite(SLAVESELECT, HIGH);
  delay(100);

  digitalWrite(SLAVESELECT, LOW);
  spi_transfer(CLR_INT); // clear interupt and eom bit
  spi_transfer(0x00); // data byte
  digitalWrite(SLAVESELECT, HIGH);

  Serial.println("...setup");
}

unsigned char once = 1;

void loop() {
  if (once) {
    once--;

    int start = 219;
    int endx = 272;

    digitalWrite(SLAVESELECT, LOW);
    spi_transfer(SET_PLAY);  /* not so fast */
    spi_transfer(0);

    spi_transfer(start & 0xff);
    spi_transfer(start >> 8);

    spi_transfer(endx & 0xff);
    spi_transfer(endx >> 8);
    spi_transfer(0);

/*  spi_transfer(start % 256);
    spi_transfer((int) start / 256);

    spi_transfer(end % 256);
    spi_transfer((int) end / 256);
    spi_transfer(0);
*/
    digitalWrite(SLAVESELECT, HIGH);

    ready_wait();
    Serial.println("done.");
  }
}


void ready_wait()
{
  int counter, aCopy;
  long int longCounter;
  byte byte3;

  counter = 0;
  longCounter = 0;
  do {
 //   delay(1);
    counter++;
    longCounter++;
    digitalWrite(SLAVESELECT, LOW);
    spi_transfer(RD_STATUS);
    spi_transfer(0x00);
    byte3 = spi_transfer(0x00);
    digitalWrite(SLAVESELECT, HIGH);
  } while (byte3 << 7 != 128);

  Serial.println(" DOESN'T");

  Serial.println(counter);

// uncomment these two lines and the above Serial.println prints a number between +/- 32K

//  aCopy = counter;
//  Serial.println(aCopy);
  Serial.println(longCounter);
}

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
}

gives me

...setup
 DOESN'T
4294935762
34002
done.

It feels like I am corrupting something. But Serial.println passed an integer should never print 4294935762. And yes, in hex the bottom part is correct, I mean it is the right number with FFFF in front of what would be a negative 16 bit signed integer.

alto777

Looks like the compiler has gotten confused and is calling the 'unsigned long' version of .println() instead of 'int' or 'long'. The count 34002 has overflowed to the negative value -31534 (0x84D2) which gets sign-extended to 0xFFFF84D2 when converted to 'long' and that comes out as 4294935762 when treated as 'unsigned long'. I don't know why it thinks 'counter' should be printed as 'unsigned long' but 'aCopy' should be printed as 'int'.