//
// COMPILE TIME CONSTANTS
//
#define ENC_CLK 0
#define ENC_DT 1
#define ENC_BUTN 2
#define DIS_REG_DATA 3
#define DIS_REG_CLOCK 4
#define DIS_REG_LATCH 5
#define DIG_REG_DATA 8
#define DIG_REG_CLOCK 9
#define DIG_REG_LATCH 10
//
// TYPES
//
typedef struct
{ int LAST_CLOCK, CLOCK, DT, BUTTON; }
ENCODER;
typedef struct
{ int data_pin, clock_pin, latch_pin; }
REGISTER;
typedef struct
{ byte memcell[7]; }
ledSymbol;
typedef struct
{
REGISTER display;
REGISTER digit_socket;
bool flush_call;
int current_dig;
}
FOUR_LED;
enum Rotor
{
None = 0,
TurnRight = 1,
TurnLeft = 2,
ButtonPress = 3
};
// BOILERPLATE
void setup() {
//Serial.begin(9600);
Serial.begin(115200);
pinMode(ENC_CLK, INPUT);
pinMode(ENC_DT, INPUT);
pinMode(ENC_BUTN, INPUT_PULLUP);
pinMode(DIS_REG_DATA, OUTPUT);
pinMode(DIS_REG_CLOCK, OUTPUT);
pinMode(DIS_REG_LATCH, OUTPUT);
pinMode(DIG_REG_DATA, OUTPUT);
pinMode(DIG_REG_CLOCK, OUTPUT);
pinMode(DIG_REG_LATCH, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
}
//
// REGISTER API
//
void registerClearCell(int dataPin,int clockPin)
{
digitalWrite(dataPin, LOW);
digitalWrite(clockPin, HIGH);
digitalWrite(clockPin, LOW);
}
void registerFlashCell(int dataPin,int clockPin)
{
digitalWrite(dataPin, HIGH);
digitalWrite(clockPin, HIGH);
digitalWrite(clockPin, LOW);
}
void registerClear(int dataPin,int clockPin)
{
for(int i = 0; i < 8; i++)
{
registerClearCell(dataPin,clockPin);
}
}
void registerBeginRead(int latchPin)
{
digitalWrite(latchPin,LOW);
}
void registerFlush(int latchPin)
{
digitalWrite(latchPin, HIGH);
}
// 00000001
// 00000000
void registerOut(REGISTER reg,byte seq[8])
{
registerBeginRead(reg.latch_pin);
//registerClear(reg.data_pin,reg.clock_pin);
for(int i = 0; i < 8; i++)
{
if(seq[i])
registerFlashCell(reg.data_pin,reg.clock_pin);
else
registerClearCell(reg.data_pin,reg.clock_pin);
}
registerFlush(reg.latch_pin);
}
void registerOutForce(REGISTER reg,byte seq[8])
{
registerBeginRead(reg.latch_pin);
registerClear(reg.data_pin,reg.clock_pin);
for(int i = 0; i < 8; i++)
{
if(seq[i])
registerFlashCell(reg.data_pin,reg.clock_pin);
else
registerClearCell(reg.data_pin,reg.clock_pin);
}
registerFlush(reg.latch_pin);
}
REGISTER initRegister(int dataPin, int clockPin, int latchPin)
{
REGISTER reg = {dataPin,clockPin,latchPin};
return reg;
}
//
// ENCODER API
//
ENCODER initEncoder(int clock_pin, int dt_pin, int button_pin)
{
return (ENCODER)
{
.LAST_CLOCK = HIGH,
.CLOCK = clock_pin,
.DT = dt_pin,
.BUTTON = button_pin
};
}
inline void getEncoderInputBinary(ENCODER *p,char* byte_value)
{
int MSB = digitalRead(p->CLOCK);
int LSB = digitalRead(p->DT);
int encoded = (MSB << 1) | LSB;
int sum = (p->LAST_CLOCK << 2) | encoded;
if (sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) {
(*byte_value) = TurnRight;
} else if (sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) {
(*byte_value) = TurnLeft;
}
else
(*byte_value) = None;
p->LAST_CLOCK = encoded;
delay(5); // BULLSHIT
}
int getEncoderInput(ENCODER *p)
{
static int read;
int Btn = digitalRead(p->BUTTON);
int Clk = digitalRead(p->CLOCK);
if (p->LAST_CLOCK != Clk)
{
p->LAST_CLOCK = Clk;
int Dt = digitalRead(p->DT);
if (Clk == LOW && Dt == HIGH)
return TurnRight;
else
{
return TurnLeft;
}
}
else if (Btn == LOW)
return ButtonPress;
else
return None;
}
//
// DISPLAY API
//
FOUR_LED initLed(REGISTER num, REGISTER sock)
{
return (FOUR_LED)
{ num, sock };
}
ledSymbol symbol_from_bytes(byte seq[7])
{
ledSymbol s;
for(int i = 0; i < 7; i++)
s.memcell[i] = seq[i];
return s;
}
inline void clearAll (FOUR_LED dest)
{
byte out[8];
const short BYTE_SIZE = 8;
for(int i = 0; i < BYTE_SIZE; i++)
out[(BYTE_SIZE-1)-i] = 0;
registerOut(dest.digit_socket,out);
}
int drawBinaryImage(FOUR_LED dest,ledSymbol img,short dig_socket)
{
const short UNUSED = 0;
const short BYTE_SIZE = 8;
//byte debug[8] = {1,0,0,0,0,0,0,0};
byte out[BYTE_SIZE];
byte digit_socket[BYTE_SIZE] = {0,0,0,0,0,0,0,0};
out[0] = UNUSED;
for(int i = 0; i < BYTE_SIZE-1; i++)
out[(BYTE_SIZE-1)-i] = (img.memcell[i] == 1) ? 0 : 1;
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// for some reason i have to swap bytes for display
// to work as expected :\
digit_socket[(BYTE_SIZE/2)+dig_socket] = 1;
registerOut(dest.display,out);
registerOut(dest.digit_socket,digit_socket);
}
int drawImage(FOUR_LED targ, ledSymbol number[4], short number_size, short FPS)
{
for(int i = 0; i < number_size; i++)
{
clearAll(targ);
drawBinaryImage(targ,number[i],i);
}
delay(1000 / FPS);
clearAll(targ);
}
//
// QOL
//
int digc(int number)
{
int digc=0;
while(number > 0)
{
digc++;
number /= 10;
}
return digc;
}
int getdig(int number,int offset)
{
int dig = -1;
for(int i = 0; i < offset; i++) {
dig = number % 10;
number /= 10;
}
return dig;
}
int constructLedVec4(int n,byte rnums[10][7], ledSymbol(*p)[4], short* size)
{
(*size) = abs(digc(n));
if((*size) > 4)
(*size) = 1;
for(int i = 0; i < 3; i++)
{
p[0][i] = symbol_from_bytes(rnums[getdig(n,i+1)]);
}
}
// idk :\
byte RAW_NUMBERS[10][7] = {
{1,1,1,1,1,1,0},//0
{0,1,1,0,0,0,0},
{1,1,0,1,1,0,1},
{1,1,1,1,0,0,1},
{0,1,1,0,0,1,1},
{1,0,1,1,0,1,1},//5
{1,0,1,1,1,1,1},
{1,1,1,0,0,0,0},
{1,1,1,1,1,1,1},
{1,1,1,1,0,1,1}
};
//
//
// ALL CONNECTED INTERFACES
//
//
ENCODER encod =
initEncoder(ENC_CLK,
ENC_DT,
ENC_BUTN);
REGISTER display_symbol =
initRegister(DIS_REG_DATA,
DIS_REG_CLOCK,
DIS_REG_LATCH);
REGISTER display_socket =
initRegister(DIG_REG_DATA,
DIG_REG_CLOCK,
DIG_REG_LATCH);
FOUR_LED ledis = initLed(display_symbol,display_socket);
ledSymbol numbers[10];
//
// RELATED TO MAIN LOOP
//
bool once = true;
int counter = 1;
char* encoder_state;
ledSymbol numer[4]; // DEF
short numer_size = 1; // DEF
void loop(void)
{
if(once) // RUN ONCE
{
//
// COMPILE NUMBERS TO PASSABLE STUCTURE ARRAY
//
for(int i = 0; i < 10; i++)
numbers[i] = symbol_from_bytes(RAW_NUMBERS[i]);
Serial.println("ran once.");
once=(!once);
}
// BATCH RENDERING
// USED ledSymbol array to DRAW ON LED SCREEN
drawImage(ledis,
numer,
numer_size,
18);
//
// READ ENCODER INPUT
//
// THIS S*IT DOES NOT WORK UNDER HEAVY LOAD !!!!
//getEncoderInputBinary(&encod,encoder_state);
int input = getEncoderInput (&encod);
//if(*encoder_state==TurnRight)
// counter++;
//else if (*encoder_state==TurnLeft)
// counter--;
if (input == ButtonPress)
counter++;
// CONVERT int INTO ledSymbol Array //
constructLedVec4(abs(counter), RAW_NUMBERS, &numer, &numer_size);
}