forked from sker65/pinball-lw3
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSwitchScanner.cpp
124 lines (103 loc) · 2.87 KB
/
SwitchScanner.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/*
* SwitchScanner.cpp
*
* Created on: 04.09.2015
* Author: sr
*/
#include "SwitchScanner.h"
#include <TimerOne.h>
#include <FastLED.h>
SwitchScanner::SwitchScanner(uint32_t delay) {
pin = 0x80;
switchChanged = false;
colChanged = false;
col = 0;
rowIndex=0;
handlerIndex = 0;
led = false;
this->delay =delay;
nextPeriodic = 0L;
}
void SwitchScanner::registerSwitchAction(int col, int row, SwitchAction* action, Trigger t /* = EDGE*/) {
handlers[handlerIndex].action = action;
handlers[handlerIndex].col = col;
handlers[handlerIndex].row = row;
handlers[handlerIndex].rowMask = (1 << row);
handlers[handlerIndex].trigger = t;
if( handlerIndex < MAX_HANDLERS ) handlerIndex++;
}
// this will called as interrupt routine triggered by timer 1
void SwitchScanner::readSwitches() {
// row index for row to compare
int row = rowIndex==1?0:1;
// generate rect wave just to control timing with logic analyser
pin = ~pin;
PORTC = pin;
// read row return
rows[rowIndex][col] = PINA; // for mega this will be PIN 22 - 29
// compare this row with the row read last time
if( rows[rowIndex][col] != rows[row][col] ) {
colChanged = true;
}
// we read col 0 to 6
if (++col == LAST_COL_TO_READ) {
col = 0;
Timer1.stop();
// update from with (or at end) of interrupt
FastLED.show();
rowIndex = row;
if( colChanged ) switchChanged =true;
colChanged = false;
}
}
SwitchScanner::~SwitchScanner() {
}
void SwitchScanner::update(uint32_t now) {
if( now > nextPeriodic ) {
nextPeriodic = now + delay;
for (int h = 0; h < handlerIndex; h++) {
if (handlers[h].trigger == PERIODIC ) {
bool active = (rows[rowIndex][handlers[h].col] & handlers[h].rowMask) == LOW;
handlers[h].action->onSwitchUpdate(active, handlers[h].col*100+handlers[h].row);
}
}
}
if (switchChanged) {
int nrow = rowIndex == 1 ? 0 : 1;
// scan handlers
for (int h = 0; h < handlerIndex; h++) {
if (handlers[h].trigger == EDGE) {
// Serial.println("edge handler found");
int col = handlers[h].col;
if ((rows[nrow][col] & handlers[h].rowMask)
!= (rows[rowIndex][col] & handlers[h].rowMask)) {
Serial.print("handler fired col="); Serial.println(col);
bool active = (rows[rowIndex][col] & handlers[h].rowMask) == LOW;
handlers[h].action->onSwitchUpdate(!active,handlers[h].col*100+handlers[h].row);
}
}
}
// flash led just to show switch change was recognized
led = ~led;
digitalWrite(13, led);
// dump switches to serial
dump();
switchChanged = false;
}
}
void SwitchScanner::dump() {
Serial.println(" 7 6 5 4 3 2 1 0");
for (int col = 0; col < LAST_COL_TO_READ; col++) {
Serial.print(col);
printbin(rows[rowIndex][col]);
}
}
/**
* used for printing switch matrix to serial
*/
void SwitchScanner::printbin(byte bin) {
for (byte mask = 0x80; mask; mask >>= 1) {
Serial.print(mask & bin ? " ." : " *");
}
Serial.println();
}