/*
MIT License
Copyright (c) 2022 MicroBeaut
*/
#include "MicroBeaut.h"
typedef struct {
bool StateLock = false;
bool AutoRelease = false;
int Index = 0;
int Value = 0;
int Length = 0;
} ObjectState;
const int ledPins [] = {2, 3, 4, 5, 6, 7, 8, 9};
MicroBeaut_Lock<int, ObjectState> lock;
int lockObject1; // Input ObjectState
ObjectState stateObject1; // Input/Output ObgjectState
int lockObject2; // Input ObjectState
ObjectState stateObject2; // Input/Output ObjectState
int lockObject3; // Input ObjectState
ObjectState stateObject3; // Input/Output ObjectState
int lockObject4; // Input ObjectState
ObjectState stateObject4; // Input/Output ObjectState
const int dataObject1[] = {0x00, 0x01, 0x02, 0x04, 0x08, 0x08, 0x10, 0x20, 0x40, 0x80, 0x80};
const int dataObject2[] = {0x00, 0x81, 0x42, 0x24, 0x18, 0x24, 0x42, 0x81, 0x81};
const int dataObject3[] = {0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xFF};
const int dataObject4[] = {0x00, 0xF0, 0xF0, 0x00, 0x0F, 0xF0, 0xF0};
bool ledBuiltinState = false;
bool prevStateLock = false;
// Function Declaration
void DoSomething(int* lockObject, ObjectState* stateObject);
void ReportLock(int lockObject);
void ReportAutoRelease(int lockObject);
void ReportManualRelease(int lockObject);
void ReportDoSomething(int lockObject, ObjectState* stateObject);
void SetLEDValue(int value);
String DecToHex(int value, int numDigit = 2);
// Timer 3 Interrupt => Reload = 0.25 Second.
ISR(TIMER3_COMPA_vect) {
lockObject1 = 1;
if (!lock) { // Check Lock State
lock.Lock(&lockObject1, &stateObject1.StateLock); // Lock Object
ReportLock(lockObject1);
}
if (lock == lockObject1) {
prevStateLock = &stateObject1.StateLock;
stateObject1.Value = dataObject1[stateObject1.Index];
bool runCompleted = lock.Run(DoSomething, &lockObject1, &stateObject1, &stateObject1.StateLock,stateObject1.AutoRelease);
if (stateObject1.AutoRelease && !stateObject1.StateLock && prevStateLock) {
ReportAutoRelease(lockObject1);
}
}
}
// Timer 4 Interrupt => Reload = 0.50 Second.
ISR(TIMER4_COMPA_vect) {
lockObject2 = 2;
if (!lock) { // Check Lock State
lock.Lock(&lockObject2); // Lock Object
ReportLock(lockObject2);
}
stateObject2.Value = dataObject2[stateObject2.Index];
lock.Run(DoSomething, &lockObject2, &stateObject2, &stateObject2.StateLock, stateObject2.AutoRelease);
}
// Timer 5 Interrupt => Reload = 1.00 Second.
ISR(TIMER5_COMPA_vect) {
lockObject3 = 3;
if (!lock) { // Check Lock State
lock.Lock(&lockObject3); // Lock Object
ReportLock(lockObject3);
}
stateObject3.Value = dataObject3[stateObject3.Index];
lock.Run(DoSomething, &lockObject3, &stateObject3, &stateObject3.StateLock);
}
void setup() {
Serial.begin(115200);
for (int index = 0; index < 8; index++) {
pinMode(ledPins[index], OUTPUT);
}
pinMode(LED_BUILTIN, OUTPUT);
stateObject1.Length = sizeof(dataObject1)/sizeof(int);
stateObject2.Length = sizeof(dataObject2)/sizeof(int);
stateObject3.Length = sizeof(dataObject3)/sizeof(int);
stateObject4.Length = sizeof(dataObject4)/sizeof(int);
stateObject1.AutoRelease = true;
cli(); // Global Interrupt Disable
// TODO: Timer 3 Configuration
TCCR3A = 0; // Normal Oparation
TCCR3B = 0; // Initial
OCR3A = 0x0F42; // Reload = 0.25 Second.
TCCR3B = (1 << WGM32) | (1 << CS32) | (1 << CS30); // Clear Timer on Compare Match (WGMx 2:0 = 0x04) + Prescale 1024 (CSx 2:0 = 0x02)
TIMSK3 = (1 << OCIE3A); // Output Compare A Match Interrupt Enable
// TODO: Timer 4 Configuration
TCCR4A = 0; // Normal Oparation
TCCR4B = 0; // Initial
OCR4A = 0x1E84; // Reload = 0.5 Second.
TCCR4B = (1 << WGM42) | (1 << CS42) | (1 << CS40); // Clear Timer on Compare Match (WGMx 2:0 = 0x04) + Prescale 1024 (CSx 2:0 = 0x02))
TIMSK4 = (1 << OCIE4A); // Output Compare A Match Interrupt Enable
// TODO: Timer 5 Configuration
TCCR5A = 0; // Normal Oparation
TCCR5B = 0; // Initial
OCR5A = 0x3D08; // Reload = 1 Second.
TCCR5B = (1 << WGM52) | (1 << CS52) | (1 << CS50); // Clear Timer on Compare Match (WGMx 2:0 = 0x04) + Prescale 1024 (CSx 2:0 = 0x02))
TIMSK5 = (1 << OCIE5A); // Output Compare A Match Interrupt Enable
sei(); // // Global Interrupt Enable
}
void loop() {
digitalWrite(LED_BUILTIN, ledBuiltinState);
lockObject4 = 4;
if (!lock) { // Check Lock State
lock.Lock(&lockObject4); // Lock Object
ReportLock(lockObject4);
}
stateObject4.Value = dataObject4[stateObject4.Index];
lock.Run(DoSomething, &lockObject4, &stateObject4, &stateObject4.StateLock, false);
ledBuiltinState = !ledBuiltinState;
delay(500);
}
void DoSomething(int* lockObject, ObjectState* stateObject ) {
SetLEDValue(stateObject->Value); // Send value to LED
ReportDoSomething(*lockObject, stateObject ); // Report Object (n) DoSomthing
stateObject->Index++; // Increase IO-ObjectState Value
prevStateLock = stateObject->StateLock; // Save last value
if (stateObject->Index >= stateObject->Length) {
lock.Release(lockObject, &stateObject->StateLock); // Release ObjectState
stateObject->Index = 0; // Reset Index of OUT-ObjectState
}
if (stateObject->AutoRelease == false && !stateObject->StateLock && prevStateLock) { // Compare current StateLock state with previous state
ReportManualRelease(*lockObject); // Report Manual Release
}
}
void SetLEDValue(int value) {
for (int index = 0; index < 8; index++) {
digitalWrite(ledPins[index], (value >> index) & 0x01);
}
}
void ReportLock(int lockObject) {
Serial.print("\n******** Lock by Object ");
Serial.print(lockObject);
Serial.println(" ********");
}
void ReportAutoRelease(int lockObject) {
Serial.print("******** Auto Release Object ");
Serial.print(lockObject);
Serial.println(" ********");
}
void ReportManualRelease(int lockObject) {
Serial.print("******** Manual Release Object ");
Serial.print(lockObject);
Serial.println(" ********");
}
void ReportDoSomething(int lockObject, ObjectState* stateObject ) {
Serial.print("Object:=");
Serial.print(lockObject);
Serial.print(" ==> DoSomthing");
Serial.print(" Index:=");
Serial.print(stateObject->Index);
Serial.print(" Value:=");
Serial.println(DecToHex(stateObject->Value));
}
String DecToHex(int value, int numDigit) {
String retrunString = "";
for (int index = 0; index < numDigit ; index++) {
retrunString = String(value >> (4 * index) & 0x0F, HEX) + retrunString;
}
retrunString.toUpperCase();
retrunString = "0x" + retrunString;
return retrunString;
}