Arduino Playground is read-only starting December 31st, 2018. For more info please look at this Forum Post


#include <util/delay_basic.h>

// Debug point pin 16
#define DBG 0x04

// ADC RD signal pin 17
#define RD 0x08

// ADC write signal pin 18
#define WR 0x10

// CCD Shift Gate pin 19
#define SH 0x20

// CCD Integration Clear Gate pin 20
#define ICG 0x40

// CCD Master clock pin 21
#define MCLK 0x80
    CG 0x40

// CCD M
// CCD and ADC clocks
#define CLOCK PORTD

// ADC data
#define ADATA PINC

uint8_t buffer[3694];
char cmdBuffer[16];
int cmdIndex;
int exposureTime = 10;

void setup()
{
  // Initialize the clocks.
  DDRD |= (WR | SH | ICG | MCLK | RD | DBG);  // Set the clock lines to outputs
  CLOCK |= ICG;              // Set the integration clear gate high.
  CLOCK |= (RD | WR);        // Set the ADC wr line high.

  // Setup the ADC data port.
  DDRC = 0;
  // Enable the serial port.
  Serial.begin(115200);

  // Setup timer2 to generate a 470kHz frequency on pin 21
  TCCR2A =  + (0 << COM2A1) | (1 << COM2A0) | (1 << WGM21) | (0 << WGM20);
  TCCR2B = (0 << WGM22) | (1 << CS20);
  OCR2A = 16;
  TCNT2 = 1;
}

void readCCD(void)
{
  int x;
  uint8_t dummy;

  // Clear the CCD shift register and
  // dump the electrons into it.
  CLOCK |= DBG;
  CLOCK &= ~ICG;
  _delay_loop_1(12);
  CLOCK |= SH;
  delayMicroseconds(5);
  CLOCK &= ~SH;
  delayMicroseconds(10);
  CLOCK |= ICG;
  delayMicroseconds(1);

  for (x = 0; x < 3694; x++)
  {
    // Shift out one pixel and
    // digitize it.
    CLOCK |= SH;

    // ADC write.
    CLOCK &= ~WR;
    delayMicroseconds(1);
    CLOCK |= WR;

    // ADC convert.
    delayMicroseconds(2);

    // ADC read.
    CLOCK &= ~RD;
    delayMicroseconds(1);
    buffer[x] = ADATA;
    CLOCK |= RD;

    // Eat up a few cycles for timing.
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");

    CLOCK &= ~SH;
    delayMicroseconds(4);
  }
  CLOCK &= ~DBG;
}

void sendData(void)
{
  int x;

  for (x = 30; x < 3678; ++x)
  {
    Serial.print(x - 30);
    Serial.print(",");
    Serial.print(buffer[x]);
    Serial.print("\n");
  }
}

int cmdRecvd = 0;

void loop()
{
  int x;
  char ch;

  if (cmdRecvd) {
    if (cmdBuffer[0] == 'r')
    {
      sendData();
    }
    else if (cmdBuffer[0] == 'e')
    {
      sscanf(cmdBuffer+1,"%d", &exposureTime);
      if (exposureTime > 1000) exposureTime = 1000;
    }
    memset(cmdBuffer, 0, sizeof(cmdBuffer));
    cmdIndex = 0;
    cmdRecvd = 0;
  }
  delay(exposureTime);
  readCCD();
  if (Serial.available())
  {
    ch = Serial.read();
    if (ch == 0x0a) {
      cmdBuffer[cmdIndex++] = '\0';
      cmdRecvd = 1;
    } else {
      cmdBuffer[cmdIndex++] = ch;
      cmdRecvd = 0;
    }
  }
}