/*
How to Use 74HC165 Shift register as serial Asyn input 6 bit
8 shift per: Idle1-Start0-d0d1d2d3d4d5-Stop1
Versione UART TX-RX */
const int dataPin = 2; /* Q7 */
const int CP = 5; /* CP */
const int PL = 4; /* PL */
const int Start = 3; /* start Read */
//
const int numBit = 6; /* numero data bit */
const int numShift = 9; /* 8+1 shift: idle1-Start0-d0d1d2d3d4-Stop1 */
volatile uint32_t m0, m1, T, bounce;
volatile uint8_t rby;
volatile int8_t shift_count, bit_count;
#define BAUD 104
#define RECV_OK -1
#define FERR -2
void setup() {
Serial.begin(9600);
pinMode(Start, INPUT_PULLUP);
pinMode(CP, OUTPUT);
pinMode(PL, OUTPUT);
digitalWrite(CP, HIGH);
digitalWrite(PL, HIGH);
shift_count = bit_count = rby = bounce = 0;
load_SR();
//attachInterrupt(digitalPinToInterrupt(Start), StartBit, FALLING);
//attachInterrupt(digitalPinToInterrupt(dataPin), StartRec, FALLING);
}
void loop() {
if (shift_count) shifter(); else check_bounce();
if (bit_count > 0) serialin();
else if (bit_count < 0) {
if (bit_count == RECV_OK) Serial.println(rby, BIN);
else if (bit_count == FERR) Serial.println("Framing Error");
bit_count = 0;
}
}
void load_SR() {
digitalWrite(PL, HIGH); // Per sicurezza - Flash di cattura
digitalWrite(PL, LOW); // Durata minima impulso (/PL):
digitalWrite(PL, HIGH); // da 20 a 120 nS
}
void shifter() {
uint32_t mx = millis();
if ((mx - m0) > BAUD) {
m0 += BAUD;
digitalWrite(CP, LOW); // Per sicurezza Shift avviene da L --> H
digitalWrite(CP, HIGH); // Durata minima impulso (CP):
digitalWrite(CP, LOW); // da 20 a 120 nS
shift_count--;
//if (shift_count == 0) attachInterrupt(digitalPinToInterrupt(Start), StartBit, FALLING);
}
}
void serialin() {
uint32_t mx = millis();
if ((mx - m1) > T) {
if (bit_count > numBit) { // Siamo al bit di stop
if (digitalRead(dataPin)) bit_count = RECV_OK; else bit_count = FERR;
attachInterrupt(digitalPinToInterrupt(dataPin), StartRec, FALLING);
} else {
rby >>= 1;
if (digitalRead(dataPin)) rby |= 0x80;
T = BAUD;
m1 += T;
bit_count++; // sempre allo stato RUN (count > 0)
}
}
}
void StartBit() {
m0 = millis();
load_SR();
shift_count = numShift;
detachInterrupt(digitalPinToInterrupt(Start)); //disabilita l'interupt fino al termine della trasmissione
}
void StartRec() {
m1 = millis();
T = BAUD + BAUD / 2;
bit_count = 1;
rby = 0;
detachInterrupt(digitalPinToInterrupt(dataPin));
}
void check_bounce(){
uint32_t mx = millis();
if((mx-bounce) > 400){
attachInterrupt(digitalPinToInterrupt(Start), StartBit, FALLING);
bounce += 400;
}
}