297 lines
7.2 KiB
Plaintext
297 lines
7.2 KiB
Plaintext
#include <NewSoftSerial.h>
|
|
|
|
NewSoftSerial mySerial(3, 8);
|
|
|
|
//TLC5940NT pin definitions
|
|
#define VPRG 2
|
|
#define SIN 11
|
|
#define SCLK 13
|
|
#define XLAT 4
|
|
#define BLANK 5
|
|
#define DCPRG 6
|
|
#define GSCLK 7
|
|
#define MISO 12
|
|
#define SS 10
|
|
|
|
#define BAUD 9600
|
|
#define BAUD_SOFT 9600
|
|
|
|
// For interrupt timing; needed only to do intermediate clock speeds
|
|
/* Divide interrupt frequency by a factor of FREQ. It is preferable to keep
|
|
FREQ as small as possible, and control the frequency of the interrupts
|
|
using the hardware clock. Setting it to 1 disables this entirely, which,
|
|
if it works, is ideal; this should be the same as commenting out the
|
|
"#define FREQ" statement entirely.
|
|
*/
|
|
#define FREQ 1 // How many interrupts occur before the serial commands are read
|
|
#if FREQ > 1
|
|
byte int_counter = 0;
|
|
#endif
|
|
|
|
const int sensor[6] = {14,15,16,17,18,19};
|
|
|
|
long level[16] = {
|
|
4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095,4095, 4095, 4095, 4095,4095, 4095, 4095, 4095};
|
|
|
|
char RFID_temp[30] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
|
char RFID[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
|
|
|
const int remap[16] = {
|
|
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
|
|
|
|
byte ready = true;
|
|
byte command = 0;
|
|
byte lastread;
|
|
byte estado = 0;
|
|
byte estado_ant = 0;
|
|
|
|
byte count=0;
|
|
|
|
//The timer interrupt routine, which periodically interprets the serial commands
|
|
ISR(TIMER2_OVF_vect) {
|
|
sei(); //Reenable global interrupts, otherwise serial commands will get dropped
|
|
#if FREQ > 1
|
|
if(++int_counter == FREQ){ // Only do this once every FREQ-th interrupt
|
|
int_counter = 0;
|
|
#endif //FREQ
|
|
if(Serial.available()){
|
|
if(ready){ // If the last command has finished executing, read in the next command and reset the command flag
|
|
command = Serial.read();
|
|
ready = false;
|
|
}
|
|
switch (command >> 4) { //Execute the appropriate command, but only if we have received enough bytes to complete it. We might one day add "partial completion" for long command strings.
|
|
case 1: // set colour
|
|
if( Serial.available()) {
|
|
level[command&0x0F] = Serial.read()*16;
|
|
ready=true;
|
|
}
|
|
break;
|
|
case 2: // led_on
|
|
if( Serial.available() ) {
|
|
lastread = Serial.read();
|
|
|
|
ready = true;
|
|
}
|
|
|
|
break;
|
|
case 3: // led_off
|
|
if( Serial.available() ) {
|
|
lastread = Serial.read();
|
|
|
|
ready = true;
|
|
}
|
|
break;
|
|
case 4: // led_row1
|
|
if( Serial.available() ) {
|
|
lastread = Serial.read();
|
|
|
|
ready = true;
|
|
}
|
|
break;
|
|
case 5: // led_col1
|
|
if( Serial.available() ) {
|
|
lastread = Serial.read();
|
|
|
|
ready = true;
|
|
}
|
|
break;
|
|
case 8: //frame
|
|
if( Serial.available() > 7 ) {
|
|
lastread = Serial.read();
|
|
lastread = Serial.read();
|
|
lastread = Serial.read();
|
|
lastread = Serial.read();
|
|
lastread = Serial.read();
|
|
lastread = Serial.read();
|
|
lastread = Serial.read();
|
|
lastread = Serial.read();
|
|
|
|
ready = true;
|
|
}
|
|
break;
|
|
case 9: //clear
|
|
if( Serial.available() ) {
|
|
lastread = Serial.read();
|
|
|
|
ready = true;
|
|
}
|
|
break;
|
|
case 12:
|
|
if( Serial.available() ) {
|
|
lastread = Serial.read();
|
|
|
|
ready = true;
|
|
}
|
|
break;
|
|
case 13:
|
|
if( Serial.available() ) {
|
|
lastread = Serial.read();
|
|
|
|
ready = true;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
#if FREQ > 1
|
|
}
|
|
#endif //FREQ
|
|
}
|
|
|
|
|
|
char spi_transfer(volatile byte data)
|
|
{
|
|
SPDR = data; // Start the transmission
|
|
while (!(SPSR & (1<<SPIF))) // Wait the end of the transmission
|
|
{
|
|
};
|
|
return SPDR; // return the received byte
|
|
}
|
|
|
|
void makemagic(){
|
|
setGreys();
|
|
feedPorts();
|
|
}
|
|
|
|
void feedPorts() {
|
|
// Clock for TLC5940's PWM
|
|
digitalWrite(BLANK, HIGH);
|
|
digitalWrite(BLANK, LOW); //=all outputs ON, start PWM cycle
|
|
for (int i=0; i<4096; i++) {
|
|
pulseGSCLK();
|
|
}
|
|
}
|
|
|
|
void pulseGSCLK() {
|
|
//ultra fast pulse trick, using digitalWrite caused flickering
|
|
PORTD |= 0x80 ; // bring pin 7 high, but don't touch any of the other pins in PORTB
|
|
//16 nanosecs is the min pulse width for the 5940, but no pause seems needed here
|
|
PORTD &= 0x7F; // bring pin 7 low without touching the other pins in PORTB
|
|
}
|
|
|
|
void setGreys() {
|
|
digitalWrite(BLANK, HIGH);
|
|
digitalWrite(XLAT,LOW);
|
|
for(int i = 15; i>=0; i--){
|
|
spi_transfer( (level[2*i+1] & 0x0FF0) >> 4 );
|
|
spi_transfer( ((level[2*i+1] & 0xF) << 4) | ((level[2*i] & 0x0F00) >> 8) );
|
|
spi_transfer( level[2*i] & 0xFF);
|
|
}
|
|
digitalWrite(XLAT,HIGH);
|
|
digitalWrite(XLAT,LOW);
|
|
digitalWrite(BLANK, LOW);
|
|
}
|
|
|
|
void startup(){
|
|
for(byte x = 0; x < 16; ++x){
|
|
level[x] = 0;
|
|
makemagic();
|
|
}
|
|
|
|
}
|
|
|
|
void setup()
|
|
{
|
|
|
|
for (int i=0; i <= 5; i++){
|
|
pinMode(sensor[i], INPUT);
|
|
}
|
|
pinMode(VPRG, OUTPUT);
|
|
pinMode(SIN, OUTPUT);
|
|
pinMode(SCLK, OUTPUT);
|
|
pinMode(XLAT, OUTPUT);
|
|
pinMode(BLANK, OUTPUT);
|
|
pinMode(DCPRG, OUTPUT);
|
|
pinMode(GSCLK, OUTPUT);
|
|
pinMode(MISO, INPUT);
|
|
pinMode(SS,OUTPUT);
|
|
digitalWrite(SS,HIGH); //disable device
|
|
digitalWrite(SIN, LOW);
|
|
digitalWrite(SCLK, LOW);
|
|
digitalWrite(XLAT, LOW);
|
|
digitalWrite(VPRG, LOW);
|
|
digitalWrite(BLANK, HIGH);
|
|
digitalWrite(GSCLK, HIGH);
|
|
digitalWrite(DCPRG, LOW); // USE EEPROM DC register if LOW
|
|
|
|
/* Setup the timer interrupt
|
|
|
|
Settings for TCCR2B: (remember, interrupts occur every 255 cycles)
|
|
000 = Clock stopped
|
|
001 = No prescaling (16MHz)
|
|
010 = 1/8 (2MHz)
|
|
011 = 1/32 (500kHz)
|
|
100 = 1/64 (250kHz)
|
|
101 = 1/128 (125kHz)
|
|
110 = 1/256 (62.5khZ)
|
|
111 = 1/1024 (15.625kHz)
|
|
|
|
010 (2MHz) with FREQ set to 10 or less seem to work reasonably well
|
|
Trying to use 011 (500kHz), to eliminate the if statement needed for FREQ
|
|
Might even work as slow as 100 (250kHz).
|
|
*/
|
|
TCCR2A = 0;
|
|
TCCR2B = 0<<CS22 | 1<<CS21 | 1<<CS20;
|
|
|
|
//Timer2 Overflow Interrupt Enable
|
|
TIMSK2 = 1<<TOIE2;
|
|
|
|
//Setup the Hardware SPI registers
|
|
// SPCR = 01010000
|
|
//interrupt disabled,spi enabled,msb 1st,master,clk low when idle,
|
|
//sample on leading edge of clk,system clock/4 (fastest)
|
|
byte clr;
|
|
SPCR = (1<<SPE)|(1<<MSTR);
|
|
clr=SPSR;
|
|
clr=SPDR;
|
|
delay(10);
|
|
|
|
Serial.begin(BAUD);
|
|
Serial.println("Picasso");
|
|
|
|
// set the data rate for the NewSoftSerial port
|
|
mySerial.begin(BAUD_SOFT);
|
|
startup();
|
|
}
|
|
|
|
|
|
void loop()
|
|
{
|
|
makemagic();
|
|
|
|
/* REHACER!!!!
|
|
if (mySerial.available()) {
|
|
RFID_temp[count]=mySerial.read();
|
|
if (count == 16)
|
|
{
|
|
count=0;
|
|
if (RFID_temp[0]=0x02)
|
|
{
|
|
for (int i=0; i <= 11; i++) RFID[i]=RFID_temp[i+1];
|
|
Serial.print(RFID);
|
|
}
|
|
}
|
|
count++;
|
|
}
|
|
*/
|
|
|
|
for (int i=0; i <= 5; i++){
|
|
if (digitalRead(sensor[i]))
|
|
{
|
|
estado=(0x01<<i)|estado;
|
|
}
|
|
else
|
|
{
|
|
estado=(~(0x01<<i))&estado;
|
|
}
|
|
}
|
|
|
|
if (estado!=estado_ant)
|
|
{
|
|
//Serial.print(RFID);
|
|
//Serial.print(estado);
|
|
}
|
|
estado_ant=estado;
|
|
}
|