#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;
}
}
}