289 lines
7.3 KiB
Plaintext
289 lines
7.3 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 57600
|
|
#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[13] = "";
|
|
|
|
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
|
|
|
|
//makemagic();
|
|
//makemagic();
|
|
//makemagic();
|
|
|
|
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;
|
|
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);
|
|
|
|
// set the data rate for the NewSoftSerial port
|
|
mySerial.begin(BAUD_SOFT);
|
|
startup();
|
|
|
|
}
|
|
|
|
|
|
void loop()
|
|
{
|
|
|
|
makemagic();
|
|
|
|
if( rfid_read() )
|
|
Serial.print(RFID);
|
|
|
|
for (int i=0 ; i<5 ; i++){ // limite a tres botones + 1 final de carrera (valor max estado = 31)
|
|
if (digitalRead(sensor[i]))
|
|
estado = (0x01<<i) | estado;
|
|
else
|
|
estado = (~(0x01<<i)) & estado;
|
|
}
|
|
|
|
if (estado != estado_ant)
|
|
{
|
|
Serial.print(estado);
|
|
estado_ant = estado;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
byte rfid_read()
|
|
{
|
|
|
|
byte i = 0;
|
|
byte val = 0;
|
|
byte code[6];
|
|
byte checksum = 0;
|
|
byte bytesread = 0;
|
|
byte tempbyte = 0;
|
|
byte check = 0;
|
|
|
|
if(mySerial.available() > 0) {
|
|
if((val = mySerial.read()) == 2) { // check for header
|
|
bytesread = 0;
|
|
while (bytesread < 12) { // read 10 digit code + 2 digit checksum
|
|
if( mySerial.available() > 0) {
|
|
val = mySerial.read();
|
|
if((val == 0x0D)||(val == 0x0A)||(val == 0x03)||(val == 0x02)) { // if header or stop bytes before the 10 digit reading
|
|
break; // stop reading
|
|
}
|
|
|
|
RFID[bytesread] = val;
|
|
//makemagic();
|
|
/*
|
|
// Do Ascii/Hex conversion:
|
|
if ((val >= '0') && (val <= '9')) {
|
|
val = val - '0';
|
|
} else if ((val >= 'A') && (val <= 'F')) {
|
|
val = 10 + val - 'A';
|
|
}
|
|
|
|
// Every two hex-digits, add byte to code:
|
|
if (bytesread & 1 == 1) {
|
|
// make some space for this hex-digit by
|
|
// shifting the previous hex-digit with 4 bits to the left:
|
|
code[bytesread >> 1] = (val | (tempbyte << 4));
|
|
|
|
if (bytesread >> 1 != 5) { // If we're at the checksum byte,
|
|
checksum ^= code[bytesread >> 1]; // Calculate the checksum... (XOR)
|
|
};
|
|
} else {
|
|
tempbyte = val; // Store the first hex digit first...
|
|
};
|
|
*/
|
|
|
|
bytesread++; // ready to read next digit
|
|
|
|
}
|
|
}
|
|
|
|
// Output to Serial:
|
|
|
|
if (bytesread == 12) { // if 12 digit read is complete
|
|
check = 1;
|
|
bytesread = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
return(check);
|
|
|
|
}
|
|
|