Lab_interaccio/2014/sck_beta_v0_9/SCKBase.cpp
2025-02-25 21:29:42 +01:00

892 lines
23 KiB
C++

/*
SCKBase.cpp
Supports core and data management functions (Power, WiFi, SD storage, RTClock and EEPROM storage)
- Modules supported:
- WIFI (Microchip RN131 (WiFly))
- RTC (DS1339U and DS1307Z)
- EEPROM (24LC256)
- POWER MANAGEMENT IC's
*/
#include "Constants.h"
#include "SCKBase.h"
#include <Wire.h>
#include <EEPROM.h>
#define debugBASE false
void SCKBase::begin() {
Wire.begin();
TWBR = ((F_CPU / TWI_FREQ) - 16) / 2;
Serial.begin(115200);
Serial1.begin(9600);
pinMode(IO0, OUTPUT); //VH_MICS5525
pinMode(IO1, OUTPUT); //VH_MICS2710
pinMode(IO2, OUTPUT); //MICS2710_HIGH_IMPEDANCE
pinMode(AWAKE, OUTPUT);
pinMode(MOSI, OUTPUT);
pinMode(SCK, OUTPUT);
pinMode(FACTORY, OUTPUT);
pinMode(CONTROL, INPUT);
digitalWrite(AWAKE, LOW);
digitalWrite(FACTORY, LOW);
}
void SCKBase::config(){
if (!compareData(__TIME__, readData(EE_ADDR_TIME_VERSION, 0, INTERNAL)))
{
digitalWrite(AWAKE, HIGH);
for(uint16_t i=0; i<(DEFAULT_ADDR_ANTENNA + 160); i++) EEPROM.write(i, 0x00); // Memory erasing
writeData(EE_ADDR_TIME_VERSION, 0, __TIME__, INTERNAL);
writeData(EE_ADDR_SENSOR_MODE, DEFAULT_MODE_SENSOR, INTERNAL);
writeData(EE_ADDR_TIME_UPDATE, DEFAULT_TIME_UPDATE, INTERNAL);
writeData(EE_ADDR_NUMBER_UPDATES, DEFAULT_MIN_UPDATES, INTERNAL);
writeData(EE_ADDR_MAC, 0, MAC(), INTERNAL);
#if (networks > 0)
for(byte i=0; i<networks; i++)
{
writeData(DEFAULT_ADDR_SSID, i, mySSID[i], INTERNAL);
writeData(DEFAULT_ADDR_PASS, i, myPassword[i], INTERNAL);
writeData(DEFAULT_ADDR_AUTH, i, wifiEncript[i], INTERNAL);
writeData(DEFAULT_ADDR_ANTENNA, i, antennaExt[i], INTERNAL);
}
writeData(EE_ADDR_NUMBER_NETS, networks, INTERNAL);
#endif
reset();
}
timer1Initialize();
}
float SCKBase::average(int anaPin) {
int lecturas = 100;
long total = 0;
float average = 0;
for(int i=0; i<lecturas; i++)
{
//delay(1);
total = total + analogRead(anaPin);
}
average = (float)total / lecturas;
return(average);
}
boolean SCKBase::checkText(char* text, char *text1)
{
byte check = 0;
byte limit = strlen(text);
int i = 0;
for (i = 0; ((i< strlen(text1))&&(check<limit)); i++)
{
if (text[check]==text1[i]) check++;
else check = 0;
}
if (check == limit)
{
limit = strlen(text1);
int j = 0;
for (j = 0; i<=limit; j++)
{
if (text1[i]=='\r') text1[j]=0x00;
else text1[j] = text1[i];
i++;
}
return true;
}
else return false;
}
boolean SCKBase::compareData(char* text, char* text1)
{
if ((strlen(text))!=(strlen(text1))) return false;
else
{
for(int i=0; i<strlen(text); i++)
{
if (text[i]!=text1[i]) return false;
}
}
return true;
}
float kr= ((float)P1*1000)/RES; // Resistance conversion Constant for the digital pot.
void SCKBase::writeMCP(byte deviceaddress, byte address, int data ) {
if (data>RES) data=RES;
Wire.beginTransmission(deviceaddress);
address=(address<<4)|bitRead(data, 8) ;
Wire.write(address);
Wire.write(lowByte(data));
Wire.endTransmission();
delay(4);
}
int SCKBase::readMCP(int deviceaddress, uint16_t address ) {
byte rdata = 0xFF;
int data = 0x0000;
Wire.beginTransmission(deviceaddress);
address=(address<<4)|B00001100;
Wire.write(address);
Wire.endTransmission();
Wire.requestFrom(deviceaddress,2);
unsigned long time = millis();
while (!Wire.available()) if ((millis() - time)>500) return 0x00;
rdata = Wire.read();
data=rdata<<8;
while (!Wire.available());
rdata = Wire.read();
data=data|rdata;
return data;
}
#if F_CPU == 8000000
#define MCP3 0x2D // Direction of the mcp3 Ajust the battary charge
float SCKBase::readCharge() {
float resistor = kr*readMCP(MCP3, 0x00)/1000;
float current = 1000./(1+((resistor * 10)/(resistor + 10)));
#if debugBASE
Serial.print("Resistor : ");
Serial.print(resistor);
Serial.print(" kOhm, ");
Serial.print("Current : ");
Serial.print(current);
Serial.println(" mA");
#endif
return(current);
}
void SCKBase::writeCharge(int current) {
if (current < 100) current = 100;
else if (current > 1000) current = 1000;
float Rp = (1000./current)-1;
float resistor = Rp*10/(10-Rp);
writeMCP(MCP3, 0x00, (uint8_t)(resistor*1000/kr));
#if debugBASE
Serial.print("Rc : ");
Serial.print(Rp + 2);
Serial.print(" kOhm, ");
Serial.print("Rpot : ");
Serial.print(resistor);
Serial.print(" kOhm, ");
Serial.print("Current : ");
Serial.print(current);
Serial.println(" mA");
#endif
}
#endif
void SCKBase::writeEEPROM(uint16_t eeaddress, uint8_t data) {
uint8_t retry = 0;
while ((readEEPROM(eeaddress)!=data)&&(retry<10))
{
Wire.beginTransmission(E2PROM);
Wire.write((byte)(eeaddress >> 8)); // MSB
Wire.write((byte)(eeaddress & 0xFF)); // LSB
Wire.write(data);
Wire.endTransmission();
delay(6);
retry++;
}
}
byte SCKBase::readEEPROM(uint16_t eeaddress) {
byte rdata = 0xFF;
Wire.beginTransmission(E2PROM);
Wire.write((byte)(eeaddress >> 8)); // MSB
Wire.write((byte)(eeaddress & 0xFF)); // LSB
Wire.endTransmission();
Wire.requestFrom(E2PROM,1);
while (!Wire.available());
rdata = Wire.read();
return rdata;
}
void SCKBase::writeData(uint32_t eeaddress, long data, uint8_t location)
{
for (int i =0; i<4; i++)
{
if (location == EXTERNAL) writeEEPROM(eeaddress + (3 -i) , data>>(i*8));
else EEPROM.write(eeaddress + (3 -i), data>>(i*8));
}
}
void SCKBase::writeData(uint32_t eeaddress, uint16_t pos, char* text, uint8_t location)
{
uint16_t eeaddressfree = eeaddress + buffer_length * pos;
if (location == EXTERNAL)
{
for (uint16_t i = eeaddressfree; i< (eeaddressfree + buffer_length); i++) writeEEPROM(i, 0x00);
for (uint16_t i = eeaddressfree; text[i - eeaddressfree]!= 0x00; i++) writeEEPROM(i, text[i - eeaddressfree]);
}
else
{
for (uint16_t i = eeaddressfree; i< (eeaddressfree + buffer_length); i++) EEPROM.write(i, 0x00);
for (uint16_t i = eeaddressfree; text[i - eeaddressfree]!= 0x00; i++)
{
if (eeaddressfree>=DEFAULT_ADDR_SSID) if (text[i - eeaddressfree]==' ') text[i - eeaddressfree]='$';
EEPROM.write(i, text[i - eeaddressfree]);
}
}
}
uint32_t SCKBase::readData(uint16_t eeaddress, uint8_t location)
{
uint32_t data = 0;
for (int i =0; i<4; i++)
{
if (location == EXTERNAL) data = data + (uint32_t)((uint32_t)readEEPROM(eeaddress + i)<<((3-i)*8));
else data = data + (uint32_t)((uint32_t)EEPROM.read(eeaddress + i)<<((3-i)*8));
}
return data;
}
char* SCKBase::readData(uint16_t eeaddress, uint16_t pos, uint8_t location)
{
eeaddress = eeaddress + buffer_length * pos;
uint16_t i;
if (location == EXTERNAL)
{
uint8_t temp = readEEPROM(eeaddress);
for ( i = eeaddress; ((temp!= 0x00)&&(temp<0x7E)&&(temp>0x1F)&&((i - eeaddress)<buffer_length)); i++)
{
buffer[i - eeaddress] = readEEPROM(i);
temp = readEEPROM(i + 1);
}
}
else
{
uint8_t temp = EEPROM.read(eeaddress);
for ( i = eeaddress; ((temp!= 0x00)&&(temp<0x7E)&&(temp>0x1F)&&((i - eeaddress)<buffer_length)); i++)
{
buffer[i - eeaddress] = EEPROM.read(i);
temp = EEPROM.read(i + 1);
}
}
buffer[i - eeaddress] = 0x00;
return buffer;
}
boolean SCKBase::checkRTC() {
Wire.beginTransmission(RTC_ADDRESS);
Wire.write(0x00); //Address
Wire.endTransmission();
delay(4);
Wire.requestFrom(RTC_ADDRESS,1);
unsigned long time = millis();
while (!Wire.available()) if ((millis() - time)>500) return false;
Wire.read();
return true;
}
boolean SCKBase::RTCadjust(char *time) {
byte rtc[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
byte count = 0x00;
byte data_count=0;
while (time[count]!=0x00)
{
if(time[count] == '-') data_count++;
else if(time[count] == ' ') data_count++;
else if(time[count] == ':') data_count++;
else if ((time[count] >= '0')&&(time[count] <= '9'))
{
rtc[data_count] =(rtc[data_count]<<4)|(0x0F&time[count]);
}
else break;
count++;
}
if (data_count == 5)
{
#if F_CPU == 8000000
Wire.beginTransmission(RTC_ADDRESS);
Wire.write((int)0);
Wire.write(rtc[5]);
Wire.write(rtc[4]);
Wire.write(rtc[3]);
Wire.write(0x00);
Wire.write(rtc[2]);
Wire.write(rtc[1]);
Wire.write(rtc[0]);
Wire.endTransmission();
delay(4);
Wire.beginTransmission(RTC_ADDRESS);
Wire.write(0x0E); //Address
Wire.write(0x00); //Value
Wire.endTransmission();
#else
Wire.beginTransmission(RTC_ADDRESS);
Wire.write((int)0);
Wire.write(rtc[5]);
Wire.write(rtc[4]);
Wire.write(rtc[3]);
Wire.write(0x00);
Wire.write(rtc[2]);
Wire.write(rtc[1]);
Wire.write(rtc[0]);
Wire.write((int)0);
Wire.endTransmission();
return true;
#endif
return true;
}
return false;
}
boolean SCKBase::RTCtime(char *time) {
Wire.beginTransmission(RTC_ADDRESS);
Wire.write((int)0);
Wire.endTransmission();
Wire.requestFrom(RTC_ADDRESS, 7);
uint8_t seconds = (Wire.read() & 0x7F);
uint8_t minutes = Wire.read();
uint8_t hours = Wire.read();
Wire.read();
uint8_t day = Wire.read();
uint8_t month = Wire.read();
uint8_t year = Wire.read();
time[0] = '2';
time[1] = '0';
time[2] = (year>>4) + '0';
time[3] = (year&0x0F) + '0';
time[4] = '-';
time[5] = (month>>4) + '0';
time[6] = (month&0x0F) + '0';
time[7] = '-';
time[8] = (day>>4) + '0';
time[9] = (day&0x0F) + '0';
time[10] = ' ';
time[11] = (hours>>4) + '0';
time[12] = (hours&0x0F) + '0';
time[13] = ':';
time[14] = (minutes>>4) + '0';
time[15] = (minutes&0x0F) + '0';
time[16] = ':';
time[17] = (seconds>>4) + '0';
time[18] = (seconds&0x0F) + '0';
time[19] = 0x00;
return true;
}
uint16_t SCKBase::getPanel(float Vref){
#if F_CPU == 8000000
uint16_t value = 11*average(PANEL)*Vref/1023.;
if (value > 500) value = value + 120; //Voltage protection diode
else value = 0;
#else
uint16_t value = 3*average(PANEL)*Vref/1023.;
if (value > 500) value = value + 750; //Voltage protection diode
else value = 0;
#endif
#if debugBASE
Serial.print("Panel = ");
Serial.print(value);
Serial.println(" mV");
#endif
return value;
}
uint16_t SCKBase::getBattery(float Vref) {
uint16_t temp = average(BAT);
#if F_CPU == 8000000
float voltage = Vref*temp/1023.;
voltage = voltage + (voltage/180)*100;
#else
float voltage = Vref*temp/1023.;
#endif
temp = map(voltage, VAL_MIN_BATTERY, VAL_MAX_BATTERY, 0, 1000);
if (temp>1000) temp=1000;
if (temp<0) temp=0;
#if debugBASE
Serial.print("Vbat: ");
Serial.print(voltage);
Serial.print(" mV, ");
Serial.print("Battery level: ");
Serial.print(temp/10.);
Serial.println(" %");
#endif
return temp;
}
boolean SCKBase::findInResponse(const char *toMatch,
unsigned int timeOut = 1000) {
int byteRead;
unsigned long timeOutTarget; // in milliseconds
for (unsigned int offset = 0; offset < strlen(toMatch); offset++) {
timeOutTarget = millis() + timeOut; // Doesn't handle timer wrapping
while (!Serial1.available()) {
// Wait, with optional time out.
if (timeOut > 0) {
if (millis() > timeOutTarget) {
return false;
}
}
delay(1); // This seems to improve reliability slightly
}
byteRead = Serial1.read();
//Serial.print((char)byteRead);
delay(1); // Removing logging may affect timing slightly
if (byteRead != toMatch[offset]) {
offset = 0;
// Ignore character read if it's not a match for the start of the string
if (byteRead != toMatch[offset]) {
offset = -1;
}
continue;
}
}
return true;
}
void SCKBase::skipRemainderOfResponse(unsigned int timeOut) {
unsigned long time = millis();
while (((millis()-time)<timeOut))
{
if (Serial1.available())
{
byte temp = Serial1.read();
//Serial.write(temp);
time = millis();
}
}
}
boolean SCKBase::sendCommand(const __FlashStringHelper *command,
boolean isMultipartCommand = false,
const char *expectedResponse = "AOK") {
Serial1.print(command);
delay(20);
if (!isMultipartCommand) {
Serial1.flush();
Serial1.println();
// TODO: Handle other responses
// (e.g. autoconnect message before it's turned off,
// DHCP messages, and/or ERR etc)
if (!findInResponse(expectedResponse, 3000)) {
return false;
}
//findInResponse(expectedResponse);
}
return true;
}
boolean SCKBase::sendCommand(const char *command,
boolean isMultipartCommand = false,
const char *expectedResponse = "AOK") {
Serial1.print(command);
delay(20);
if (!isMultipartCommand) {
Serial1.flush();
Serial1.println();
// TODO: Handle other responses
// (e.g. autoconnect message before it's turned off,
// DHCP messages, and/or ERR etc)
if (!findInResponse(expectedResponse, 3000)) {
return false;
}
//findInResponse(expectedResponse);
}
return true;
}
#define COMMAND_MODE_ENTER_RETRY_ATTEMPTS 2
#define COMMAND_MODE_GUARD_TIME 250 // in milliseconds
boolean SCKBase::enterCommandMode() {
for (int retryCount = 0; retryCount < COMMAND_MODE_ENTER_RETRY_ATTEMPTS; retryCount++)
{
delay(COMMAND_MODE_GUARD_TIME);
Serial1.print(F("$$$"));
delay(COMMAND_MODE_GUARD_TIME);
Serial1.println();
Serial1.println();
if (findInResponse("\r\n<", 1000))
{
return true;
}
}
return false;
}
boolean SCKBase::sleep() {
enterCommandMode();
sendCommand(F("sleep"));
digitalWrite(AWAKE, LOW);
}
boolean SCKBase::reset() {
enterCommandMode();
sendCommand(F("factory R"), false, "Set Factory Defaults"); // Store settings
sendCommand(F("save"), false, "Storing in config"); // Store settings
sendCommand(F("reboot"), false, "*READY*");
}
boolean SCKBase::exitCommandMode() {
for (int retryCount = 0; retryCount < COMMAND_MODE_ENTER_RETRY_ATTEMPTS; retryCount++)
{
if (sendCommand(F("exit"), false, "EXIT"))
{
return true;
}
}
return false;
}
boolean SCKBase::connect()
{
if (!ready())
{
if (readData(EE_ADDR_NUMBER_NETS, INTERNAL)<1) return false;
if(enterCommandMode())
{
sendCommand(F("set wlan join 1")); // Disable AP mode
sendCommand(F("set ip dhcp 1")); // Enable DHCP server
sendCommand(F("set ip proto 10")); //TCP mode and HTML mode
sendCommand(F(DEFAULT_WIFLY_FTP_UPDATE)); //ftp server update
sendCommand(F("set ftp mode 1"));
char* auth;
char* ssid;
char* pass;
char* antenna;
for (uint16_t nets = 0 ; nets < readData(EE_ADDR_NUMBER_NETS, INTERNAL); nets++) {
auth = readData(DEFAULT_ADDR_AUTH, nets, INTERNAL);
sendCommand(F("set wlan auth "), true);
sendCommand(auth);
boolean mode = true;
if ((auth==WEP)||(auth==WEP64)) mode=false;
ssid = readData(DEFAULT_ADDR_SSID, nets, INTERNAL);
sendCommand(F("set wlan ssid "), true);
sendCommand(ssid);
pass = readData(DEFAULT_ADDR_PASS, nets, INTERNAL);
if (mode) sendCommand(F("set wlan phrase "), true); // WPA1, WPA2, OPEN
else sendCommand(F("set wlan key "), true);
sendCommand(pass);
antenna = readData(DEFAULT_ADDR_ANTENNA, nets, INTERNAL);
sendCommand(F("set wlan ext_antenna "), true);
sendCommand(antenna);
sendCommand(F("save"), false, "Storing in config"); // Store settings
sendCommand(F("reboot"), false, "*READY*");
if (ready()) return true;
enterCommandMode();
}
}
return false;
}
else return true;
}
void SCKBase::APmode(char* ssid)
{
if (enterCommandMode())
{
sendCommand(F("set wlan join 7")); // Enable AP mode
//sendCommand(F("set wlan channel <value> // Specify the channel to create network
sendCommand(F("set wlan ssid "), true); // Set up network broadcast SSID
sendCommand(ssid);
buffer[6] = 0x00;
sendCommand(F("set opt device_id "), true); // Set up network broadcast SSID
sendCommand(ssid);
sendCommand(F("set ip dhcp 4")); // Enable DHCP server
sendCommand(F("set ip address 1.2.3.4")); // Specify the IP address
sendCommand(F("set ip net 255.255.255.0")); // Specify the subnet mask
sendCommand(F("set ip gateway 1.2.3.4")); // Specify the gateway
sendCommand(F("save"), false, "Storing in config"); // Store settings
sendCommand(F("reboot"), false, "*READY*"); // Reboot the module in AP mode
}
}
boolean SCKBase::ready()
{
if(!enterCommandMode())
{
repair();
return(false);
}
else
{
Serial1.println(F("join"));
if (findInResponse("Associated!", 8000))
{
skipRemainderOfResponse(3000);
exitCommandMode();
return(true);
}
}
}
boolean connected = false;
boolean SCKBase::open(const char *addr, int port) {
if (connected) {
close();
}
if (enterCommandMode())
{
sendCommand(F("open "), true);
sendCommand(addr, true);
Serial1.print(F(" "));
Serial1.print(port);
if (sendCommand("", false, "*OPEN*"))
{
connected = true;
return true;
}
else return false;
}
enterCommandMode();
return false;
}
boolean SCKBase::close() {
if (!connected) {
return true;
}
if (sendCommand(F("close"), false, "*CLOS*")) {
connected = false;
return true;
}
connected = false;
return false;
}
#define MAC_ADDRESS_BUFFER_SIZE 18 // "FF:FF:FF:FF:FF:FF\0"
char* SCKBase::MAC() {
if (enterCommandMode())
{
if (sendCommand(F("get mac"), false, "Mac Addr="))
{
char newChar;
byte offset = 0;
while (offset < MAC_ADDRESS_BUFFER_SIZE) {
if (Serial1.available())
{
newChar = Serial1.read();
//Serial.println(newChar);
if ((newChar == '\n')||(newChar < '0')) {
buffer[offset] = '\x00';
break;
}
else if (newChar != -1) {
buffer[offset] = newChar;
offset++;
}
}
}
buffer[MAC_ADDRESS_BUFFER_SIZE-1] = '\x00';
exitCommandMode();
}
}
return buffer;
}
char* SCKBase::id() {
char* temp = MAC();
byte len = strlen(temp);
byte j = 4;
buffer[0] = 'S';
buffer[1] = 'C';
buffer[2] = 'K';
buffer[3] = '_';
for(byte i=12; i<len; i++)
{
if (temp[i] == ':') buffer[j] = '-';
else buffer[j] = temp[i];
j++;
}
buffer[j] = 0x00;
return buffer;
}
#define SCAN_BUFFER_SIZE 4
uint32_t SCKBase::scan() {
if (enterCommandMode())
{
if (sendCommand(F("scan"), false, "Found "))
{
char newChar;
byte offset = 0;
while (offset < SCAN_BUFFER_SIZE) {
if (Serial1.available())
{
newChar = Serial1.read();
if ((newChar == '\r')||(newChar < '0')) {
buffer[offset] = '\x00';
break;
}
else if (newChar != -1) {
buffer[offset] = newChar;
offset++;
}
}
}
buffer[SCAN_BUFFER_SIZE-1] = '\x00';
findInResponse("END:\r\n", 2000);
exitCommandMode();
}
}
return atol(buffer);
}
int SCKBase::checkWiFly() {
int ver = getWiFlyVersion();
if (ver > 0)
{
if (ver < WIFLY_LATEST_VERSION)
{
if(update()) return 1; //Wifly Updated.
else return 2; //Update Fail.
reset();
}
else return 0; //WiFly up to date.
}
else return -1; //Error reading the wifi version.
}
int SCKBase::getWiFlyVersion() {
if (enterCommandMode())
{
if (sendCommand(F("ver"), false, "wifly-GSX Ver"))
{
char newChar;
byte offset = 0;
boolean prevWasNumber = false;
while (offset < 3) {
if (Serial1.available())
{
newChar = Serial1.read();
if ((newChar != -1 && isdigit(newChar)) || newChar == '.') {
if (newChar != '.') {
buffer[offset] = newChar;
offset++;
}
prevWasNumber = true;
}
else {
if (prevWasNumber){
break;
}
prevWasNumber = false;
}
}
}
exitCommandMode();
buffer[offset] = 0x00;
return atoi(buffer);
}
return 0;
}
return 0;
}
boolean SCKBase::update() {
if (enterCommandMode())
{
sendCommand(F(DEFAULT_WIFLY_FIRMWARE));
delay(1000);
if (findInResponse("FTP OK.", 60000))
{
return true;
}
}
else return false;
}
uint32_t baud[7]={
2400, 4800, 9600, 19200, 38400, 57600, 115200};
void SCKBase::repair()
{
if(!enterCommandMode())
{
boolean repair = true;
for (int i=6; ((i>=0)&&repair); i--)
{
Serial1.begin(baud[i]);
if(enterCommandMode())
{
reset();
repair = false;
}
Serial1.begin(9600);
}
}
}
/*TIMER*/
#define RESOLUTION 65536 // Timer1 is 16 bit
unsigned int pwmPeriod;
unsigned char clockSelectBits;
char oldSREG; // To hold Status
void SCKBase::timer1SetPeriod(long microseconds) // AR modified for atomic access
{
long cycles = (F_CPU / 2000000) * microseconds; // the counter runs backwards after TOP, interrupt is at BOTTOM so divide microseconds by 2
if(cycles < RESOLUTION) clockSelectBits = _BV(CS10); // no prescale, full xtal
else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11); // prescale by /8
else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11) | _BV(CS10); // prescale by /64
else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12); // prescale by /256
else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12) | _BV(CS10); // prescale by /1024
else cycles = RESOLUTION - 1, clockSelectBits = _BV(CS12) | _BV(CS10); // request was out of bounds, set as maximum
oldSREG = SREG;
cli(); // Disable interrupts for 16 bit register access
ICR1 = pwmPeriod = cycles; // ICR1 is TOP in p & f correct pwm mode
SREG = oldSREG;
TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12));
TCCR1B |= clockSelectBits; // reset clock select register, and starts the clock
}
void SCKBase::timer1Initialize()
{
TCCR1A = 0; // clear control register A
TCCR1B = _BV(WGM13); // set mode 8: phase and frequency correct pwm, stop the timer
timer1SetPeriod(1500);
TIMSK1 = _BV(TOIE1);
}
void SCKBase::timer1Stop()
{
TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12)); // clears all clock selects bits
TIMSK1 &= ~(_BV(TOIE1));
}