//#DOC Main, program entry and main loop
#include "main.h"
#include <otFPGA.h>
#include <otPort.h>
#include <otSpi.h>
#include <otSerial.h>
#include <otTimer.h>
#include <otPrintf.h>
#include <otPga.h>
#include <otADS868x.h>
#include <otILI9341.h>
#include <otStatistics.h>
//#define DLY DelayUs(1);
#define DLY NOP;
#define SPEC_ST BIT(15)
#define SPEC_CLK BIT(14)
#define SPEC_CHANNELS 288 // New Spec Channel
S16 data[SPEC_CHANNELS];
otPga pga;
otADS868x adc;
otILI9341 tft;
otStatistics stat;
// Draw range of sampled data
void plotRange(S16 mn, S16 mx)
{
char buf[16];
U16 col = RGB565_GREEN;
U32 l = (U32) mx;
// Blank previous draw
tft.fillRect(288, 0, 319, 239, RGB565_BLACK);
l = 240 * (mx - mn) / 25000;
// 15%
if(l < 36) col = RGB565_BLUE;
// 80%
if(l > 192) col = RGB565_RED;
tft.fillRect(288, 240 - l, 319, 239, col);
sprintf(buf, "%5d", mn);
tft.setCursor(0, 0);
tft.writeString(buf);
sprintf(buf, "%5d", mx);
tft.setCursor(260, 0);
tft.writeString(buf);
}
FAST_CODE_2 void plotSpectral(U16 col)
{
U16 y;
SpiSet(SA_LCD);
stat.evaluate();
S16 rng = stat.max - stat.min;
S16 mn = stat.min;
S16 mx = stat.max;
plotRange(mn, mx);
// Force fixed range
//rng = 25000;
//tft.clear();
for(int i = 0; i < SPEC_CHANNELS; i++)
{
y = 240 - (data[i] - mn) * 240 / rng;
//tft.setPixel(i, y, RGB565_YELLOW);
tft.drawLine(i, y, i, 239, col);
}
}
// Read spectrometer data
FAST_CODE_2 void readSpectrometer()
{
int delayTime = 1; // delay time
SpiSet(SA_ADC);
// Start clock cycle and set start pulse to signal start
PPF_CLR = SPEC_CLK;
DLY
PPF_SET = SPEC_CLK;
DLY
PPF_CLR = SPEC_CLK;
PPF_SET = SPEC_ST;
DLY
// Sample for a period of time
for(int i = 0; i < 15; i++)
{
PPF_SET = SPEC_CLK;
DLY
PPF_CLR = SPEC_CLK;
DLY
}
// Set SPEC_ST to low
PPF_CLR = SPEC_ST;
//Sample for a period of time
for(int i = 0; i < 85; i++)
{
PPF_SET = SPEC_CLK;
DLY
PPF_CLR = SPEC_CLK;
DLY
}
// One more clock pulse before the actual read
PPF_SET = SPEC_CLK;
DLY
PPF_CLR = SPEC_CLK;
DLY
// Read from SPEC_VIDEO
for(int i = 0; i < SPEC_CHANNELS; i++)
{
data[i] = adc.read();
PPF_SET = SPEC_CLK;
DLY
PPF_CLR = SPEC_CLK;
DLY
}
// Set SPEC_ST to high
PPF_SET = SPEC_ST;
// Sample for a small amount of time
for(int i = 0; i < 7; i++)
{
PPF_SET = SPEC_CLK;
DLY
PPF_CLR = SPEC_CLK;
DLY
}
PPF_SET = SPEC_CLK;
DLY
}
// Used for debug, print data values
void printData()
{
for(int i = 0; i < SPEC_CHANNELS; i++)
{
printf("%5d ", data[i]);
if(((i + 1) % 16) == 0)
printf("\n");
}
printf("\n\n");
}
void setup()
{
// Setup the UART0 used by printf
UartEnableSignals(UART0);
UartSetBaud(UART0, 115200);
// Init printf
setStdout(1024, UART0); // printf output is now directed on UART0
TimerSetAsCounter(TIMER0);
TimerEnable(TIMER0, true);
// Init multiplexor and amplifier
pga.init();
pga.channel(0);
pga.gain(otPga::GAIN_1);
// Used port and bits for the spectrometer controls
PortConfig(PP_F, 14, P_OUT);
PortConfig(PP_F, 15, P_OUT);
PPF_CLR = SPEC_ST | SPEC_CLK;
PPF_SET = SPEC_CLK;
PPF_CLR = SPEC_CLK;
// Init graphics for spectral plot
tft.init();
tft.setRotation(otILI9341::IR_270);
tft.clear();
tft.setTextColor(RGB565_YELLOW, RGB565_BLACK);
tft.setTextSize(1);
// Init 16 bit ADC
adc.init();
// Set ADC range
adc.setRange(otADS868x::UNI_5V);
// Arm statistics engine ...
stat.setData(otStatistics::T_S16, (void *) data, SPEC_CHANNELS);
}
void loop()
{
U32 st, et;
// Blank previous plot
plotSpectral(RGB565_BLACK);
// Grab new spectral
st = TimerGetCounts(TIMER0); // Grab start time
readSpectrometer();
et = TimerGetCounts(TIMER0); // Grab end time
et = ElapsedTimeUs(st, et);
printf("Grab time: %4u uS, Benchmark: %.1lf Spectrals/s\n", et, 1E6 / (double) et);
// Plot grabbed spectral
plotSpectral(RGB565_YELLOW);
//printData();
}