230 lines
7.7 KiB
C++
230 lines
7.7 KiB
C++
#include "TimerOne.h"
|
|
// Serial data transfer rate
|
|
#define BAUD 115200
|
|
|
|
//TLC5940NT pin definitions
|
|
#define VPRG 2
|
|
#define SIN 11 // MOSI - Hardware SPI, can't be changed
|
|
#define SCLK 13 // SCK - Hardware SPI, can't be changed
|
|
#define XLAT 4
|
|
#define BLANK 5
|
|
#define DCPRG 6
|
|
#define GSCLK 7
|
|
|
|
/* These pins are from the Hardware SPI, but aren't connected to the TLC5940
|
|
These definitions are only here for clarity, and aren't used. MISO can not
|
|
be used for anything else, while SS can be used for any OUTPUT. It can NOT
|
|
be used for an input. Currently, it is used for INCLOCKPIN, the 165's clock
|
|
pin setting.
|
|
*/
|
|
//#define MISO 12 //MISO - Hardware SPI, can't be changed (not connected, can't be used for anything other than MISO)
|
|
//#define SS 10 //SS - Hardware SPI, not used and therefore can be used for something else, but ONLY AS AN OUTPUT!!
|
|
|
|
// Pin definitions for the 74HC164 SIPO shift register (drives button rows high)
|
|
#define DATAPIN 16 // aka analog pin 2 (what, you didn't know that analog pins 0-5 are also digital pins 14-19? Well, now you do!)
|
|
#define CLOCKPIN 3
|
|
|
|
// Keyboard times
|
|
#define KEY_DEBOUNCE_TIME 100 // debounce time (ms) to prevent flickering when pressing or releasing the button
|
|
#define KEY_HOLD_TIME 400 // holding period (ms) how long to wait for press+hold event
|
|
|
|
/*This is the mapping of the physical position of the boards to the correct
|
|
output of the TLC5940s. The left halves are rotated to correspond to the
|
|
orientation of the boards*/
|
|
const byte remap[64] = {
|
|
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 15,
|
|
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
|
|
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
|
|
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 };
|
|
|
|
// Holds the current colour level for each of the buttons
|
|
int level[64] = {
|
|
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, 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, 0, 0, 0, 0};
|
|
|
|
byte puntos_local = 0;
|
|
byte puntos_visitante = 0;
|
|
byte sets_local = 0;
|
|
byte sets_visitante = 0;
|
|
|
|
const byte remap_puntos_local[16] = { 63, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0};
|
|
const byte remap_sets_local[4] = { 63, 32, 33, 34 };
|
|
const byte remap_puntos_visitante[16] = {63, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62};
|
|
const byte remap_sets_visitante[4] = { 63, 35, 36, 37 };
|
|
|
|
boolean flag_local = false;
|
|
boolean flag_visitante = false;
|
|
|
|
// 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.
|
|
*/
|
|
void timerIsr()
|
|
{
|
|
makemagic();
|
|
}
|
|
|
|
// Transfer a character out over hardware SPI
|
|
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
|
|
}
|
|
|
|
// Run this animation once at startup. Currently unfinished.
|
|
void startup(){
|
|
for(byte x = 0; x < 64; ++x){
|
|
level[remap[x]] = 4095;
|
|
}
|
|
}
|
|
|
|
void setup() {
|
|
//Setup data directions, and set everything to the correct initial levels,
|
|
// For TLC5940
|
|
DDRC |= B00100011; //Configuracion como pines de salida de los pines del puerto C
|
|
asm("cbi 0x08,5"); //pone a 0 el bit 5 del puerto C
|
|
|
|
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);
|
|
pinMode(17, INPUT);
|
|
pinMode(18, INPUT);
|
|
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
|
|
digitalWrite(17, HIGH);
|
|
digitalWrite(18, HIGH);
|
|
|
|
//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);
|
|
Timer1.initialize(4000); // set a timer of length 1000000 microseconds (or 1 sec - or 1Hz)
|
|
Timer1.attachInterrupt( timerIsr ); // attach the service routine here
|
|
|
|
// Start the serial port
|
|
Serial.begin(BAUD);
|
|
|
|
delay(10);
|
|
Serial.println("Reset!!");
|
|
//startup();
|
|
}
|
|
|
|
void loop () {
|
|
checkButtons();
|
|
}
|
|
|
|
void makemagic(){
|
|
setGreys();
|
|
feedPorts();
|
|
}
|
|
|
|
void setGreys() {
|
|
asm("sbi 0x0B,5"); //pone a 1 el bit 5 del puerto D (BLANK)
|
|
asm("cbi 0x0B,4"); //pone a 0 el bit 4 del puerto D (XLAT)
|
|
for(int i = 31; 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);
|
|
}
|
|
asm("sbi 0x0B,4"); //pone a 1 el bit 4 del puerto D (XLAT)
|
|
asm("cbi 0x0B,4"); //pone a 0 el bit 4 del puerto D (XLAT)
|
|
asm("cbi 0x0B,5"); //pone a 0 el bit 5 del puerto D (BLANK)
|
|
}
|
|
|
|
void feedPorts() {
|
|
// Clock for TLC5940's PWM
|
|
asm("sbi 0x0B,5"); //pone a 1 el bit 5 del puerto D (BLANK)
|
|
asm("cbi 0x0B,5"); //pone a 0 el bit 5 del puerto D (BLANK)
|
|
for (int i=0; i<4096; i++) {
|
|
asm("sbi 0x0B,7"); //pone a 1 el bit 1 del puerto D (GSCLK)
|
|
asm("cbi 0x0B,7"); //pone a 0 el bit 1 del puerto D (GSCLK)
|
|
}
|
|
}
|
|
|
|
void checkButtons(){
|
|
|
|
if ((!digitalRead(18))&&(!flag_local))
|
|
{
|
|
flag_local=true;
|
|
if ((sets_local>2)||(sets_visitante>2))
|
|
{
|
|
sets_local = 0;
|
|
sets_visitante = 0;
|
|
puntos_visitante = 0;
|
|
puntos_local = 0;
|
|
for (int i=0; i<16; i++) level[remap_sets_local[i]] = 0;
|
|
for (int i=0; i<4; i++) level[remap_sets_visitante[i]] = 0;
|
|
for (int i=0; i<16; i++) level[remap_puntos_visitante[i]] = 0;
|
|
for (int i=0; i<16; i++) level[remap_puntos_local[i]] = 0;
|
|
}
|
|
puntos_local++;
|
|
if (puntos_local>15)
|
|
{
|
|
puntos_local = 0;
|
|
puntos_visitante = 0;
|
|
for (int i=0; i<16; i++) level[remap_puntos_local[i]] = 0;
|
|
for (int i=0; i<16; i++) level[remap_puntos_visitante[i]] = 0;
|
|
sets_local++;
|
|
}
|
|
level[remap_puntos_local[puntos_local]] = 4095;
|
|
level[remap_sets_local[sets_local]] = 4095;
|
|
delay(100);
|
|
} if ((digitalRead(18))&&(flag_local)) flag_local=false;
|
|
|
|
if ((!digitalRead(17))&&(!flag_visitante))
|
|
{
|
|
flag_visitante=true;
|
|
if ((sets_local>2)||(sets_visitante>2))
|
|
{
|
|
sets_visitante = 0;
|
|
sets_local = 0;
|
|
puntos_local = 0;
|
|
puntos_visitante = 0;
|
|
for (int i=0; i<16; i++) level[remap_sets_visitante[i]] = 0;
|
|
for (int i=0; i<4; i++) level[remap_sets_local[i]] = 0;
|
|
for (int i=0; i<16; i++) level[remap_puntos_local[i]] = 0;
|
|
for (int i=0; i<16; i++) level[remap_puntos_visitante[i]] = 0;
|
|
}
|
|
puntos_visitante++;
|
|
if (puntos_visitante>15)
|
|
{
|
|
puntos_visitante = 0;
|
|
puntos_local = 0;
|
|
for (int i=0; i<16; i++) level[remap_puntos_visitante[i]] = 0;
|
|
for (int i=0; i<16; i++) level[remap_puntos_local[i]] = 0;
|
|
sets_visitante++;
|
|
}
|
|
level[remap_puntos_visitante[puntos_visitante]] = 4095;
|
|
level[remap_sets_visitante[sets_visitante]] = 4095;
|
|
delay(100);
|
|
} if ((digitalRead(17))&&(flag_visitante)) flag_visitante=false;
|
|
}
|
|
|
|
//boolean flag_local = false;
|
|
//boolean flag_visitante = false;
|