////////////////////////////////////////////////////////////////////////////////////////////////////
/*
Based on
https://github.com/TimMJN/Arduino-Clock-Divider
*/
////////////////////////////////////////////////////////////////////////////////////////////////////
// pin definitions
#define CLOCK_PIN 2
#define RANDOM_PIN 3
#define INT_CLOCK_PIN 12
#define INT_CLOCK_RATE_PIN A4
#define SER_CLOCK_PIN A0
#define SER_DATA_PIN A1
#define SER_LATCH_PIN A2
// outputs
#define N_OUTS 8 // number of outputs
// divisions
byte division[N_OUTS] = {1, 2, 3, 4, 8, 12, 16, 32}; // initial (startup) divisions
//byte division[N_OUTS] = {1, 2, 4, 8, 16, 32, 64, 128}; // initial (startup) divisions
//byte division[N_OUTS] = {1, 2, 3, 5, 7, 8, 12, 32}; // initial (startup) divisions
byte counter[N_OUTS] = {0, 0, 0, 0, 0, 0, 0, 0}; // clock pulse counters
int int_clock_rate = 100;
////////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
// pinModes
pinMode(CLOCK_PIN, INPUT);
pinMode(INT_CLOCK_RATE_PIN, INPUT);
pinMode(INT_CLOCK_PIN, OUTPUT);
pinMode(RANDOM_PIN, OUTPUT);
pinMode(SER_DATA_PIN, OUTPUT);
pinMode(SER_CLOCK_PIN, OUTPUT);
pinMode(SER_LATCH_PIN, OUTPUT);
// output shift register
digitalWrite(SER_LATCH_PIN, LOW);
set_outputs_low(); // set all outputs low
digitalWrite(SER_LATCH_PIN, HIGH);
set_outputs_next(); // prepare for next pulse
// set-up interrups
attachInterrupt(digitalPinToInterrupt(CLOCK_PIN), clock_isr, CHANGE);
interrupts();
randomSeed(analogRead(INT_CLOCK_RATE_PIN));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void loop() {
//bool div_changed = false; // has any division changed this loop?
// if any division has changed and we're in between clock pulses, update the shift register
// if (div_changed && digitalRead(CLOCK_PIN))
// set_outputs_next();
int_clock_rate = map(analogRead(INT_CLOCK_RATE_PIN),0,255,25,500);
digitalWrite(INT_CLOCK_PIN, HIGH);
delay(int_clock_rate);
digitalWrite(INT_CLOCK_PIN, LOW);
delay(int_clock_rate);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// interrupt routine
// push the shift register to the outputs, update counters and update shift register
void clock_isr() {
// push to output register (pulse latch pin)
digitalWrite(SER_LATCH_PIN, HIGH);
digitalWrite(SER_LATCH_PIN, LOW);
if (digitalRead(CLOCK_PIN)) {
set_outputs_next();
}
else {
set_outputs_low();
// increment counters
for (int i = 0; i < N_OUTS; i++) {
counter[i]++;
counter[i] %= division[i];
}
digitalWrite(RANDOM_PIN,LOW);
digitalWrite(RANDOM_PIN,random(2));
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// set all outputs low on the shift register
void set_outputs_low() {
noInterrupts(); // do not interrupt writing to the shift register
digitalWrite(SER_DATA_PIN, LOW); // set output low
for (int i = (N_OUTS-1); i >= 0; i--) {
digitalWrite(SER_CLOCK_PIN, HIGH); // give clock pin a pulse
digitalWrite(SER_CLOCK_PIN, LOW);
}
interrupts(); // re-enable interrupts
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// set the shift register in anticipation of the next clock pulse
void set_outputs_next() {
noInterrupts(); // do not interrupt writing to the shift register
// loop over the outputs
for (int i = (N_OUTS-1); i >= 0; i--) {
if (counter[i] == 0) // check the counter value
digitalWrite(SER_DATA_PIN, HIGH); // set output high
else
digitalWrite(SER_DATA_PIN, LOW); // set output low
digitalWrite(SER_CLOCK_PIN, HIGH); // give clock pin a pulse
digitalWrite(SER_CLOCK_PIN, LOW);
}
interrupts(); // re-enable interrupts
}