diff --git a/Variometer/Variometer.ino b/Variometer/Variometer.ino index 61db8e5..50f7bee 100644 --- a/Variometer/Variometer.ino +++ b/Variometer/Variometer.ino @@ -134,7 +134,7 @@ struct Conf float p0; uint8_t stat_index; } conf = { - 0.8 , -1.1 , 0, 0, 50, true, 1040.00, 0 + 0.3, -1.1 , 0, 0, 50, true, 1040.00, 0 }; // Statistic structure (176 bits) @@ -164,9 +164,7 @@ void writeStat(uint8_t index = conf.stat_index, Stat &value = stat) void incrementStatIndex() { - conf.stat_index++; - if (conf.stat_index > NB_STATS - 1) - conf.stat_index = 0; + conf.stat_index = (conf.stat_index == NB_STATS - 1)? 0 : conf.stat_index + 1; EEPROM_writeAnything(0, conf); readStat(); } @@ -221,14 +219,7 @@ void initEeprom() void renderChrono(Stat value = stat) { - uint16_t s; - if (value.chrono == 0 && value.chrono_start != 0) { - DateTime now = rtc.now(); - s = now.unixtime() - value.chrono_start; - } - else - s = value.chrono; - + uint16_t s = (value.chrono == 0 && value.chrono_start != 0)? rtc.now().unixtime() - value.chrono_start: value.chrono; uint8_t h = floor(s / 3600); s -= h * 3600; uint8_t m = floor(s / 60); @@ -245,7 +236,7 @@ void renderChrono(Stat value = stat) void renderVario() { - if (varioState == true){ + if (true == varioState){ display.fillRect(0, 0, 84, 32, WHITE); // text display tests @@ -279,6 +270,8 @@ void renderVario() } else { display.setCursor(62, 9); + // set up my_temperature + bmp085.getTemperature(&my_temperature); display.print((int)my_temperature); display.drawCircle(75, 10, 1, BLACK); display.setCursor(72, 9); @@ -328,16 +321,13 @@ void renderVarioBar() } } -void renderVolume(uint8_t dir = MENU_RIGHT) +void renderVolume(bool volume) { display.clearDisplay(); display.setTextSize(2); display.setTextColor(WHITE, BLACK); - if (dir == MENU_RIGHT) - conf.volume = true; - else if (dir == MENU_LEFT) - conf.volume = false; + conf.volume = volume; push_write_eeprom = 0; get_time2 = millis(); //stop the refresh rendering vario @@ -819,6 +809,7 @@ void updateBrightness() analogWrite(PIN_LIGHT, conf.light_cpt * 51); } + int readVccPercent() { uint16_t real_bat = (int)(4.89 * analogRead(A0)); @@ -835,26 +826,36 @@ int readVccPercent() return percent; } + uint8_t getBeepLatency(float variation) { int latency = 150 - (variation * 30); return (latency < 70)? 70: (latency > 150)? 150: latency; } + uint16_t getBeepFrequency(float variation) { int frequency = 690 + (150 * variation); return (frequency < 100)? 100: (frequency > 1300)? 1300 :frequency; } -void resetAltitudeSensor() + +void updateAltitude(bool reset = false) { // get a new sensor event sensors_event_t event; - bmp085.getEvent(&event); - average_pressure = event.pressure; //put it in filter and take average - bmp085.getTemperature(&my_temperature); - Altitude = bmp085.pressureToAltitude(conf.p0, average_pressure, my_temperature) + conf.currentAltitude; //take new altitude in meters + bmp085.getEvent(&event); + // put it in smooth filter and take average + average_pressure = (true == reset)? event.pressure : average_pressure * 0.94 + event.pressure * 0.06; + // take new altitude in meters + Altitude = bmp085.pressureToAltitude(conf.p0, average_pressure) + conf.currentAltitude; +} + + +void resetAltitudeSensor() +{ + updateAltitude(true); altitude_temp = Altitude; alt = Altitude; tim = millis(); @@ -897,6 +898,7 @@ void makeBeeps() } } + void setup() { //Serial.begin(9600); @@ -929,21 +931,15 @@ void setup() updateBrightness(); } -void loop() -{ - readButtons(); - // get a new sensor event - sensors_event_t event; - bmp085.getEvent(&event); - // put it in filter and take average - average_pressure = average_pressure * 0.94 + event.pressure * 0.06; - // set up my_temperature - bmp085.getTemperature(&my_temperature); - // take new altitude in meters - Altitude = bmp085.pressureToAltitude(conf.p0, average_pressure, my_temperature) + conf.currentAltitude; +void loop() +{ float tempo = micros(); - // put it in filter and take average + + readButtons(); + updateAltitude(); + + // put it in smooth filter and take average //vario = 1000000 * ((alt - Altitude) / (tim - tempo))); vario = vario * 0.8 + (200000 * ((alt - Altitude) / (tim - tempo))); @@ -1056,6 +1052,8 @@ void loop() //correction beep latency makeBeeps(); } + + //Serial.println((tempo - micros())); } void readButtons() @@ -1080,7 +1078,7 @@ void readButtons() else if (varioState == false) renderMenu(menu.getCurrent(), MENU_RIGHT); else if (varioState == true) - renderVolume(MENU_RIGHT); + renderVolume(true); } else { //Left if (!menuUsed && varioState == false) { @@ -1096,7 +1094,7 @@ void readButtons() else if (varioState == false) renderMenu(menu.getCurrent(), MENU_LEFT); else if (varioState == true) - renderVolume(MENU_LEFT); + renderVolume(false); } knobPosition = newKnobPosition; } diff --git a/libraries/Adafruit_BMP085_U/Adafruit_BMP085_U.cpp b/libraries/Adafruit_BMP085_U/Adafruit_BMP085_U.cpp index 1122d12..18695c2 100644 --- a/libraries/Adafruit_BMP085_U/Adafruit_BMP085_U.cpp +++ b/libraries/Adafruit_BMP085_U/Adafruit_BMP085_U.cpp @@ -353,7 +353,34 @@ void Adafruit_BMP085_Unified::getTemperature(float *temp) /**************************************************************************/ /*! Calculates the altitude (in meters) from the specified atmospheric - pressure (in hPa), sea-level pressure (in hPa), and temperature (in �C) + pressure (in hPa), and sea-level pressure (in hPa). + + @param seaLevel Sea-level pressure in hPa + @param atmospheric Atmospheric pressure in hPa +*/ +/**************************************************************************/ +float Adafruit_BMP085_Unified::pressureToAltitude(float seaLevel, float atmospheric) +{ + // Equation taken from BMP180 datasheet (page 16): + // http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf + + // Note that using the equation from wikipedia can give bad results + // at high altitude. See this thread for more information: + // http://forums.adafruit.com/viewtopic.php?f=22&t=58064 + + return 44330.0 * (1.0 - pow(atmospheric / seaLevel, 0.1903)); +} + +/**************************************************************************/ +/*! + Calculates the altitude (in meters) from the specified atmospheric + pressure (in hPa), and sea-level pressure (in hPa). Note that this + function just calls the overload of pressureToAltitude which takes + seaLevel and atmospheric pressure--temperature is ignored. The original + implementation of this function was based on calculations from Wikipedia + which are not accurate at higher altitudes. To keep compatibility with + old code this function remains with the same interface, but it calls the + more accurate calculation. @param seaLevel Sea-level pressure in hPa @param atmospheric Atmospheric pressure in hPa @@ -362,33 +389,49 @@ void Adafruit_BMP085_Unified::getTemperature(float *temp) /**************************************************************************/ float Adafruit_BMP085_Unified::pressureToAltitude(float seaLevel, float atmospheric, float temp) { - /* Hyposometric formula: */ - /* */ - /* ((P0/P)^(1/5.257) - 1) * (T + 273.15) */ - /* h = ------------------------------------- */ - /* 0.0065 */ - /* */ - /* where: h = height (in meters) */ - /* P0 = sea-level pressure (in hPa) */ - /* P = atmospheric pressure (in hPa) */ - /* T = temperature (in �C) */ - - return (((float)pow((seaLevel/atmospheric), 0.190223F) - 1.0F) - * (temp + 273.15F)) / 0.0065F; + return pressureToAltitude(seaLevel, atmospheric); } +/**************************************************************************/ +/*! + Calculates the pressure at sea level (in hPa) from the specified altitude + (in meters), and atmospheric pressure (in hPa). + + @param altitude Altitude in meters + @param atmospheric Atmospheric pressure in hPa +*/ +/**************************************************************************/ +float Adafruit_BMP085_Unified::seaLevelForAltitude(float altitude, float atmospheric) +{ + // Equation taken from BMP180 datasheet (page 17): + // http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf + + // Note that using the equation from wikipedia can give bad results + // at high altitude. See this thread for more information: + // http://forums.adafruit.com/viewtopic.php?f=22&t=58064 + + return atmospheric / pow(1.0 - (altitude/44330.0), 5.255); +} + +/**************************************************************************/ +/*! + Calculates the pressure at sea level (in hPa) from the specified altitude + (in meters), and atmospheric pressure (in hPa). Note that this + function just calls the overload of seaLevelForAltitude which takes + altitude and atmospheric pressure--temperature is ignored. The original + implementation of this function was based on calculations from Wikipedia + which are not accurate at higher altitudes. To keep compatibility with + old code this function remains with the same interface, but it calls the + more accurate calculation. + + @param altitude Altitude in meters + @param atmospheric Atmospheric pressure in hPa + @param temp Temperature in degrees Celsius +*/ +/**************************************************************************/ float Adafruit_BMP085_Unified::seaLevelForAltitude(float altitude, float atmospheric, float temp) { - /* Hyposometric formula: */ - /* */ - /* P0=((((h*0.0065)/(temp + 273.15F))+1)^(^/0.190223F))*P */ - /* */ - /* where: h = height (in meters) */ - /* P0 = sea-level pressure (in hPa) */ - /* P = atmospheric pressure (in hPa) */ - /* T = temperature (in �C) */ - - return (float)pow((((altitude*0.0065)/(temp + 273.15F))+1), (1.0/0.190223F))*atmospheric; + return seaLevelForAltitude(altitude, atmospheric); } diff --git a/libraries/Adafruit_BMP085_U/Adafruit_BMP085_U.h b/libraries/Adafruit_BMP085_U/Adafruit_BMP085_U.h index 386fbcc..5a929f0 100644 --- a/libraries/Adafruit_BMP085_U/Adafruit_BMP085_U.h +++ b/libraries/Adafruit_BMP085_U/Adafruit_BMP085_U.h @@ -104,6 +104,11 @@ class Adafruit_BMP085_Unified : public Adafruit_Sensor bool begin(bmp085_mode_t mode = BMP085_MODE_ULTRAHIGHRES); void getTemperature(float *temp); void getPressure(float *pressure); + float pressureToAltitude(float seaLvel, float atmospheric); + float seaLevelForAltitude(float altitude, float atmospheric); + // Note that the next two functions are just for compatibility with old + // code that passed the temperature as a third parameter. A newer + // calculation is used which does not need temperature. float pressureToAltitude(float seaLevel, float atmospheric, float temp); float seaLevelForAltitude(float altitude, float atmospheric, float temp); void getEvent(sensors_event_t*); diff --git a/libraries/Adafruit_BMP085_U/examples/sensorapi/sensorapi.pde b/libraries/Adafruit_BMP085_U/examples/sensorapi/sensorapi.pde index 73d5150..46b7b51 100644 --- a/libraries/Adafruit_BMP085_U/examples/sensorapi/sensorapi.pde +++ b/libraries/Adafruit_BMP085_U/examples/sensorapi/sensorapi.pde @@ -115,13 +115,12 @@ void loop(void) Serial.print(temperature); Serial.println(" C"); - /* Then convert the atmospheric pressure, SLP and temp to altitude */ + /* Then convert the atmospheric pressure, and SLP to altitude */ /* Update this next line with the current SLP for better results */ float seaLevelPressure = SENSORS_PRESSURE_SEALEVELHPA; Serial.print("Altitude: "); Serial.print(bmp.pressureToAltitude(seaLevelPressure, - event.pressure, - temperature)); + event.pressure)); Serial.println(" m"); Serial.println(""); } diff --git a/libraries/Adafruit_GFX/Adafruit_GFX.cpp b/libraries/Adafruit_GFX/Adafruit_GFX.cpp index c85cfa2..d0dce2c 100644 --- a/libraries/Adafruit_GFX/Adafruit_GFX.cpp +++ b/libraries/Adafruit_GFX/Adafruit_GFX.cpp @@ -358,7 +358,46 @@ void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, for(j=0; j> (i & 7))) { - drawPixel(x+i, y+j, color); + drawPixel(x+i, y+j, color); + } + } + } +} + +// Draw a 1-bit color bitmap at the specified x, y position from the +// provided bitmap buffer (must be PROGMEM memory) using color as the +// foreground color and bg as the background color. +void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, + const uint8_t *bitmap, int16_t w, int16_t h, + uint16_t color, uint16_t bg) { + + int16_t i, j, byteWidth = (w + 7) / 8; + + for(j=0; j> (i & 7))) { + drawPixel(x+i, y+j, color); + } + else { + drawPixel(x+i, y+j, bg); + } + } + } +} + +//Draw XBitMap Files (*.xbm), exported from GIMP, +//Usage: Export from GIMP to *.xbm, rename *.xbm to *.c and open in editor. +//C Array can be directly used with this function +void Adafruit_GFX::drawXBitmap(int16_t x, int16_t y, + const uint8_t *bitmap, int16_t w, int16_t h, + uint16_t color) { + + int16_t i, j, byteWidth = (w + 7) / 8; + + for(j=0; j/Libraries/ folder. You may need to create the Libraries subfolder if its your first library. Restart the IDE. + +Useful Resources +================ + +- Image2Code + This is a handy Java GUI utility to convert a BMP file into the array code necessary to display the image with the drawBitmap function. Check out the code at ehubin's GitHub repository: + https://github.com/ehubin/Adafruit-GFX-Library/tree/master/Img2Code + +- drawXBitmap function + You can use the GIMP photo editor to save a .xbm file and use the array saved in the file to draw a bitmap with the drawXBitmap function. See the pull request here for more details: + https://github.com/adafruit/Adafruit-GFX-Library/pull/31 diff --git a/libraries/Adafruit_GFX/glcdfont.c b/libraries/Adafruit_GFX/glcdfont.c index d016b93..2d9d3a9 100644 --- a/libraries/Adafruit_GFX/glcdfont.c +++ b/libraries/Adafruit_GFX/glcdfont.c @@ -11,251 +11,251 @@ // Standard ASCII 5x7 font static const unsigned char font[] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, - 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, - 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, - 0x18, 0x3C, 0x7E, 0x3C, 0x18, - 0x1C, 0x57, 0x7D, 0x57, 0x1C, - 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, - 0x00, 0x18, 0x3C, 0x18, 0x00, - 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, - 0x00, 0x18, 0x24, 0x18, 0x00, - 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, - 0x30, 0x48, 0x3A, 0x06, 0x0E, - 0x26, 0x29, 0x79, 0x29, 0x26, - 0x40, 0x7F, 0x05, 0x05, 0x07, - 0x40, 0x7F, 0x05, 0x25, 0x3F, - 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, - 0x7F, 0x3E, 0x1C, 0x1C, 0x08, - 0x08, 0x1C, 0x1C, 0x3E, 0x7F, - 0x14, 0x22, 0x7F, 0x22, 0x14, - 0x5F, 0x5F, 0x00, 0x5F, 0x5F, - 0x06, 0x09, 0x7F, 0x01, 0x7F, - 0x00, 0x66, 0x89, 0x95, 0x6A, - 0x60, 0x60, 0x60, 0x60, 0x60, - 0x94, 0xA2, 0xFF, 0xA2, 0x94, - 0x08, 0x04, 0x7E, 0x04, 0x08, - 0x10, 0x20, 0x7E, 0x20, 0x10, - 0x08, 0x08, 0x2A, 0x1C, 0x08, - 0x08, 0x1C, 0x2A, 0x08, 0x08, - 0x1E, 0x10, 0x10, 0x10, 0x10, - 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, - 0x30, 0x38, 0x3E, 0x38, 0x30, - 0x06, 0x0E, 0x3E, 0x0E, 0x06, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x5F, 0x00, 0x00, - 0x00, 0x07, 0x00, 0x07, 0x00, - 0x14, 0x7F, 0x14, 0x7F, 0x14, - 0x24, 0x2A, 0x7F, 0x2A, 0x12, - 0x23, 0x13, 0x08, 0x64, 0x62, - 0x36, 0x49, 0x56, 0x20, 0x50, - 0x00, 0x08, 0x07, 0x03, 0x00, - 0x00, 0x1C, 0x22, 0x41, 0x00, - 0x00, 0x41, 0x22, 0x1C, 0x00, - 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, - 0x08, 0x08, 0x3E, 0x08, 0x08, - 0x00, 0x80, 0x70, 0x30, 0x00, - 0x08, 0x08, 0x08, 0x08, 0x08, - 0x00, 0x00, 0x60, 0x60, 0x00, - 0x20, 0x10, 0x08, 0x04, 0x02, - 0x3E, 0x51, 0x49, 0x45, 0x3E, - 0x00, 0x42, 0x7F, 0x40, 0x00, - 0x72, 0x49, 0x49, 0x49, 0x46, - 0x21, 0x41, 0x49, 0x4D, 0x33, - 0x18, 0x14, 0x12, 0x7F, 0x10, - 0x27, 0x45, 0x45, 0x45, 0x39, - 0x3C, 0x4A, 0x49, 0x49, 0x31, - 0x41, 0x21, 0x11, 0x09, 0x07, - 0x36, 0x49, 0x49, 0x49, 0x36, - 0x46, 0x49, 0x49, 0x29, 0x1E, - 0x00, 0x00, 0x14, 0x00, 0x00, - 0x00, 0x40, 0x34, 0x00, 0x00, - 0x00, 0x08, 0x14, 0x22, 0x41, - 0x14, 0x14, 0x14, 0x14, 0x14, - 0x00, 0x41, 0x22, 0x14, 0x08, - 0x02, 0x01, 0x59, 0x09, 0x06, - 0x3E, 0x41, 0x5D, 0x59, 0x4E, - 0x7C, 0x12, 0x11, 0x12, 0x7C, - 0x7F, 0x49, 0x49, 0x49, 0x36, - 0x3E, 0x41, 0x41, 0x41, 0x22, - 0x7F, 0x41, 0x41, 0x41, 0x3E, - 0x7F, 0x49, 0x49, 0x49, 0x41, - 0x7F, 0x09, 0x09, 0x09, 0x01, - 0x3E, 0x41, 0x41, 0x51, 0x73, - 0x7F, 0x08, 0x08, 0x08, 0x7F, - 0x00, 0x41, 0x7F, 0x41, 0x00, - 0x20, 0x40, 0x41, 0x3F, 0x01, - 0x7F, 0x08, 0x14, 0x22, 0x41, - 0x7F, 0x40, 0x40, 0x40, 0x40, - 0x7F, 0x02, 0x1C, 0x02, 0x7F, - 0x7F, 0x04, 0x08, 0x10, 0x7F, - 0x3E, 0x41, 0x41, 0x41, 0x3E, - 0x7F, 0x09, 0x09, 0x09, 0x06, - 0x3E, 0x41, 0x51, 0x21, 0x5E, - 0x7F, 0x09, 0x19, 0x29, 0x46, - 0x26, 0x49, 0x49, 0x49, 0x32, - 0x03, 0x01, 0x7F, 0x01, 0x03, - 0x3F, 0x40, 0x40, 0x40, 0x3F, - 0x1F, 0x20, 0x40, 0x20, 0x1F, - 0x3F, 0x40, 0x38, 0x40, 0x3F, - 0x63, 0x14, 0x08, 0x14, 0x63, - 0x03, 0x04, 0x78, 0x04, 0x03, - 0x61, 0x59, 0x49, 0x4D, 0x43, - 0x00, 0x7F, 0x41, 0x41, 0x41, - 0x02, 0x04, 0x08, 0x10, 0x20, - 0x00, 0x41, 0x41, 0x41, 0x7F, - 0x04, 0x02, 0x01, 0x02, 0x04, - 0x40, 0x40, 0x40, 0x40, 0x40, - 0x00, 0x03, 0x07, 0x08, 0x00, - 0x20, 0x54, 0x54, 0x78, 0x40, - 0x7F, 0x28, 0x44, 0x44, 0x38, - 0x38, 0x44, 0x44, 0x44, 0x28, - 0x38, 0x44, 0x44, 0x28, 0x7F, - 0x38, 0x54, 0x54, 0x54, 0x18, - 0x00, 0x08, 0x7E, 0x09, 0x02, - 0x18, 0xA4, 0xA4, 0x9C, 0x78, - 0x7F, 0x08, 0x04, 0x04, 0x78, - 0x00, 0x44, 0x7D, 0x40, 0x00, - 0x20, 0x40, 0x40, 0x3D, 0x00, - 0x7F, 0x10, 0x28, 0x44, 0x00, - 0x00, 0x41, 0x7F, 0x40, 0x00, - 0x7C, 0x04, 0x78, 0x04, 0x78, - 0x7C, 0x08, 0x04, 0x04, 0x78, - 0x38, 0x44, 0x44, 0x44, 0x38, - 0xFC, 0x18, 0x24, 0x24, 0x18, - 0x18, 0x24, 0x24, 0x18, 0xFC, - 0x7C, 0x08, 0x04, 0x04, 0x08, - 0x48, 0x54, 0x54, 0x54, 0x24, - 0x04, 0x04, 0x3F, 0x44, 0x24, - 0x3C, 0x40, 0x40, 0x20, 0x7C, - 0x1C, 0x20, 0x40, 0x20, 0x1C, - 0x3C, 0x40, 0x30, 0x40, 0x3C, - 0x44, 0x28, 0x10, 0x28, 0x44, - 0x4C, 0x90, 0x90, 0x90, 0x7C, - 0x44, 0x64, 0x54, 0x4C, 0x44, - 0x00, 0x08, 0x36, 0x41, 0x00, - 0x00, 0x00, 0x77, 0x00, 0x00, - 0x00, 0x41, 0x36, 0x08, 0x00, - 0x02, 0x01, 0x02, 0x04, 0x02, - 0x3C, 0x26, 0x23, 0x26, 0x3C, - 0x1E, 0xA1, 0xA1, 0x61, 0x12, - 0x3A, 0x40, 0x40, 0x20, 0x7A, - 0x38, 0x54, 0x54, 0x55, 0x59, - 0x21, 0x55, 0x55, 0x79, 0x41, - 0x21, 0x54, 0x54, 0x78, 0x41, - 0x21, 0x55, 0x54, 0x78, 0x40, - 0x20, 0x54, 0x55, 0x79, 0x40, - 0x0C, 0x1E, 0x52, 0x72, 0x12, - 0x39, 0x55, 0x55, 0x55, 0x59, - 0x39, 0x54, 0x54, 0x54, 0x59, - 0x39, 0x55, 0x54, 0x54, 0x58, - 0x00, 0x00, 0x45, 0x7C, 0x41, - 0x00, 0x02, 0x45, 0x7D, 0x42, - 0x00, 0x01, 0x45, 0x7C, 0x40, - 0xF0, 0x29, 0x24, 0x29, 0xF0, - 0xF0, 0x28, 0x25, 0x28, 0xF0, - 0x7C, 0x54, 0x55, 0x45, 0x00, - 0x20, 0x54, 0x54, 0x7C, 0x54, - 0x7C, 0x0A, 0x09, 0x7F, 0x49, - 0x32, 0x49, 0x49, 0x49, 0x32, - 0x32, 0x48, 0x48, 0x48, 0x32, - 0x32, 0x4A, 0x48, 0x48, 0x30, - 0x3A, 0x41, 0x41, 0x21, 0x7A, - 0x3A, 0x42, 0x40, 0x20, 0x78, - 0x00, 0x9D, 0xA0, 0xA0, 0x7D, - 0x39, 0x44, 0x44, 0x44, 0x39, - 0x3D, 0x40, 0x40, 0x40, 0x3D, - 0x3C, 0x24, 0xFF, 0x24, 0x24, - 0x48, 0x7E, 0x49, 0x43, 0x66, - 0x2B, 0x2F, 0xFC, 0x2F, 0x2B, - 0xFF, 0x09, 0x29, 0xF6, 0x20, - 0xC0, 0x88, 0x7E, 0x09, 0x03, - 0x20, 0x54, 0x54, 0x79, 0x41, - 0x00, 0x00, 0x44, 0x7D, 0x41, - 0x30, 0x48, 0x48, 0x4A, 0x32, - 0x38, 0x40, 0x40, 0x22, 0x7A, - 0x00, 0x7A, 0x0A, 0x0A, 0x72, - 0x7D, 0x0D, 0x19, 0x31, 0x7D, - 0x26, 0x29, 0x29, 0x2F, 0x28, - 0x26, 0x29, 0x29, 0x29, 0x26, - 0x30, 0x48, 0x4D, 0x40, 0x20, - 0x38, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x38, - 0x2F, 0x10, 0xC8, 0xAC, 0xBA, - 0x2F, 0x10, 0x28, 0x34, 0xFA, - 0x00, 0x00, 0x7B, 0x00, 0x00, - 0x08, 0x14, 0x2A, 0x14, 0x22, - 0x22, 0x14, 0x2A, 0x14, 0x08, - 0xAA, 0x00, 0x55, 0x00, 0xAA, - 0xAA, 0x55, 0xAA, 0x55, 0xAA, - 0x00, 0x00, 0x00, 0xFF, 0x00, - 0x10, 0x10, 0x10, 0xFF, 0x00, - 0x14, 0x14, 0x14, 0xFF, 0x00, - 0x10, 0x10, 0xFF, 0x00, 0xFF, - 0x10, 0x10, 0xF0, 0x10, 0xF0, - 0x14, 0x14, 0x14, 0xFC, 0x00, - 0x14, 0x14, 0xF7, 0x00, 0xFF, - 0x00, 0x00, 0xFF, 0x00, 0xFF, - 0x14, 0x14, 0xF4, 0x04, 0xFC, - 0x14, 0x14, 0x17, 0x10, 0x1F, - 0x10, 0x10, 0x1F, 0x10, 0x1F, - 0x14, 0x14, 0x14, 0x1F, 0x00, - 0x10, 0x10, 0x10, 0xF0, 0x00, - 0x00, 0x00, 0x00, 0x1F, 0x10, - 0x10, 0x10, 0x10, 0x1F, 0x10, - 0x10, 0x10, 0x10, 0xF0, 0x10, - 0x00, 0x00, 0x00, 0xFF, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0xFF, 0x10, - 0x00, 0x00, 0x00, 0xFF, 0x14, - 0x00, 0x00, 0xFF, 0x00, 0xFF, - 0x00, 0x00, 0x1F, 0x10, 0x17, - 0x00, 0x00, 0xFC, 0x04, 0xF4, - 0x14, 0x14, 0x17, 0x10, 0x17, - 0x14, 0x14, 0xF4, 0x04, 0xF4, - 0x00, 0x00, 0xFF, 0x00, 0xF7, - 0x14, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0xF7, 0x00, 0xF7, - 0x14, 0x14, 0x14, 0x17, 0x14, - 0x10, 0x10, 0x1F, 0x10, 0x1F, - 0x14, 0x14, 0x14, 0xF4, 0x14, - 0x10, 0x10, 0xF0, 0x10, 0xF0, - 0x00, 0x00, 0x1F, 0x10, 0x1F, - 0x00, 0x00, 0x00, 0x1F, 0x14, - 0x00, 0x00, 0x00, 0xFC, 0x14, - 0x00, 0x00, 0xF0, 0x10, 0xF0, - 0x10, 0x10, 0xFF, 0x10, 0xFF, - 0x14, 0x14, 0x14, 0xFF, 0x14, - 0x10, 0x10, 0x10, 0x1F, 0x00, - 0x00, 0x00, 0x00, 0xF0, 0x10, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, - 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, - 0x38, 0x44, 0x44, 0x38, 0x44, - 0x7C, 0x2A, 0x2A, 0x3E, 0x14, - 0x7E, 0x02, 0x02, 0x06, 0x06, - 0x02, 0x7E, 0x02, 0x7E, 0x02, - 0x63, 0x55, 0x49, 0x41, 0x63, - 0x38, 0x44, 0x44, 0x3C, 0x04, - 0x40, 0x7E, 0x20, 0x1E, 0x20, - 0x06, 0x02, 0x7E, 0x02, 0x02, - 0x99, 0xA5, 0xE7, 0xA5, 0x99, - 0x1C, 0x2A, 0x49, 0x2A, 0x1C, - 0x4C, 0x72, 0x01, 0x72, 0x4C, - 0x30, 0x4A, 0x4D, 0x4D, 0x30, - 0x30, 0x48, 0x78, 0x48, 0x30, - 0xBC, 0x62, 0x5A, 0x46, 0x3D, - 0x3E, 0x49, 0x49, 0x49, 0x00, - 0x7E, 0x01, 0x01, 0x01, 0x7E, - 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, - 0x44, 0x44, 0x5F, 0x44, 0x44, - 0x40, 0x51, 0x4A, 0x44, 0x40, - 0x40, 0x44, 0x4A, 0x51, 0x40, - 0x00, 0x00, 0xFF, 0x01, 0x03, - 0xE0, 0x80, 0xFF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, + 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, + 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, + 0x18, 0x3C, 0x7E, 0x3C, 0x18, + 0x1C, 0x57, 0x7D, 0x57, 0x1C, + 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, + 0x00, 0x18, 0x3C, 0x18, 0x00, + 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, + 0x00, 0x18, 0x24, 0x18, 0x00, + 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, + 0x30, 0x48, 0x3A, 0x06, 0x0E, + 0x26, 0x29, 0x79, 0x29, 0x26, + 0x40, 0x7F, 0x05, 0x05, 0x07, + 0x40, 0x7F, 0x05, 0x25, 0x3F, + 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, + 0x7F, 0x3E, 0x1C, 0x1C, 0x08, + 0x08, 0x1C, 0x1C, 0x3E, 0x7F, + 0x14, 0x22, 0x7F, 0x22, 0x14, + 0x5F, 0x5F, 0x00, 0x5F, 0x5F, + 0x06, 0x09, 0x7F, 0x01, 0x7F, + 0x00, 0x66, 0x89, 0x95, 0x6A, + 0x60, 0x60, 0x60, 0x60, 0x60, + 0x94, 0xA2, 0xFF, 0xA2, 0x94, + 0x08, 0x04, 0x7E, 0x04, 0x08, + 0x10, 0x20, 0x7E, 0x20, 0x10, + 0x08, 0x08, 0x2A, 0x1C, 0x08, + 0x08, 0x1C, 0x2A, 0x08, 0x08, + 0x1E, 0x10, 0x10, 0x10, 0x10, + 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, + 0x30, 0x38, 0x3E, 0x38, 0x30, + 0x06, 0x0E, 0x3E, 0x0E, 0x06, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x5F, 0x00, 0x00, + 0x00, 0x07, 0x00, 0x07, 0x00, + 0x14, 0x7F, 0x14, 0x7F, 0x14, + 0x24, 0x2A, 0x7F, 0x2A, 0x12, + 0x23, 0x13, 0x08, 0x64, 0x62, + 0x36, 0x49, 0x56, 0x20, 0x50, + 0x00, 0x08, 0x07, 0x03, 0x00, + 0x00, 0x1C, 0x22, 0x41, 0x00, + 0x00, 0x41, 0x22, 0x1C, 0x00, + 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, + 0x08, 0x08, 0x3E, 0x08, 0x08, + 0x00, 0x80, 0x70, 0x30, 0x00, + 0x08, 0x08, 0x08, 0x08, 0x08, + 0x00, 0x00, 0x60, 0x60, 0x00, + 0x20, 0x10, 0x08, 0x04, 0x02, + 0x3E, 0x51, 0x49, 0x45, 0x3E, + 0x00, 0x42, 0x7F, 0x40, 0x00, + 0x72, 0x49, 0x49, 0x49, 0x46, + 0x21, 0x41, 0x49, 0x4D, 0x33, + 0x18, 0x14, 0x12, 0x7F, 0x10, + 0x27, 0x45, 0x45, 0x45, 0x39, + 0x3C, 0x4A, 0x49, 0x49, 0x31, + 0x41, 0x21, 0x11, 0x09, 0x07, + 0x36, 0x49, 0x49, 0x49, 0x36, + 0x46, 0x49, 0x49, 0x29, 0x1E, + 0x00, 0x00, 0x14, 0x00, 0x00, + 0x00, 0x40, 0x34, 0x00, 0x00, + 0x00, 0x08, 0x14, 0x22, 0x41, + 0x14, 0x14, 0x14, 0x14, 0x14, + 0x00, 0x41, 0x22, 0x14, 0x08, + 0x02, 0x01, 0x59, 0x09, 0x06, + 0x3E, 0x41, 0x5D, 0x59, 0x4E, + 0x7C, 0x12, 0x11, 0x12, 0x7C, + 0x7F, 0x49, 0x49, 0x49, 0x36, + 0x3E, 0x41, 0x41, 0x41, 0x22, + 0x7F, 0x41, 0x41, 0x41, 0x3E, + 0x7F, 0x49, 0x49, 0x49, 0x41, + 0x7F, 0x09, 0x09, 0x09, 0x01, + 0x3E, 0x41, 0x41, 0x51, 0x73, + 0x7F, 0x08, 0x08, 0x08, 0x7F, + 0x00, 0x41, 0x7F, 0x41, 0x00, + 0x20, 0x40, 0x41, 0x3F, 0x01, + 0x7F, 0x08, 0x14, 0x22, 0x41, + 0x7F, 0x40, 0x40, 0x40, 0x40, + 0x7F, 0x02, 0x1C, 0x02, 0x7F, + 0x7F, 0x04, 0x08, 0x10, 0x7F, + 0x3E, 0x41, 0x41, 0x41, 0x3E, + 0x7F, 0x09, 0x09, 0x09, 0x06, + 0x3E, 0x41, 0x51, 0x21, 0x5E, + 0x7F, 0x09, 0x19, 0x29, 0x46, + 0x26, 0x49, 0x49, 0x49, 0x32, + 0x03, 0x01, 0x7F, 0x01, 0x03, + 0x3F, 0x40, 0x40, 0x40, 0x3F, + 0x1F, 0x20, 0x40, 0x20, 0x1F, + 0x3F, 0x40, 0x38, 0x40, 0x3F, + 0x63, 0x14, 0x08, 0x14, 0x63, + 0x03, 0x04, 0x78, 0x04, 0x03, + 0x61, 0x59, 0x49, 0x4D, 0x43, + 0x00, 0x7F, 0x41, 0x41, 0x41, + 0x02, 0x04, 0x08, 0x10, 0x20, + 0x00, 0x41, 0x41, 0x41, 0x7F, + 0x04, 0x02, 0x01, 0x02, 0x04, + 0x40, 0x40, 0x40, 0x40, 0x40, + 0x00, 0x03, 0x07, 0x08, 0x00, + 0x20, 0x54, 0x54, 0x78, 0x40, + 0x7F, 0x28, 0x44, 0x44, 0x38, + 0x38, 0x44, 0x44, 0x44, 0x28, + 0x38, 0x44, 0x44, 0x28, 0x7F, + 0x38, 0x54, 0x54, 0x54, 0x18, + 0x00, 0x08, 0x7E, 0x09, 0x02, + 0x18, 0xA4, 0xA4, 0x9C, 0x78, + 0x7F, 0x08, 0x04, 0x04, 0x78, + 0x00, 0x44, 0x7D, 0x40, 0x00, + 0x20, 0x40, 0x40, 0x3D, 0x00, + 0x7F, 0x10, 0x28, 0x44, 0x00, + 0x00, 0x41, 0x7F, 0x40, 0x00, + 0x7C, 0x04, 0x78, 0x04, 0x78, + 0x7C, 0x08, 0x04, 0x04, 0x78, + 0x38, 0x44, 0x44, 0x44, 0x38, + 0xFC, 0x18, 0x24, 0x24, 0x18, + 0x18, 0x24, 0x24, 0x18, 0xFC, + 0x7C, 0x08, 0x04, 0x04, 0x08, + 0x48, 0x54, 0x54, 0x54, 0x24, + 0x04, 0x04, 0x3F, 0x44, 0x24, + 0x3C, 0x40, 0x40, 0x20, 0x7C, + 0x1C, 0x20, 0x40, 0x20, 0x1C, + 0x3C, 0x40, 0x30, 0x40, 0x3C, + 0x44, 0x28, 0x10, 0x28, 0x44, + 0x4C, 0x90, 0x90, 0x90, 0x7C, + 0x44, 0x64, 0x54, 0x4C, 0x44, + 0x00, 0x08, 0x36, 0x41, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, + 0x00, 0x41, 0x36, 0x08, 0x00, + 0x02, 0x01, 0x02, 0x04, 0x02, + 0x3C, 0x26, 0x23, 0x26, 0x3C, + 0x1E, 0xA1, 0xA1, 0x61, 0x12, + 0x3A, 0x40, 0x40, 0x20, 0x7A, + 0x38, 0x54, 0x54, 0x55, 0x59, + 0x21, 0x55, 0x55, 0x79, 0x41, + 0x22, 0x54, 0x54, 0x78, 0x42, // a-umlaut + 0x21, 0x55, 0x54, 0x78, 0x40, + 0x20, 0x54, 0x55, 0x79, 0x40, + 0x0C, 0x1E, 0x52, 0x72, 0x12, + 0x39, 0x55, 0x55, 0x55, 0x59, + 0x39, 0x54, 0x54, 0x54, 0x59, + 0x39, 0x55, 0x54, 0x54, 0x58, + 0x00, 0x00, 0x45, 0x7C, 0x41, + 0x00, 0x02, 0x45, 0x7D, 0x42, + 0x00, 0x01, 0x45, 0x7C, 0x40, + 0x7D, 0x12, 0x11, 0x12, 0x7D, // A-umlaut + 0xF0, 0x28, 0x25, 0x28, 0xF0, + 0x7C, 0x54, 0x55, 0x45, 0x00, + 0x20, 0x54, 0x54, 0x7C, 0x54, + 0x7C, 0x0A, 0x09, 0x7F, 0x49, + 0x32, 0x49, 0x49, 0x49, 0x32, + 0x3A, 0x44, 0x44, 0x44, 0x3A, // o-umlaut + 0x32, 0x4A, 0x48, 0x48, 0x30, + 0x3A, 0x41, 0x41, 0x21, 0x7A, + 0x3A, 0x42, 0x40, 0x20, 0x78, + 0x00, 0x9D, 0xA0, 0xA0, 0x7D, + 0x3D, 0x42, 0x42, 0x42, 0x3D, // O-umlaut + 0x3D, 0x40, 0x40, 0x40, 0x3D, + 0x3C, 0x24, 0xFF, 0x24, 0x24, + 0x48, 0x7E, 0x49, 0x43, 0x66, + 0x2B, 0x2F, 0xFC, 0x2F, 0x2B, + 0xFF, 0x09, 0x29, 0xF6, 0x20, + 0xC0, 0x88, 0x7E, 0x09, 0x03, + 0x20, 0x54, 0x54, 0x79, 0x41, + 0x00, 0x00, 0x44, 0x7D, 0x41, + 0x30, 0x48, 0x48, 0x4A, 0x32, + 0x38, 0x40, 0x40, 0x22, 0x7A, + 0x00, 0x7A, 0x0A, 0x0A, 0x72, + 0x7D, 0x0D, 0x19, 0x31, 0x7D, + 0x26, 0x29, 0x29, 0x2F, 0x28, + 0x26, 0x29, 0x29, 0x29, 0x26, + 0x30, 0x48, 0x4D, 0x40, 0x20, + 0x38, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x38, + 0x2F, 0x10, 0xC8, 0xAC, 0xBA, + 0x2F, 0x10, 0x28, 0x34, 0xFA, + 0x00, 0x00, 0x7B, 0x00, 0x00, + 0x08, 0x14, 0x2A, 0x14, 0x22, + 0x22, 0x14, 0x2A, 0x14, 0x08, + 0xAA, 0x00, 0x55, 0x00, 0xAA, + 0xAA, 0x55, 0xAA, 0x55, 0xAA, + 0x00, 0x00, 0x00, 0xFF, 0x00, + 0x10, 0x10, 0x10, 0xFF, 0x00, + 0x14, 0x14, 0x14, 0xFF, 0x00, + 0x10, 0x10, 0xFF, 0x00, 0xFF, + 0x10, 0x10, 0xF0, 0x10, 0xF0, + 0x14, 0x14, 0x14, 0xFC, 0x00, + 0x14, 0x14, 0xF7, 0x00, 0xFF, + 0x00, 0x00, 0xFF, 0x00, 0xFF, + 0x14, 0x14, 0xF4, 0x04, 0xFC, + 0x14, 0x14, 0x17, 0x10, 0x1F, + 0x10, 0x10, 0x1F, 0x10, 0x1F, + 0x14, 0x14, 0x14, 0x1F, 0x00, + 0x10, 0x10, 0x10, 0xF0, 0x00, + 0x00, 0x00, 0x00, 0x1F, 0x10, + 0x10, 0x10, 0x10, 0x1F, 0x10, + 0x10, 0x10, 0x10, 0xF0, 0x10, + 0x00, 0x00, 0x00, 0xFF, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0xFF, 0x10, + 0x00, 0x00, 0x00, 0xFF, 0x14, + 0x00, 0x00, 0xFF, 0x00, 0xFF, + 0x00, 0x00, 0x1F, 0x10, 0x17, + 0x00, 0x00, 0xFC, 0x04, 0xF4, + 0x14, 0x14, 0x17, 0x10, 0x17, + 0x14, 0x14, 0xF4, 0x04, 0xF4, + 0x00, 0x00, 0xFF, 0x00, 0xF7, + 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0xF7, 0x00, 0xF7, + 0x14, 0x14, 0x14, 0x17, 0x14, + 0x10, 0x10, 0x1F, 0x10, 0x1F, + 0x14, 0x14, 0x14, 0xF4, 0x14, + 0x10, 0x10, 0xF0, 0x10, 0xF0, + 0x00, 0x00, 0x1F, 0x10, 0x1F, + 0x00, 0x00, 0x00, 0x1F, 0x14, + 0x00, 0x00, 0x00, 0xFC, 0x14, + 0x00, 0x00, 0xF0, 0x10, 0xF0, + 0x10, 0x10, 0xFF, 0x10, 0xFF, + 0x14, 0x14, 0x14, 0xFF, 0x14, + 0x10, 0x10, 0x10, 0x1F, 0x00, + 0x00, 0x00, 0x00, 0xF0, 0x10, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0xFF, 0xFF, 0xFF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFF, 0xFF, + 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, + 0x38, 0x44, 0x44, 0x38, 0x44, + 0xFC, 0x4A, 0x4A, 0x4A, 0x34, // sharp-s or beta + 0x7E, 0x02, 0x02, 0x06, 0x06, + 0x02, 0x7E, 0x02, 0x7E, 0x02, + 0x63, 0x55, 0x49, 0x41, 0x63, + 0x38, 0x44, 0x44, 0x3C, 0x04, + 0x40, 0x7E, 0x20, 0x1E, 0x20, + 0x06, 0x02, 0x7E, 0x02, 0x02, + 0x99, 0xA5, 0xE7, 0xA5, 0x99, + 0x1C, 0x2A, 0x49, 0x2A, 0x1C, + 0x4C, 0x72, 0x01, 0x72, 0x4C, + 0x30, 0x4A, 0x4D, 0x4D, 0x30, + 0x30, 0x48, 0x78, 0x48, 0x30, + 0xBC, 0x62, 0x5A, 0x46, 0x3D, + 0x3E, 0x49, 0x49, 0x49, 0x00, + 0x7E, 0x01, 0x01, 0x01, 0x7E, + 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, + 0x44, 0x44, 0x5F, 0x44, 0x44, + 0x40, 0x51, 0x4A, 0x44, 0x40, + 0x40, 0x44, 0x4A, 0x51, 0x40, + 0x00, 0x00, 0xFF, 0x01, 0x03, + 0xE0, 0x80, 0xFF, 0x00, 0x00, 0x08, 0x08, 0x6B, 0x6B, 0x08, 0x36, 0x12, 0x36, 0x24, 0x36, 0x06, 0x0F, 0x09, 0x0F, 0x06, diff --git a/libraries/Adafruit_PCD8544/Adafruit_PCD8544.cpp b/libraries/Adafruit_PCD8544/Adafruit_PCD8544.cpp index a3d9cf2..f9a957c 100644 --- a/libraries/Adafruit_PCD8544/Adafruit_PCD8544.cpp +++ b/libraries/Adafruit_PCD8544/Adafruit_PCD8544.cpp @@ -104,9 +104,40 @@ Adafruit_PCD8544::Adafruit_PCD8544(int8_t SCLK, int8_t DIN, int8_t DC, _cs = -1; } +Adafruit_PCD8544::Adafruit_PCD8544(int8_t DC, int8_t CS, int8_t RST): + Adafruit_GFX(LCDWIDTH, LCDHEIGHT) { + // -1 for din and sclk specify using hardware SPI + _din = -1; + _sclk = -1; + _dc = DC; + _rst = RST; + _cs = CS; +} + // the most basic function, set a single pixel void Adafruit_PCD8544::drawPixel(int16_t x, int16_t y, uint16_t color) { + if ((x < 0) || (x >= _width) || (y < 0) || (y >= _height)) + return; + + int16_t t; + switch(rotation){ + case 1: + t = x; + x = y; + y = LCDHEIGHT - 1 - t; + break; + case 2: + x = LCDWIDTH - 1 - x; + y = LCDHEIGHT - 1 - y; + break; + case 3: + t = x; + x = LCDWIDTH - 1 - y; + y = t; + break; + } + if ((x < 0) || (x >= LCDWIDTH) || (y < 0) || (y >= LCDHEIGHT)) return; @@ -129,15 +160,34 @@ uint8_t Adafruit_PCD8544::getPixel(int8_t x, int8_t y) { } -void Adafruit_PCD8544::begin(uint8_t contrast) { - // set pin directions - pinMode(_din, OUTPUT); - pinMode(_sclk, OUTPUT); +void Adafruit_PCD8544::begin(uint8_t contrast, uint8_t bias) { + if (isHardwareSPI()) { + // Setup hardware SPI. + SPI.begin(); + SPI.setClockDivider(PCD8544_SPI_CLOCK_DIV); + SPI.setDataMode(SPI_MODE0); + SPI.setBitOrder(MSBFIRST); + } + else { + // Setup software SPI. + + // Set software SPI specific pin outputs. + pinMode(_din, OUTPUT); + pinMode(_sclk, OUTPUT); + + // Set software SPI ports and masks. + clkport = portOutputRegister(digitalPinToPort(_sclk)); + clkpinmask = digitalPinToBitMask(_sclk); + mosiport = portOutputRegister(digitalPinToPort(_din)); + mosipinmask = digitalPinToBitMask(_din); + } + + // Set common pin outputs. pinMode(_dc, OUTPUT); if (_rst > 0) - pinMode(_rst, OUTPUT); + pinMode(_rst, OUTPUT); if (_cs > 0) - pinMode(_cs, OUTPUT); + pinMode(_cs, OUTPUT); // toggle RST low to reset if (_rst > 0) { @@ -146,20 +196,11 @@ void Adafruit_PCD8544::begin(uint8_t contrast) { digitalWrite(_rst, HIGH); } - clkport = portOutputRegister(digitalPinToPort(_sclk)); - clkpinmask = digitalPinToBitMask(_sclk); - mosiport = portOutputRegister(digitalPinToPort(_din)); - mosipinmask = digitalPinToBitMask(_din); - csport = portOutputRegister(digitalPinToPort(_cs)); - cspinmask = digitalPinToBitMask(_cs); - dcport = portOutputRegister(digitalPinToPort(_dc)); - dcpinmask = digitalPinToBitMask(_dc); - // get into the EXTENDED mode! command(PCD8544_FUNCTIONSET | PCD8544_EXTENDEDINSTRUCTION ); // LCD bias select (4 is optimal?) - command(PCD8544_SETBIAS | 0x4); + command(PCD8544_SETBIAS | bias); // set VOP if (contrast > 0x7f) @@ -187,25 +228,31 @@ void Adafruit_PCD8544::begin(uint8_t contrast) { } -inline void Adafruit_PCD8544::fastSPIwrite(uint8_t d) { - - for(uint8_t bit = 0x80; bit; bit >>= 1) { - *clkport &= ~clkpinmask; - if(d & bit) *mosiport |= mosipinmask; - else *mosiport &= ~mosipinmask; - *clkport |= clkpinmask; +inline void Adafruit_PCD8544::spiWrite(uint8_t d) { + if (isHardwareSPI()) { + // Hardware SPI write. + SPI.transfer(d); + } + else { + // Software SPI write with bit banging. + for(uint8_t bit = 0x80; bit; bit >>= 1) { + *clkport &= ~clkpinmask; + if(d & bit) *mosiport |= mosipinmask; + else *mosiport &= ~mosipinmask; + *clkport |= clkpinmask; + } } } -inline void Adafruit_PCD8544::slowSPIwrite(uint8_t c) { - shiftOut(_din, _sclk, MSBFIRST, c); +bool Adafruit_PCD8544::isHardwareSPI() { + return (_din == -1 && _sclk == -1); } void Adafruit_PCD8544::command(uint8_t c) { digitalWrite(_dc, LOW); if (_cs > 0) digitalWrite(_cs, LOW); - fastSPIwrite(c); + spiWrite(c); if (_cs > 0) digitalWrite(_cs, HIGH); } @@ -214,7 +261,7 @@ void Adafruit_PCD8544::data(uint8_t c) { digitalWrite(_dc, HIGH); if (_cs > 0) digitalWrite(_cs, LOW); - fastSPIwrite(c); + spiWrite(c); if (_cs > 0) digitalWrite(_cs, HIGH); } @@ -242,7 +289,7 @@ void Adafruit_PCD8544::display(void) { } if (yUpdateMax < p*8) { break; - }d + } #endif command(PCD8544_SETYADDR | p); @@ -263,9 +310,7 @@ void Adafruit_PCD8544::display(void) { if (_cs > 0) digitalWrite(_cs, LOW); for(; col <= maxcol; col++) { - //uart_putw_dec(col); - //uart_putchar(' '); - fastSPIwrite(pcd8544_buffer[(LCDWIDTH*p)+col]); + spiWrite(pcd8544_buffer[(LCDWIDTH*p)+col]); } if (_cs > 0) digitalWrite(_cs, HIGH); diff --git a/libraries/Adafruit_PCD8544/Adafruit_PCD8544.h b/libraries/Adafruit_PCD8544/Adafruit_PCD8544.h index 1e234f5..8dda9a7 100644 --- a/libraries/Adafruit_PCD8544/Adafruit_PCD8544.h +++ b/libraries/Adafruit_PCD8544/Adafruit_PCD8544.h @@ -15,6 +15,8 @@ Written by Limor Fried/Ladyada for Adafruit Industries. BSD license, check license.txt for more information All text above, and the splash screen must be included in any redistribution *********************************************************************/ +#ifndef _ADAFRUIT_PCD8544_H +#define _ADAFRUIT_PCD8544_H #if defined(ARDUINO) && ARDUINO >= 100 #include "Arduino.h" @@ -23,6 +25,8 @@ All text above, and the splash screen must be included in any redistribution #include "pins_arduino.h" #endif +#include + #define BLACK 1 #define WHITE 0 @@ -49,12 +53,21 @@ All text above, and the splash screen must be included in any redistribution #define PCD8544_SETBIAS 0x10 #define PCD8544_SETVOP 0x80 +// Default to max SPI clock speed for PCD8544 of 4 mhz (16mhz / 4) for normal Arduinos. +// This can be modified to change the clock speed if necessary (like for supporting other hardware). +#define PCD8544_SPI_CLOCK_DIV SPI_CLOCK_DIV4 + class Adafruit_PCD8544 : public Adafruit_GFX { public: + // Software SPI with explicit CS pin. Adafruit_PCD8544(int8_t SCLK, int8_t DIN, int8_t DC, int8_t CS, int8_t RST); + // Software SPI with CS tied to ground. Saves a pin but other pins can't be shared with other hardware. Adafruit_PCD8544(int8_t SCLK, int8_t DIN, int8_t DC, int8_t RST); + // Hardware SPI based on hardware controlled SCK (SCLK) and MOSI (DIN) pins. CS is still controlled by any IO pin. + // NOTE: MISO and SS will be set as an input and output respectively, so be careful sharing those pins! + Adafruit_PCD8544(int8_t DC, int8_t CS, int8_t RST); - void begin(uint8_t contrast = 40); + void begin(uint8_t contrast = 40, uint8_t bias = 0x04); void command(uint8_t c); void data(uint8_t c); @@ -68,9 +81,11 @@ class Adafruit_PCD8544 : public Adafruit_GFX { private: int8_t _din, _sclk, _dc, _rst, _cs; - volatile uint8_t *mosiport, *clkport, *csport, *dcport; - uint8_t mosipinmask, clkpinmask, cspinmask, dcpinmask; + volatile uint8_t *mosiport, *clkport; + uint8_t mosipinmask, clkpinmask; - void slowSPIwrite(uint8_t c); - void fastSPIwrite(uint8_t c); + void spiWrite(uint8_t c); + bool isHardwareSPI(); }; + +#endif diff --git a/libraries/Adafruit_PCD8544/examples/pcdtest/pcdtest.ino b/libraries/Adafruit_PCD8544/examples/pcdtest/pcdtest.ino new file mode 100644 index 0000000..2fa0ce2 --- /dev/null +++ b/libraries/Adafruit_PCD8544/examples/pcdtest/pcdtest.ino @@ -0,0 +1,350 @@ +/********************************************************************* +This is an example sketch for our Monochrome Nokia 5110 LCD Displays + + Pick one up today in the adafruit shop! + ------> http://www.adafruit.com/products/338 + +These displays use SPI to communicate, 4 or 5 pins are required to +interface + +Adafruit invests time and resources providing this open source code, +please support Adafruit and open-source hardware by purchasing +products from Adafruit! + +Written by Limor Fried/Ladyada for Adafruit Industries. +BSD license, check license.txt for more information +All text above, and the splash screen must be included in any redistribution +*********************************************************************/ + +#include +#include +#include + +// Software SPI (slower updates, more flexible pin options): +// pin 7 - Serial clock out (SCLK) +// pin 6 - Serial data out (DIN) +// pin 5 - Data/Command select (D/C) +// pin 4 - LCD chip select (CS) +// pin 3 - LCD reset (RST) +Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, 4, 3); + +// Hardware SPI (faster, but must use certain hardware pins): +// SCK is LCD serial clock (SCLK) - this is pin 13 on Arduino Uno +// MOSI is LCD DIN - this is pin 11 on an Arduino Uno +// pin 5 - Data/Command select (D/C) +// pin 4 - LCD chip select (CS) +// pin 3 - LCD reset (RST) +// Adafruit_PCD8544 display = Adafruit_PCD8544(5, 4, 3); +// Note with hardware SPI MISO and SS pins aren't used but will still be read +// and written to during SPI transfer. Be careful sharing these pins! + +#define NUMFLAKES 10 +#define XPOS 0 +#define YPOS 1 +#define DELTAY 2 + + +#define LOGO16_GLCD_HEIGHT 16 +#define LOGO16_GLCD_WIDTH 16 + +static const unsigned char PROGMEM logo16_glcd_bmp[] = +{ B00000000, B11000000, + B00000001, B11000000, + B00000001, B11000000, + B00000011, B11100000, + B11110011, B11100000, + B11111110, B11111000, + B01111110, B11111111, + B00110011, B10011111, + B00011111, B11111100, + B00001101, B01110000, + B00011011, B10100000, + B00111111, B11100000, + B00111111, B11110000, + B01111100, B11110000, + B01110000, B01110000, + B00000000, B00110000 }; + +void setup() { + Serial.begin(9600); + + display.begin(); + // init done + + // you can change the contrast around to adapt the display + // for the best viewing! + display.setContrast(50); + + display.display(); // show splashscreen + delay(2000); + display.clearDisplay(); // clears the screen and buffer + + // draw a single pixel + display.drawPixel(10, 10, BLACK); + display.display(); + delay(2000); + display.clearDisplay(); + + // draw many lines + testdrawline(); + display.display(); + delay(2000); + display.clearDisplay(); + + // draw rectangles + testdrawrect(); + display.display(); + delay(2000); + display.clearDisplay(); + + // draw multiple rectangles + testfillrect(); + display.display(); + delay(2000); + display.clearDisplay(); + + // draw mulitple circles + testdrawcircle(); + display.display(); + delay(2000); + display.clearDisplay(); + + // draw a circle, 10 pixel radius + display.fillCircle(display.width()/2, display.height()/2, 10, BLACK); + display.display(); + delay(2000); + display.clearDisplay(); + + testdrawroundrect(); + delay(2000); + display.clearDisplay(); + + testfillroundrect(); + delay(2000); + display.clearDisplay(); + + testdrawtriangle(); + delay(2000); + display.clearDisplay(); + + testfilltriangle(); + delay(2000); + display.clearDisplay(); + + // draw the first ~12 characters in the font + testdrawchar(); + display.display(); + delay(2000); + display.clearDisplay(); + + // text display tests + display.setTextSize(1); + display.setTextColor(BLACK); + display.setCursor(0,0); + display.println("Hello, world!"); + display.setTextColor(WHITE, BLACK); // 'inverted' text + display.println(3.141592); + display.setTextSize(2); + display.setTextColor(BLACK); + display.print("0x"); display.println(0xDEADBEEF, HEX); + display.display(); + delay(2000); + + // rotation example + display.clearDisplay(); + display.setRotation(1); // rotate 90 degrees counter clockwise, can also use values of 2 and 3 to go further. + display.setTextSize(1); + display.setTextColor(BLACK); + display.setCursor(0,0); + display.println("Rotation"); + display.setTextSize(2); + display.println("Example!"); + display.display(); + delay(2000); + + // revert back to no rotation + display.setRotation(0); + + // miniature bitmap display + display.clearDisplay(); + display.drawBitmap(30, 16, logo16_glcd_bmp, 16, 16, 1); + display.display(); + + // invert the display + display.invertDisplay(true); + delay(1000); + display.invertDisplay(false); + delay(1000); + + // draw a bitmap icon and 'animate' movement + testdrawbitmap(logo16_glcd_bmp, LOGO16_GLCD_WIDTH, LOGO16_GLCD_HEIGHT); +} + + +void loop() { + +} + + +void testdrawbitmap(const uint8_t *bitmap, uint8_t w, uint8_t h) { + uint8_t icons[NUMFLAKES][3]; + srandom(666); // whatever seed + + // initialize + for (uint8_t f=0; f< NUMFLAKES; f++) { + icons[f][XPOS] = random() % display.width(); + icons[f][YPOS] = 0; + icons[f][DELTAY] = random() % 5 + 1; + + Serial.print("x: "); + Serial.print(icons[f][XPOS], DEC); + Serial.print(" y: "); + Serial.print(icons[f][YPOS], DEC); + Serial.print(" dy: "); + Serial.println(icons[f][DELTAY], DEC); + } + + while (1) { + // draw each icon + for (uint8_t f=0; f< NUMFLAKES; f++) { + display.drawBitmap(icons[f][XPOS], icons[f][YPOS], logo16_glcd_bmp, w, h, BLACK); + } + display.display(); + delay(200); + + // then erase it + move it + for (uint8_t f=0; f< NUMFLAKES; f++) { + display.drawBitmap(icons[f][XPOS], icons[f][YPOS], logo16_glcd_bmp, w, h, WHITE); + // move it + icons[f][YPOS] += icons[f][DELTAY]; + // if its gone, reinit + if (icons[f][YPOS] > display.height()) { + icons[f][XPOS] = random() % display.width(); + icons[f][YPOS] = 0; + icons[f][DELTAY] = random() % 5 + 1; + } + } + } +} + + +void testdrawchar(void) { + display.setTextSize(1); + display.setTextColor(BLACK); + display.setCursor(0,0); + + for (uint8_t i=0; i < 168; i++) { + if (i == '\n') continue; + display.write(i); + //if ((i > 0) && (i % 14 == 0)) + //display.println(); + } + display.display(); +} + +void testdrawcircle(void) { + for (int16_t i=0; i0; i-=5) { + display.fillTriangle(display.width()/2, display.height()/2-i, + display.width()/2-i, display.height()/2+i, + display.width()/2+i, display.height()/2+i, color); + if (color == WHITE) color = BLACK; + else color = WHITE; + display.display(); + } +} + +void testdrawroundrect(void) { + for (int16_t i=0; i=0; i-=4) { + display.drawLine(0, display.height()-1, display.width()-1, i, BLACK); + display.display(); + } + delay(250); + + display.clearDisplay(); + for (int16_t i=display.width()-1; i>=0; i-=4) { + display.drawLine(display.width()-1, display.height()-1, i, 0, BLACK); + display.display(); + } + for (int16_t i=display.height()-1; i>=0; i-=4) { + display.drawLine(display.width()-1, display.height()-1, 0, i, BLACK); + display.display(); + } + delay(250); + + display.clearDisplay(); + for (int16_t i=0; i= 100) #include // capital A so it is error prone on case-sensitive filesystems + // Macro to deal with the difference in I2C write functions from old and new Arduino versions. + #define _I2C_WRITE write + #define _I2C_READ read #else #include + #define _I2C_WRITE send + #define _I2C_READ receive #endif //////////////////////////////////////////////////////////////////////////////// @@ -86,6 +93,15 @@ DateTime::DateTime (uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uin ss = sec; } +DateTime::DateTime (const DateTime& copy): + yOff(copy.yOff), + m(copy.m), + d(copy.d), + hh(copy.hh), + mm(copy.mm), + ss(copy.ss) +{} + static uint8_t conv2d(const char* p) { uint8_t v = 0; if ('0' <= *p && *p <= '9') @@ -95,7 +111,7 @@ static uint8_t conv2d(const char* p) { // A convenient constructor for using "the compiler's time": // DateTime now (__DATE__, __TIME__); -// NOTE: using PSTR would further reduce the RAM footprint +// NOTE: using F() would further reduce the RAM footprint, see below. DateTime::DateTime (const char* date, const char* time) { // sample input: date = "Dec 26 2009", time = "12:34:56" yOff = conv2d(date + 9); @@ -116,6 +132,32 @@ DateTime::DateTime (const char* date, const char* time) { ss = conv2d(time + 6); } +// A convenient constructor for using "the compiler's time": +// This version will save RAM by using PROGMEM to store it by using the F macro. +// DateTime now (F(__DATE__), F(__TIME__)); +DateTime::DateTime (const __FlashStringHelper* date, const __FlashStringHelper* time) { + // sample input: date = "Dec 26 2009", time = "12:34:56" + char buff[11]; + memcpy_P(buff, date, 11); + yOff = conv2d(buff + 9); + // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec + switch (buff[0]) { + case 'J': m = buff[1] == 'a' ? 1 : m = buff[2] == 'n' ? 6 : 7; break; + case 'F': m = 2; break; + case 'A': m = buff[2] == 'r' ? 4 : 8; break; + case 'M': m = buff[2] == 'r' ? 3 : 5; break; + case 'S': m = 9; break; + case 'O': m = 10; break; + case 'N': m = 11; break; + case 'D': m = 12; break; + } + d = conv2d(buff + 4); + memcpy_P(buff, time, 8); + hh = conv2d(buff); + mm = conv2d(buff + 3); + ss = conv2d(buff + 6); +} + uint8_t DateTime::dayOfWeek() const { uint16_t day = date2days(yOff, m, d); return (day + 6) % 7; // Jan 1, 2000 is a Saturday, i.e. returns 6 @@ -130,6 +172,48 @@ uint32_t DateTime::unixtime(void) const { return t; } +long DateTime::secondstime(void) const { + long t; + uint16_t days = date2days(yOff, m, d); + t = time2long(days, hh, mm, ss); + return t; +} + +DateTime DateTime::operator+(const TimeSpan& span) { + return DateTime(unixtime()+span.totalseconds()); +} + +DateTime DateTime::operator-(const TimeSpan& span) { + return DateTime(unixtime()-span.totalseconds()); +} + +TimeSpan DateTime::operator-(const DateTime& right) { + return TimeSpan(unixtime()-right.unixtime()); +} + +//////////////////////////////////////////////////////////////////////////////// +// TimeSpan implementation + +TimeSpan::TimeSpan (int32_t seconds): + _seconds(seconds) +{} + +TimeSpan::TimeSpan (int16_t days, int8_t hours, int8_t minutes, int8_t seconds): + _seconds(days*86400L + hours*3600 + minutes*60 + seconds) +{} + +TimeSpan::TimeSpan (const TimeSpan& copy): + _seconds(copy._seconds) +{} + +TimeSpan TimeSpan::operator+(const TimeSpan& right) { + return TimeSpan(_seconds+right._seconds); +} + +TimeSpan TimeSpan::operator-(const TimeSpan& right) { + return TimeSpan(_seconds-right._seconds); +} + //////////////////////////////////////////////////////////////////////////////// // RTC_DS1307 implementation @@ -140,95 +224,99 @@ uint8_t RTC_DS1307::begin(void) { return 1; } - -#if (ARDUINO >= 100) - uint8_t RTC_DS1307::isrunning(void) { WIRE.beginTransmission(DS1307_ADDRESS); - WIRE.write(0); + WIRE._I2C_WRITE(0); WIRE.endTransmission(); WIRE.requestFrom(DS1307_ADDRESS, 1); - uint8_t ss = WIRE.read(); + uint8_t ss = WIRE._I2C_READ(); return !(ss>>7); } void RTC_DS1307::adjust(const DateTime& dt) { - WIRE.beginTransmission(DS1307_ADDRESS); - WIRE.write(0); - WIRE.write(bin2bcd(dt.second())); - WIRE.write(bin2bcd(dt.minute())); - WIRE.write(bin2bcd(dt.hour())); - WIRE.write(bin2bcd(0)); - WIRE.write(bin2bcd(dt.day())); - WIRE.write(bin2bcd(dt.month())); - WIRE.write(bin2bcd(dt.year() - 2000)); - WIRE.write(0); - WIRE.endTransmission(); + WIRE.beginTransmission(DS1307_ADDRESS); + WIRE._I2C_WRITE(0); + WIRE._I2C_WRITE(bin2bcd(dt.second())); + WIRE._I2C_WRITE(bin2bcd(dt.minute())); + WIRE._I2C_WRITE(bin2bcd(dt.hour())); + WIRE._I2C_WRITE(bin2bcd(0)); + WIRE._I2C_WRITE(bin2bcd(dt.day())); + WIRE._I2C_WRITE(bin2bcd(dt.month())); + WIRE._I2C_WRITE(bin2bcd(dt.year() - 2000)); + WIRE._I2C_WRITE(0); + WIRE.endTransmission(); } DateTime RTC_DS1307::now() { WIRE.beginTransmission(DS1307_ADDRESS); - WIRE.write(0); + WIRE._I2C_WRITE(0); WIRE.endTransmission(); WIRE.requestFrom(DS1307_ADDRESS, 7); - uint8_t ss = bcd2bin(WIRE.read() & 0x7F); - uint8_t mm = bcd2bin(WIRE.read()); - uint8_t hh = bcd2bin(WIRE.read()); - WIRE.read(); - uint8_t d = bcd2bin(WIRE.read()); - uint8_t m = bcd2bin(WIRE.read()); - uint16_t y = bcd2bin(WIRE.read()) + 2000; + uint8_t ss = bcd2bin(WIRE._I2C_READ() & 0x7F); + uint8_t mm = bcd2bin(WIRE._I2C_READ()); + uint8_t hh = bcd2bin(WIRE._I2C_READ()); + WIRE._I2C_READ(); + uint8_t d = bcd2bin(WIRE._I2C_READ()); + uint8_t m = bcd2bin(WIRE._I2C_READ()); + uint16_t y = bcd2bin(WIRE._I2C_READ()) + 2000; return DateTime (y, m, d, hh, mm, ss); } -#else +Ds1307SqwPinMode RTC_DS1307::readSqwPinMode() { + int mode; -uint8_t RTC_DS1307::isrunning(void) { WIRE.beginTransmission(DS1307_ADDRESS); - WIRE.send(0); - WIRE.endTransmission(); - - WIRE.requestFrom(DS1307_ADDRESS, 1); - uint8_t ss = WIRE.receive(); - return !(ss>>7); -} - -void RTC_DS1307::adjust(const DateTime& dt) { - WIRE.beginTransmission(DS1307_ADDRESS); - WIRE.send(0); - WIRE.send(bin2bcd(dt.second())); - WIRE.send(bin2bcd(dt.minute())); - WIRE.send(bin2bcd(dt.hour())); - WIRE.send(bin2bcd(0)); - WIRE.send(bin2bcd(dt.day())); - WIRE.send(bin2bcd(dt.month())); - WIRE.send(bin2bcd(dt.year() - 2000)); - WIRE.send(0); - WIRE.endTransmission(); -} - -DateTime RTC_DS1307::now() { - WIRE.beginTransmission(DS1307_ADDRESS); - WIRE.send(0); + WIRE._I2C_WRITE(DS1307_CONTROL); WIRE.endTransmission(); - WIRE.requestFrom(DS1307_ADDRESS, 7); - uint8_t ss = bcd2bin(WIRE.receive() & 0x7F); - uint8_t mm = bcd2bin(WIRE.receive()); - uint8_t hh = bcd2bin(WIRE.receive()); - WIRE.receive(); - uint8_t d = bcd2bin(WIRE.receive()); - uint8_t m = bcd2bin(WIRE.receive()); - uint16_t y = bcd2bin(WIRE.receive()) + 2000; - - return DateTime (y, m, d, hh, mm, ss); + WIRE.requestFrom((uint8_t)DS1307_ADDRESS, (uint8_t)1); + mode = WIRE._I2C_READ(); + + mode &= 0x93; + return static_cast(mode); } -#endif +void RTC_DS1307::writeSqwPinMode(Ds1307SqwPinMode mode) { + WIRE.beginTransmission(DS1307_ADDRESS); + WIRE._I2C_WRITE(DS1307_CONTROL); + WIRE._I2C_WRITE(mode); + WIRE.endTransmission(); +} +void RTC_DS1307::readnvram(uint8_t* buf, uint8_t size, uint8_t address) { + int addrByte = DS1307_NVRAM + address; + WIRE.beginTransmission(DS1307_ADDRESS); + WIRE._I2C_WRITE(addrByte); + WIRE.endTransmission(); + + WIRE.requestFrom((uint8_t) DS1307_ADDRESS, size); + for (uint8_t pos = 0; pos < size; ++pos) { + buf[pos] = WIRE._I2C_READ(); + } +} + +void RTC_DS1307::writenvram(uint8_t address, uint8_t* buf, uint8_t size) { + int addrByte = DS1307_NVRAM + address; + WIRE.beginTransmission(DS1307_ADDRESS); + WIRE._I2C_WRITE(addrByte); + for (uint8_t pos = 0; pos < size; ++pos) { + WIRE._I2C_WRITE(buf[pos]); + } + WIRE.endTransmission(); +} + +uint8_t RTC_DS1307::readnvram(uint8_t address) { + uint8_t data; + readnvram(&data, 1, address); + return data; +} + +void RTC_DS1307::writenvram(uint8_t address, uint8_t data) { + writenvram(address, &data, 1); +} //////////////////////////////////////////////////////////////////////////////// // RTC_Millis implementation diff --git a/libraries/RTClib/RTClib.h b/libraries/RTClib/RTClib.h index a9301af..6d6b361 100644 --- a/libraries/RTClib/RTClib.h +++ b/libraries/RTClib/RTClib.h @@ -4,13 +4,17 @@ #ifndef _RTCLIB_H_ #define _RTCLIB_H_ +class TimeSpan; + // Simple general-purpose date/time class (no TZ / DST / leap second handling!) class DateTime { public: DateTime (uint32_t t =0); DateTime (uint16_t year, uint8_t month, uint8_t day, uint8_t hour =0, uint8_t min =0, uint8_t sec =0); + DateTime (const DateTime& copy); DateTime (const char* date, const char* time); + DateTime (const __FlashStringHelper* date, const __FlashStringHelper* time); uint16_t year() const { return 2000 + yOff; } uint8_t month() const { return m; } uint8_t day() const { return d; } @@ -24,17 +28,48 @@ public: // 32-bit times as seconds since 1/1/1970 uint32_t unixtime(void) const; + DateTime operator+(const TimeSpan& span); + DateTime operator-(const TimeSpan& span); + TimeSpan operator-(const DateTime& right); + protected: uint8_t yOff, m, d, hh, mm, ss; }; +// Timespan which can represent changes in time with seconds accuracy. +class TimeSpan { +public: + TimeSpan (int32_t seconds = 0); + TimeSpan (int16_t days, int8_t hours, int8_t minutes, int8_t seconds); + TimeSpan (const TimeSpan& copy); + int16_t days() const { return _seconds / 86400L; } + int8_t hours() const { return _seconds / 3600 % 24; } + int8_t minutes() const { return _seconds / 60 % 60; } + int8_t seconds() const { return _seconds % 60; } + int32_t totalseconds() const { return _seconds; } + + TimeSpan operator+(const TimeSpan& right); + TimeSpan operator-(const TimeSpan& right); + +protected: + int32_t _seconds; +}; + // RTC based on the DS1307 chip connected via I2C and the Wire library +enum Ds1307SqwPinMode { OFF = 0x00, ON = 0x80, SquareWave1HZ = 0x10, SquareWave4kHz = 0x11, SquareWave8kHz = 0x12, SquareWave32kHz = 0x13 }; + class RTC_DS1307 { public: static uint8_t begin(void); static void adjust(const DateTime& dt); uint8_t isrunning(void); static DateTime now(); + static Ds1307SqwPinMode readSqwPinMode(); + static void writeSqwPinMode(Ds1307SqwPinMode mode); + uint8_t readnvram(uint8_t address); + void readnvram(uint8_t* buf, uint8_t size, uint8_t address); + void writenvram(uint8_t address, uint8_t data); + void writenvram(uint8_t address, uint8_t* buf, uint8_t size); }; // RTC using the internal millis() clock, has to be initialized before use diff --git a/libraries/RTClib/examples/datecalc/datecalc.ino b/libraries/RTClib/examples/datecalc/datecalc.ino new file mode 100644 index 0000000..b148c7c --- /dev/null +++ b/libraries/RTClib/examples/datecalc/datecalc.ino @@ -0,0 +1,102 @@ +// Simple date conversions and calculations + +#include +#include "RTClib.h" + +void showDate(const char* txt, const DateTime& dt) { + Serial.print(txt); + Serial.print(' '); + Serial.print(dt.year(), DEC); + Serial.print('/'); + Serial.print(dt.month(), DEC); + Serial.print('/'); + Serial.print(dt.day(), DEC); + Serial.print(' '); + Serial.print(dt.hour(), DEC); + Serial.print(':'); + Serial.print(dt.minute(), DEC); + Serial.print(':'); + Serial.print(dt.second(), DEC); + + Serial.print(" = "); + Serial.print(dt.unixtime()); + Serial.print("s / "); + Serial.print(dt.unixtime() / 86400L); + Serial.print("d since 1970"); + + Serial.println(); +} + +void showTimeSpan(const char* txt, const TimeSpan& ts) { + Serial.print(txt); + Serial.print(" "); + Serial.print(ts.days(), DEC); + Serial.print(" days "); + Serial.print(ts.hours(), DEC); + Serial.print(" hours "); + Serial.print(ts.minutes(), DEC); + Serial.print(" minutes "); + Serial.print(ts.seconds(), DEC); + Serial.print(" seconds ("); + Serial.print(ts.totalseconds(), DEC); + Serial.print(" total seconds)"); + Serial.println(); +} + +void setup () { + Serial.begin(57600); + + DateTime dt0 (0, 1, 1, 0, 0, 0); + showDate("dt0", dt0); + + DateTime dt1 (1, 1, 1, 0, 0, 0); + showDate("dt1", dt1); + + DateTime dt2 (2009, 1, 1, 0, 0, 0); + showDate("dt2", dt2); + + DateTime dt3 (2009, 1, 2, 0, 0, 0); + showDate("dt3", dt3); + + DateTime dt4 (2009, 1, 27, 0, 0, 0); + showDate("dt4", dt4); + + DateTime dt5 (2009, 2, 27, 0, 0, 0); + showDate("dt5", dt5); + + DateTime dt6 (2009, 12, 27, 0, 0, 0); + showDate("dt6", dt6); + + DateTime dt7 (dt6.unixtime() + 3600); // One hour later. + showDate("dt7", dt7); + + DateTime dt75 = dt6 + TimeSpan(0, 1, 0, 0); // One hour later with TimeSpan addition. + showDate("dt7.5", dt75); + + DateTime dt8 (dt6.unixtime() + 86400L); // One day later. + showDate("dt8", dt8); + + DateTime dt85 = dt6 + TimeSpan(1, 0, 0, 0); // One day later with TimeSpan addition. + showDate("dt8.5", dt85); + + DateTime dt9 (dt6.unixtime() + 7 * 86400L); // One week later. + showDate("dt9", dt9); + + DateTime dt95 = dt6 + TimeSpan(7, 0, 0, 0); // One week later with TimeSpan addition. + showDate("dt9.5", dt95); + + DateTime dt10 = dt6 + TimeSpan(0, 0, 42, 42); // Fourty two minutes and fourty two seconds later. + showDate("dt10", dt10); + + DateTime dt11 = dt6 - TimeSpan(7, 0, 0, 0); // One week ago. + showDate("dt11", dt11); + + TimeSpan ts1 = dt6 - dt5; + showTimeSpan("dt6-dt5", ts1); + + TimeSpan ts2 = dt10 - dt6; + showTimeSpan("dt10-dt6", ts2); +} + +void loop () { +} diff --git a/libraries/RTClib/examples/ds1307/ds1307.ino b/libraries/RTClib/examples/ds1307/ds1307.ino new file mode 100644 index 0000000..d0e6da9 --- /dev/null +++ b/libraries/RTClib/examples/ds1307/ds1307.ino @@ -0,0 +1,68 @@ +// Date and time functions using a DS1307 RTC connected via I2C and Wire lib + +#include +#include "RTClib.h" + +RTC_DS1307 rtc; + +void setup () { + Serial.begin(57600); +#ifdef AVR + Wire.begin(); +#else + Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino Due +#endif + rtc.begin(); + + if (! rtc.isrunning()) { + Serial.println("RTC is NOT running!"); + // following line sets the RTC to the date & time this sketch was compiled + rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); + // This line sets the RTC with an explicit date & time, for example to set + // January 21, 2014 at 3am you would call: + // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); + } +} + +void loop () { + DateTime now = rtc.now(); + + Serial.print(now.year(), DEC); + Serial.print('/'); + Serial.print(now.month(), DEC); + Serial.print('/'); + Serial.print(now.day(), DEC); + Serial.print(' '); + Serial.print(now.hour(), DEC); + Serial.print(':'); + Serial.print(now.minute(), DEC); + Serial.print(':'); + Serial.print(now.second(), DEC); + Serial.println(); + + Serial.print(" since midnight 1/1/1970 = "); + Serial.print(now.unixtime()); + Serial.print("s = "); + Serial.print(now.unixtime() / 86400L); + Serial.println("d"); + + // calculate a date which is 7 days and 30 seconds into the future + DateTime future (now.unixtime() + 7 * 86400L + 30); + + Serial.print(" now + 7d + 30s: "); + Serial.print(future.year(), DEC); + Serial.print('/'); + Serial.print(future.month(), DEC); + Serial.print('/'); + Serial.print(future.day(), DEC); + Serial.print(' '); + Serial.print(future.hour(), DEC); + Serial.print(':'); + Serial.print(future.minute(), DEC); + Serial.print(':'); + Serial.print(future.second(), DEC); + Serial.println(); + + Serial.println(); + delay(3000); +} diff --git a/libraries/RTClib/examples/ds1307SqwPin/ds1307SqwPin.ino b/libraries/RTClib/examples/ds1307SqwPin/ds1307SqwPin.ino new file mode 100644 index 0000000..d092619 --- /dev/null +++ b/libraries/RTClib/examples/ds1307SqwPin/ds1307SqwPin.ino @@ -0,0 +1,56 @@ +// SQW/OUT pin mode using a DS1307 RTC connected via I2C. +// +// According to the data sheet (http://datasheets.maxim-ic.com/en/ds/DS1307.pdf), the +// DS1307's SQW/OUT pin can be set to low, high, 1Hz, 4.096kHz, 8.192kHz, or 32.768kHz. +// +// This sketch reads the state of the pin, then iterates through the possible values at +// 5 second intervals. +// + +// NOTE: +// You must connect a pull up resistor (~10kohm) from the SQW pin up to VCC. Without +// this pull up the wave output will not work! + +#include +#include "RTClib.h" + +RTC_DS1307 rtc; + +int mode_index = 0; + +Ds1307SqwPinMode modes[] = {OFF, ON, SquareWave1HZ, SquareWave4kHz, SquareWave8kHz, SquareWave32kHz}; + + +void print_mode() { + Ds1307SqwPinMode mode = rtc.readSqwPinMode(); + + Serial.print("Sqw Pin Mode: "); + switch(mode) { + case OFF: Serial.println("OFF"); break; + case ON: Serial.println("ON"); break; + case SquareWave1HZ: Serial.println("1Hz"); break; + case SquareWave4kHz: Serial.println("4.096kHz"); break; + case SquareWave8kHz: Serial.println("8.192kHz"); break; + case SquareWave32kHz: Serial.println("32.768kHz"); break; + default: Serial.println("UNKNOWN"); break; + } +} + +void setup () { + Serial.begin(57600); + Wire.begin(); + rtc.begin(); + + print_mode(); +} + +void loop () { + rtc.writeSqwPinMode(modes[mode_index++]); + print_mode(); + + if (mode_index > 5) { + mode_index = 0; + } + + delay(5000); +} diff --git a/libraries/RTClib/examples/ds1307nvram/ds1307nvram.ino b/libraries/RTClib/examples/ds1307nvram/ds1307nvram.ino new file mode 100644 index 0000000..9f80346 --- /dev/null +++ b/libraries/RTClib/examples/ds1307nvram/ds1307nvram.ino @@ -0,0 +1,59 @@ +// Example of using the non-volatile RAM storage on the DS1307. +// You can write up to 56 bytes from address 0 to 55. +// Data will be persisted as long as the DS1307 has battery power. + +#include +#include "RTClib.h" + +RTC_DS1307 rtc; + +void printnvram(uint8_t address) { + Serial.print("Address 0x"); + Serial.print(address, HEX); + Serial.print(" = 0x"); + Serial.println(rtc.readnvram(address), HEX); +} + +void setup () { + Serial.begin(57600); +#ifdef AVR + Wire.begin(); +#else + Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino Due +#endif + rtc.begin(); + + // Print old RAM contents on startup. + Serial.println("Current NVRAM values:"); + for (int i = 0; i < 6; ++i) { + printnvram(i); + } + + // Write some bytes to non-volatile RAM storage. + // NOTE: You can only read and write from addresses 0 to 55 (i.e. 56 byte values). + Serial.println("Writing NVRAM values."); + // Example writing one byte at a time: + rtc.writenvram(0, 0xFE); + rtc.writenvram(1, 0xED); + // Example writing multiple bytes: + uint8_t writeData[4] = { 0xBE, 0xEF, 0x01, 0x02 }; + rtc.writenvram(2, writeData, 4); + + // Read bytes from non-volatile RAM storage. + Serial.println("Reading NVRAM values:"); + // Example reading one byte at a time. + Serial.println(rtc.readnvram(0), HEX); + Serial.println(rtc.readnvram(1), HEX); + // Example reading multiple bytes: + uint8_t readData[4] = {0}; + rtc.readnvram(readData, 4, 2); + Serial.println(readData[0], HEX); + Serial.println(readData[1], HEX); + Serial.println(readData[2], HEX); + Serial.println(readData[3], HEX); + +} + +void loop () { + // Do nothing in the loop. +} diff --git a/libraries/RTClib/examples/softrtc/softrtc.ino b/libraries/RTClib/examples/softrtc/softrtc.ino new file mode 100644 index 0000000..d43ffe6 --- /dev/null +++ b/libraries/RTClib/examples/softrtc/softrtc.ino @@ -0,0 +1,55 @@ +// Date and time functions using just software, based on millis() & timer + +#include +#include "RTClib.h" + +RTC_Millis rtc; + +void setup () { + Serial.begin(57600); + // following line sets the RTC to the date & time this sketch was compiled + rtc.begin(DateTime(F(__DATE__), F(__TIME__))); + // This line sets the RTC with an explicit date & time, for example to set + // January 21, 2014 at 3am you would call: + // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); +} + +void loop () { + DateTime now = rtc.now(); + + Serial.print(now.year(), DEC); + Serial.print('/'); + Serial.print(now.month(), DEC); + Serial.print('/'); + Serial.print(now.day(), DEC); + Serial.print(' '); + Serial.print(now.hour(), DEC); + Serial.print(':'); + Serial.print(now.minute(), DEC); + Serial.print(':'); + Serial.print(now.second(), DEC); + Serial.println(); + + Serial.print(" seconds since 1970: "); + Serial.println(now.unixtime()); + + // calculate a date which is 7 days and 30 seconds into the future + DateTime future (now.unixtime() + 7 * 86400L + 30); + + Serial.print(" now + 7d + 30s: "); + Serial.print(future.year(), DEC); + Serial.print('/'); + Serial.print(future.month(), DEC); + Serial.print('/'); + Serial.print(future.day(), DEC); + Serial.print(' '); + Serial.print(future.hour(), DEC); + Serial.print(':'); + Serial.print(future.minute(), DEC); + Serial.print(':'); + Serial.print(future.second(), DEC); + Serial.println(); + + Serial.println(); + delay(3000); +} diff --git a/libraries/RTClib/keywords.txt b/libraries/RTClib/keywords.txt index f0bdeac..26cdc1e 100644 --- a/libraries/RTClib/keywords.txt +++ b/libraries/RTClib/keywords.txt @@ -9,6 +9,7 @@ DateTime KEYWORD1 RTC_DS1307 KEYWORD1 RTC_Millis KEYWORD1 +Ds1307SqwPinMode KEYWORD1 ####################################### # Methods and Functions (KEYWORD2) @@ -27,6 +28,8 @@ begin KEYWORD2 adjust KEYWORD2 isrunning KEYWORD2 now KEYWORD2 +readSqwPinMode KEYWORD2 +writeSqwPinMode KEYWORD2 ####################################### # Constants (LITERAL1)