Library for LinkSprite Y201 JPEG serial camera.

Y201.cpp

Committer:
ashleymills
Date:
2012-07-20
Revision:
10:fd12c96da974
Parent:
9:fbd80a803857

File content as of revision 10:fd12c96da974:

#include "Y201.h"
#include "rtos.h"

const char Y201::resetSeq            [4] = {0x56,0x00,0x26,0x00};
const char Y201::resetSeqAck         [4] = {0x76,0x00,0x26,0x00};
const char Y201::takePicSeq          [5] = {0x56,0x00,0x36,0x01,0x00};
const char Y201::takePicSeqAck       [5] = {0x76,0x00,0x36,0x00,0x00};
const char Y201::set160x120          [9] = {0x56,0x00,0x31,0x05,0x04,0x01,0x00,0x19,0x22};
const char Y201::set320x240          [9] = {0x56,0x00,0x31,0x05,0x04,0x01,0x00,0x19,0x11};
const char Y201::set640x480          [9] = {0x56,0x00,0x31,0x05,0x04,0x01,0x00,0x19,0x00};
const char Y201::setSizeAck          [5] = {0x76,0x00,0x31,0x00,0x00};
const char Y201::readFileSize        [5] = {0x56,0x00,0x34,0x01,0x00};
const char Y201::readFileSizeAck     [7] = {0x76,0x00,0x34,0x00,0x04,0x00,0x00};
const char Y201::readFileHead        [8] = {0x56,0x00,0x32,0x0C,0x00,0x0A,0x00,0x00};
const char Y201::readFileAck         [5] = {0x76,0x00,0x32,0x00,0x00};
//const char Y201::changeBaudRateSeq   [5] = {0x56,0x00,0x24,0x03,0x01};
//const char Y201::changeBaudRateAck   [5] = {0x76,0x00,0x24,0x00,0x00};
const char Y201::enterPowerSavingSeq [7] = {0x56,0x00,0x3E,0x03,0x00,0x01,0x01};
const char Y201::enterPowerSavingAck [5] = {0x76,0x00,0x3E,0x00,0x00};
const char Y201::exitPowerSavingSeq  [7] = {0x56,0x00,0x3E,0x03,0x00,0x01,0x00};
const char Y201::exitPowerSavingAck  [5] = {0x76,0x00,0x3E,0x00,0x00};

void Y201::trash() {
    // wait for trash...
    while(readable()) {
        int x = getc();
    }
}

bool Y201::readImage(int startAddress, int readLen, uint8_t *readBuffer) {
   trash(); // camera sends random crap after sending certain responses, so need to clear it
   //Thread::wait(5);
   putSeq(readFileHead,readFileHeadLen);
   putc(startAddress>>8); // Start Address MSB
   putc(startAddress&255); // Start Address LSB
   putc(0x00);
   putc(0x00);
   putc(readLen>>8); // Length of file MSB
   putc(readLen&255); // length of file LSB
   putc(0x00); // Interval MSB
   putc(0x0A); // Interval LSB
   int nread = 0;
   if(waitFor(readFileAck,readFileAckLen)) {
      Thread::wait(1);
      Timer t;
      t.start();
      while(nread<readLen) {
         if(readable()) {
            uint8_t c = getc();
            // fprintf(stdout, "[%02x]", c);
            readBuffer[nread] = c;
            nread++;
            t.reset();
         } else {
            if(t.read_ms()>3000) {
               fprintf(stdout, "Blocked!\n Missed %d bytes over %d\nLast byte read is %02x\n", readLen - nread, readLen, readBuffer[nread-1]);
               return false;
            }
         }
     }
     Thread::wait(1);
   } else {
      return false;
   }
   return true;
}

bool Y201::waitFor(const char *seq, const int seqLen) {
    int spos = 0;
    long timeout = 100;
    Timer timer;
    timer.start();
    while(spos<seqLen) {
        if(readable()) {
            int c = getc();
            if(seq[spos]==c) {
                spos++;
            } else {
                return false;
            }
        } else {
            if(timer.read_ms()>timeout) {
                return false;
            }
        }
    }
    return true;
}

bool Y201::waitForInt(int bytes, int *fileSize) {
   int spos = 0;
   long timeout = 100;
   Timer timer;
   timer.start();
   *fileSize = 0;
   while(spos<bytes) {
        if(readable()) {
            uint8_t val = getc();
            if(spos==0) {
                *fileSize += (val<<8);
            } else {
                *fileSize += val;
            }
            
            spos++;
            
        } else {
            if(timer.read_ms()>timeout) {
                return false;
            }
        }
    }
    return true;
}

void Y201::putSeq(const char *seq, int seqLen) {
    while(seqLen--) {
        putc(*seq++);
    }
}

Y201::Y201(PinName tx, PinName rx, const char *name) : MODSERIAL(tx,rx,name) {
    baud(38400);
}

bool Y201::setImageSize(Y201ImageSize size) {
    switch(size) {
        case Y201::e640x480:
            putSeq(set640x480,setSizeLen);
        break;
        
        case Y201::e160x120:
            putSeq(set160x120,setSizeLen);
        break;
        
        case Y201::e320x240:
            putSeq(set320x240,setSizeLen);
        break;
    }
    return waitFor(setSizeAck,setSizeAckLen);
}

bool Y201::takePicture() {
   putSeq(takePicSeq,takePicSeqLen);
   Thread::wait(50);
   return waitFor(takePicSeqAck,takePicSeqAckLen);
}

bool Y201::enterPowerSaving() {
    putSeq(enterPowerSavingSeq,enterPowerSavingLen);
    return waitFor(enterPowerSavingAck,enterPowerSavingAckLen);
}

bool Y201::exitPowerSaving() {
    putSeq(exitPowerSavingSeq,exitPowerSavingLen);
    return waitFor(exitPowerSavingAck,exitPowerSavingAckLen);
}

bool Y201::readImageSize(int *fileSize) {
   putSeq(readFileSize,readFileSizeLen);
   bool ret = waitFor(readFileSizeAck,readFileSizeAckLen);
   if(!ret)
      return false;
  return waitForInt(2,fileSize);
}

bool Y201::reset() {
  putSeq(resetSeq,resetSeqLen);
  bool ret = waitFor(resetSeqAck,resetSeqAckLen);

  // wait for trash
  int count = 3;
  while(count) {
    count--;
    if(readable()) {
        while(readable()) {
            int c = getc();
        }
    }
    Thread::wait(1000);
  }
  return ret;
}

/*

THIS SIMPLY DOESN'T WORK -- Known bug, LinkSprite quality products


bool Y201::changeBaudRate(Y201BaudRate baudRate) {
   // put the prefix
   putSeq(changeBaudRateSeq,changeBaudRateSeqLen);
   int br = 9600;
   
   // put the baud rate
   switch(baudRate) {
      case Y201::e9600:
         putc(0xAE);
         putc(0xC8);
         br = 9600;
      break;
      
      case Y201::e19200:
         putc(0x56);
         putc(0xE4);
         br = 19200;
      break;
      
      case Y201::e38400:
         putc(0x2A);
         putc(0xF2);
         br = 38400;
      break;
      
      case Y201::e57600:
         putc(0x1C);
         putc(0x4C);
         br = 57600;
      break;
      
      case Y201::e115200:
         putc(0xAE);
         putc(0xC8);
         br = 115200;
      break;
      
      default:
         putc(0xAE);
         putc(0xC8);
         br = 9600;
      break;
   }
   
   baud(br);
   
   // wait for the ack
   return waitFor(changeBaudRateAck,changeBaudRateAckLen);
}
*/