Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: DebouncedInterrupt SharpLCD_LucidaFont mbed-src
Fork of Renard_UI_Only by
Revision 0:9bea6067730f, committed 2014-07-02
- Comitter:
- erigow01
- Date:
- Wed Jul 02 13:19:34 2014 +0000
- Child:
- 1:f0635f12df8c
- Commit message:
- Basic UI working - needs some additional work on Icons, Layout
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DebouncedInterrupt.lib Wed Jul 02 13:19:34 2014 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/kandangath/code/DebouncedInterrupt/#9733f886810a
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/EaEpaper/EPD.cpp Wed Jul 02 13:19:34 2014 +0000
@@ -0,0 +1,612 @@
+// Copyright 2013 Pervasive Displays, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+// express or implied. See the License for the specific language
+// governing permissions and limitations under the License.
+
+
+
+#include <limits.h>
+
+#include "EPD.h"
+#include "mbed.h"
+
+
+// delays - more consistent naming
+#define Delay_ms(ms) wait_ms(ms)
+#define Delay_us(us) wait_us(us)
+
+// inline arrays
+#define ARRAY(type, ...) ((type[]){__VA_ARGS__})
+#define CU8(...) (ARRAY(const uint8_t, __VA_ARGS__))
+
+#define LOW (0)
+#define HIGH (1)
+#define digitalWrite(pin, state) (pin) = (state)
+#define digitalRead(pin) (pin)
+
+Timer _time;
+#define millis() _time.read_ms()
+#define millis_start() _time.start()
+
+
+//static void PWM_start(int pin);
+//static void PWM_stop(int pin);
+
+//static void SPI_put(uint8_t c);
+//static void SPI_put_wait(uint8_t c, int busy_pin);
+//static void SPI_send(uint8_t cs_pin, const uint8_t *buffer, uint16_t length);
+
+
+EPD_Class::EPD_Class(EPD_size size,
+ PinName panel_on_pin,
+ PinName border_pin,
+ PinName discharge_pin,
+ PinName pwm_pin,
+ PinName reset_pin,
+ PinName busy_pin,
+ PinName chip_select_pin,
+ PinName mosi,
+ PinName miso,
+ PinName sck) :
+ EPD_Pin_PANEL_ON(panel_on_pin),
+ EPD_Pin_BORDER(border_pin),
+ EPD_Pin_DISCHARGE(discharge_pin),
+ EPD_Pin_PWM(pwm_pin),
+ EPD_Pin_RESET(reset_pin),
+ EPD_Pin_BUSY(busy_pin),
+ EPD_Pin_EPD_CS(chip_select_pin),
+ spi_(mosi,miso,sck) {
+
+ this->size = size;
+ this->stage_time = 480; // milliseconds
+ this->lines_per_display = 96;
+ this->dots_per_line = 128;
+ this->bytes_per_line = 128 / 8;
+ this->bytes_per_scan = 96 / 4;
+ this->filler = false;
+ spi_.frequency(12000000); // 12 MHz SPI clock
+
+ // display size dependant items
+ {
+ static uint8_t cs[] = {0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00};
+ static uint8_t gs[] = {0x72, 0x03};
+ this->channel_select = cs;
+ this->channel_select_length = sizeof(cs);
+ this->gate_source = gs;
+ this->gate_source_length = sizeof(gs);
+ }
+
+ // set up size structure
+ switch (size) {
+ default:
+ case EPD_1_44: // default so no change
+ break;
+
+ case EPD_2_0: {
+ this->lines_per_display = 96;
+ this->dots_per_line = 200;
+ this->bytes_per_line = 200 / 8;
+ this->bytes_per_scan = 96 / 4;
+ this->filler = true;
+ static uint8_t cs[] = {0x72, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xe0, 0x00};
+ static uint8_t gs[] = {0x72, 0x03};
+ this->channel_select = cs;
+ this->channel_select_length = sizeof(cs);
+ this->gate_source = gs;
+ this->gate_source_length = sizeof(gs);
+ break;
+ }
+
+ case EPD_2_7: {
+ this->stage_time = 630; // milliseconds
+ this->lines_per_display = 176;
+ this->dots_per_line = 264;
+ this->bytes_per_line = 264 / 8;
+ this->bytes_per_scan = 176 / 4;
+ this->filler = true;
+ static uint8_t cs[] = {0x72, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xfe, 0x00, 0x00};
+ static uint8_t gs[] = {0x72, 0x00};
+ this->channel_select = cs;
+ this->channel_select_length = sizeof(cs);
+ this->gate_source = gs;
+ this->gate_source_length = sizeof(gs);
+ break;
+ }
+ }
+
+ this->factored_stage_time = this->stage_time;
+}
+
+
+void EPD_Class::begin() {
+
+ // power up sequence
+ SPI_put(0x00);
+
+ digitalWrite(this->EPD_Pin_RESET, LOW);
+ digitalWrite(this->EPD_Pin_PANEL_ON, LOW);
+ digitalWrite(this->EPD_Pin_DISCHARGE, LOW);
+ digitalWrite(this->EPD_Pin_BORDER, LOW);
+ digitalWrite(this->EPD_Pin_EPD_CS, LOW);
+
+ //PWM_start(this->EPD_Pin_PWM);
+ EPD_Pin_PWM = 0.5;
+ EPD_Pin_PWM.period_us(5);
+ Delay_ms(5);
+ digitalWrite(this->EPD_Pin_PANEL_ON, HIGH);
+ Delay_ms(10);
+
+ digitalWrite(this->EPD_Pin_RESET, HIGH);
+ digitalWrite(this->EPD_Pin_BORDER, HIGH);
+ digitalWrite(this->EPD_Pin_EPD_CS, HIGH);
+ Delay_ms(5);
+
+ digitalWrite(this->EPD_Pin_RESET, LOW);
+ Delay_ms(5);
+
+ digitalWrite(this->EPD_Pin_RESET, HIGH);
+ Delay_ms(5);
+
+ // wait for COG to become ready
+ while (HIGH == digitalRead(this->EPD_Pin_BUSY)) {
+ }
+
+ // channel select
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x01), 2);
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, this->channel_select, this->channel_select_length);
+
+ // DC/DC frequency
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x06), 2);
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0xff), 2);
+
+ // high power mode osc
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x07), 2);
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x9d), 2);
+
+
+ // disable ADC
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x08), 2);
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x00), 2);
+
+ // Vcom level
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x09), 2);
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0xd0, 0x00), 3);
+
+ // gate and source voltage levels
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x04), 2);
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, this->gate_source, this->gate_source_length);
+
+ Delay_ms(5); //???
+
+ // driver latch on
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x03), 2);
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x01), 2);
+
+ // driver latch off
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x03), 2);
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x00), 2);
+
+ Delay_ms(5);
+
+ // charge pump positive voltage on
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x05), 2);
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x01), 2);
+
+ // final delay before PWM off
+ Delay_ms(30);
+ //PWM_stop(this->EPD_Pin_PWM);
+ EPD_Pin_PWM = 0.0;
+
+ // charge pump negative voltage on
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x05), 2);
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x03), 2);
+
+ Delay_ms(30);
+
+ // Vcom driver on
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x05), 2);
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x0f), 2);
+
+ Delay_ms(30);
+
+ // output enable to disable
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x02), 2);
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x24), 2);
+}
+
+
+void EPD_Class::end() {
+
+ this->frame_fixed(0x55, EPD_normal); // dummy frame
+ this->line(0x7fffu, 0, 0x55, false, EPD_normal); // dummy_line
+
+ Delay_ms(25);
+
+ digitalWrite(this->EPD_Pin_BORDER, LOW);
+ Delay_ms(30);
+
+ digitalWrite(this->EPD_Pin_BORDER, HIGH);
+
+ // latch reset turn on
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x03), 2);
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x01), 2);
+
+ // output enable off
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x02), 2);
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x05), 2);
+
+ // Vcom power off
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x05), 2);
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x0e), 2);
+
+ // power off negative charge pump
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x05), 2);
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x02), 2);
+
+ // discharge
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x04), 2);
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x0c), 2);
+
+ Delay_ms(120);
+
+ // all charge pumps off
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x05), 2);
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x00), 2);
+
+ // turn of osc
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x07), 2);
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x0d), 2);
+
+ // discharge internal - 1
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x04), 2);
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x50), 2);
+
+ Delay_ms(40);
+
+ // discharge internal - 2
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x04), 2);
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0xA0), 2);
+
+ Delay_ms(40);
+
+ // discharge internal - 3
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x04), 2);
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x00), 2);
+
+ // turn of power and all signals
+ digitalWrite(this->EPD_Pin_RESET, LOW);
+ digitalWrite(this->EPD_Pin_PANEL_ON, LOW);
+ digitalWrite(this->EPD_Pin_BORDER, LOW);
+ digitalWrite(this->EPD_Pin_EPD_CS, LOW);
+
+ digitalWrite(this->EPD_Pin_DISCHARGE, HIGH);
+
+ SPI_put(0x00);
+
+ Delay_ms(150);
+
+ digitalWrite(this->EPD_Pin_DISCHARGE, LOW);
+}
+
+
+// convert a temperature in Celcius to
+// the scale factor for frame_*_repeat methods
+int EPD_Class::temperature_to_factor_10x(int temperature) {
+ if (temperature <= -10) {
+ return 170;
+ } else if (temperature <= -5) {
+ return 120;
+ } else if (temperature <= 5) {
+ return 80;
+ } else if (temperature <= 10) {
+ return 40;
+ } else if (temperature <= 15) {
+ return 30;
+ } else if (temperature <= 20) {
+ return 20;
+ } else if (temperature <= 40) {
+ return 10;
+ }
+ return 7;
+}
+
+
+// One frame of data is the number of lines * rows. For example:
+// The 1.44” frame of data is 96 lines * 128 dots.
+// The 2” frame of data is 96 lines * 200 dots.
+// The 2.7” frame of data is 176 lines * 264 dots.
+
+// the image is arranged by line which matches the display size
+// so smallest would have 96 * 32 bytes
+
+void EPD_Class::frame_fixed(uint8_t fixed_value, EPD_stage stage) {
+ for (uint8_t line = 0; line < this->lines_per_display ; ++line) {
+ this->line(line, 0, fixed_value, false, stage);
+ }
+}
+
+
+void EPD_Class::frame_data(PROGMEM const uint8_t *image, EPD_stage stage){
+ for (uint8_t line = 0; line < this->lines_per_display ; ++line) {
+ this->line(line, &image[line * this->bytes_per_line], 0, true, stage);
+ }
+}
+
+
+#if defined(EPD_ENABLE_EXTRA_SRAM)
+void EPD_Class::frame_sram(const uint8_t *image, EPD_stage stage){
+ for (uint8_t line = 0; line < this->lines_per_display ; ++line) {
+ this->line(line, &image[line * this->bytes_per_line], 0, false, stage);
+ }
+}
+#endif
+
+
+void EPD_Class::frame_cb(uint32_t address, EPD_reader *reader, EPD_stage stage) {
+ static uint8_t buffer[264 / 8];
+ for (uint8_t line = 0; line < this->lines_per_display; ++line) {
+ reader(buffer, address + line * this->bytes_per_line, this->bytes_per_line);
+ this->line(line, buffer, 0, false, stage);
+ }
+}
+
+void EPD_Class::frame_fixed_repeat(uint8_t fixed_value, EPD_stage stage) {
+ long stage_time = this->factored_stage_time;
+
+ do {
+ millis_start();
+ unsigned long t_start = millis();
+ this->frame_fixed(fixed_value, stage);
+ unsigned long t_end = millis();
+ if (t_end > t_start) {
+ stage_time -= t_end - t_start;
+ } else {
+ stage_time -= t_start - t_end + 1 + ULONG_MAX;
+ }
+ } while (stage_time > 0);
+}
+
+
+void EPD_Class::frame_data_repeat(PROGMEM const uint8_t *image, EPD_stage stage) {
+ long stage_time = this->factored_stage_time;
+ do {
+ millis_start();
+ unsigned long t_start = millis();
+ this->frame_data(image, stage);
+ unsigned long t_end = millis();
+ if (t_end > t_start) {
+ stage_time -= t_end - t_start;
+ } else {
+ stage_time -= t_start - t_end + 1 + ULONG_MAX;
+ }
+ } while (stage_time > 0);
+}
+
+
+#if defined(EPD_ENABLE_EXTRA_SRAM)
+void EPD_Class::frame_sram_repeat(const uint8_t *image, EPD_stage stage) {
+ long stage_time = this->factored_stage_time;
+ do {
+ millis_start();
+ unsigned long t_start = millis();
+ this->frame_sram(image, stage);
+ unsigned long t_end = millis();
+ if (t_end > t_start) {
+ stage_time -= t_end - t_start;
+ } else {
+ stage_time -= t_start - t_end + 1 + ULONG_MAX;
+ }
+ } while (stage_time > 0);
+}
+#endif
+
+
+void EPD_Class::frame_cb_repeat(uint32_t address, EPD_reader *reader, EPD_stage stage) {
+ long stage_time = this->factored_stage_time;
+ do {
+ millis_start();
+ unsigned long t_start = millis();
+ this->frame_cb(address, reader, stage);
+ unsigned long t_end = millis();
+ if (t_end > t_start) {
+ stage_time -= t_end - t_start;
+ } else {
+ stage_time -= t_start - t_end + 1 + ULONG_MAX;
+ }
+ } while (stage_time > 0);
+}
+
+
+void EPD_Class::line(uint16_t line, const uint8_t *data, uint8_t fixed_value, bool read_progmem, EPD_stage stage) {
+ // charge pump voltage levels
+
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x04), 2);
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, this->gate_source, this->gate_source_length);
+
+ // send data
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x0a), 2);
+ Delay_us(10);
+
+ // CS low
+ digitalWrite(this->EPD_Pin_EPD_CS, LOW);
+ SPI_put_wait(0x72, this->EPD_Pin_BUSY);
+
+ // even pixels
+ for (uint16_t b = this->bytes_per_line; b > 0; --b) {
+ if (0 != data) {
+
+ uint8_t pixels = data[b - 1] & 0xaa;
+
+ switch(stage) {
+ case EPD_compensate: // B -> W, W -> B (Current Image)
+ pixels = 0xaa | ((pixels ^ 0xaa) >> 1);
+ break;
+ case EPD_white: // B -> N, W -> W (Current Image)
+ pixels = 0x55 + ((pixels ^ 0xaa) >> 1);
+ break;
+ case EPD_inverse: // B -> N, W -> B (New Image)
+ pixels = 0x55 | (pixels ^ 0xaa);
+ break;
+ case EPD_normal: // B -> B, W -> W (New Image)
+ pixels = 0xaa | (pixels >> 1);
+ break;
+ }
+ SPI_put_wait(pixels, this->EPD_Pin_BUSY);
+ } else {
+ SPI_put_wait(fixed_value, this->EPD_Pin_BUSY);
+ } }
+
+ // scan line
+ for (uint16_t b = 0; b < this->bytes_per_scan; ++b) {
+ if (line / 4 == b) {
+ SPI_put_wait(0xc0 >> (2 * (line & 0x03)), this->EPD_Pin_BUSY);
+ } else {
+ SPI_put_wait(0x00, this->EPD_Pin_BUSY);
+ }
+ }
+
+ // odd pixels
+ for (uint16_t b = 0; b < this->bytes_per_line; ++b) {
+ if (0 != data) {
+
+ uint8_t pixels = data[b] & 0x55;
+
+ switch(stage) {
+ case EPD_compensate: // B -> W, W -> B (Current Image)
+ pixels = 0xaa | (pixels ^ 0x55);
+ break;
+ case EPD_white: // B -> N, W -> W (Current Image)
+ pixels = 0x55 + (pixels ^ 0x55);
+ break;
+ case EPD_inverse: // B -> N, W -> B (New Image)
+ pixels = 0x55 | ((pixels ^ 0x55) << 1);
+ break;
+ case EPD_normal: // B -> B, W -> W (New Image)
+ pixels = 0xaa | pixels;
+ break;
+ }
+ uint8_t p1 = (pixels >> 6) & 0x03;
+ uint8_t p2 = (pixels >> 4) & 0x03;
+ uint8_t p3 = (pixels >> 2) & 0x03;
+ uint8_t p4 = (pixels >> 0) & 0x03;
+ pixels = (p1 << 0) | (p2 << 2) | (p3 << 4) | (p4 << 6);
+ SPI_put_wait(pixels, this->EPD_Pin_BUSY);
+ } else {
+ SPI_put_wait(fixed_value, this->EPD_Pin_BUSY);
+ }
+ }
+
+ if (this->filler) {
+ SPI_put_wait(0x00, this->EPD_Pin_BUSY);
+ }
+
+ // CS high
+ digitalWrite(this->EPD_Pin_EPD_CS, HIGH);
+
+ // output data to panel
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x70, 0x02), 2);
+ Delay_us(10);
+ SPI_send(this->EPD_Pin_EPD_CS, CU8(0x72, 0x2f), 2);
+}
+
+
+void EPD_Class::SPI_put(uint8_t c) {
+
+ spi_.write(c);
+ //spi_.fastWrite(c);
+
+
+}
+
+
+
+void EPD_Class::SPI_put_wait(uint8_t c, DigitalIn busy_pin) {
+
+ SPI_put(c);
+
+ // wait for COG ready
+ while (HIGH == digitalRead(busy_pin)) {
+ }
+}
+
+
+void EPD_Class::SPI_send(DigitalOut cs_pin, const uint8_t *buffer, uint16_t length) {
+
+ // CS low
+ digitalWrite(cs_pin, LOW);
+
+ // send all data
+ for (uint16_t i = 0; i < length; ++i) {
+ spi_.write(*buffer++);
+ }
+
+ // CS high
+ digitalWrite(cs_pin, HIGH);
+}
+
+
+//static void PWM_start(int pin) {
+// analogWrite(pin, 128); // 50% duty cycle
+//}
+
+
+//static void PWM_stop(int pin) {
+// analogWrite(pin, 0);
+//}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/EaEpaper/EPD.h Wed Jul 02 13:19:34 2014 +0000
@@ -0,0 +1,155 @@
+// Copyright 2013 Pervasive Displays, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+// express or implied. See the License for the specific language
+// governing permissions and limitations under the License.
+
+#ifndef EPD_H
+#define EPD_H
+
+#include "mbed.h"
+
+#define PROGMEM
+
+
+typedef enum {
+ EPD_1_44, // 128 x 96
+ EPD_2_0, // 200 x 96
+ EPD_2_7 // 264 x 176
+} EPD_size;
+
+typedef enum { // Image pixel -> Display pixel
+ EPD_compensate, // B -> W, W -> B (Current Image)
+ EPD_white, // B -> N, W -> W (Current Image)
+ EPD_inverse, // B -> N, W -> B (New Image)
+ EPD_normal // B -> B, W -> W (New Image)
+} EPD_stage;
+
+typedef void EPD_reader(void *buffer, uint32_t address, uint16_t length);
+
+class EPD_Class {
+private:
+ DigitalOut EPD_Pin_PANEL_ON;
+ DigitalOut EPD_Pin_BORDER;
+ DigitalOut EPD_Pin_DISCHARGE;
+ PwmOut EPD_Pin_PWM;
+ DigitalOut EPD_Pin_RESET;
+ DigitalIn EPD_Pin_BUSY;
+ DigitalOut EPD_Pin_EPD_CS;
+ SPI spi_;
+
+ EPD_size size;
+ uint16_t stage_time;
+ uint16_t factored_stage_time;
+ uint16_t lines_per_display;
+ uint16_t dots_per_line;
+ uint16_t bytes_per_line;
+ uint16_t bytes_per_scan;
+ PROGMEM const uint8_t *gate_source;
+ uint16_t gate_source_length;
+ PROGMEM const uint8_t *channel_select;
+ uint16_t channel_select_length;
+
+ bool filler;
+
+ void SPI_put(uint8_t c);
+ void SPI_put_wait(uint8_t c, DigitalIn busy_pin);
+ void SPI_send(DigitalOut cs_pin, const uint8_t *buffer, uint16_t length);
+
+public:
+ // power up and power down the EPD panel
+ void begin();
+ void end();
+
+ void setFactor(int temperature = 25) {
+ this->factored_stage_time = this->stage_time * this->temperature_to_factor_10x(temperature) / 10;
+ }
+
+ // clear display (anything -> white)
+ void clear() {
+ this->frame_fixed_repeat(0xff, EPD_compensate);
+ this->frame_fixed_repeat(0xff, EPD_white);
+ this->frame_fixed_repeat(0xaa, EPD_inverse);
+ this->frame_fixed_repeat(0xaa, EPD_normal);
+ }
+
+ // assuming a clear (white) screen output an image (PROGMEM data)
+ void image(const uint8_t *image) {
+ this->frame_fixed_repeat(0xaa, EPD_compensate);
+ this->frame_fixed_repeat(0xaa, EPD_white);
+ this->frame_data_repeat(image, EPD_inverse);
+ this->frame_data_repeat(image, EPD_normal);
+ }
+
+ // change from old image to new image (PROGMEM data)
+ void image(const uint8_t *old_image, const uint8_t *new_image) {
+ this->frame_data_repeat(old_image, EPD_compensate);
+ this->frame_data_repeat(old_image, EPD_white);
+ this->frame_data_repeat(new_image, EPD_inverse);
+ this->frame_data_repeat(new_image, EPD_normal);
+ }
+
+#if defined(EPD_ENABLE_EXTRA_SRAM)
+
+ // change from old image to new image (SRAM version)
+ void image_sram(const uint8_t *old_image, const uint8_t *new_image) {
+ this->frame_sram_repeat(old_image, EPD_compensate);
+ this->frame_sram_repeat(old_image, EPD_white);
+ this->frame_sram_repeat(new_image, EPD_inverse);
+ this->frame_sram_repeat(new_image, EPD_normal);
+ }
+#endif
+
+ // Low level API calls
+ // ===================
+
+ // single frame refresh
+ void frame_fixed(uint8_t fixed_value, EPD_stage stage);
+ void frame_data(const uint8_t *new_image, EPD_stage stage);
+#if defined(EPD_ENABLE_EXTRA_SRAM)
+ void frame_sram(const uint8_t *new_image, EPD_stage stage);
+#endif
+ void frame_cb(uint32_t address, EPD_reader *reader, EPD_stage stage);
+
+ // stage_time frame refresh
+ void frame_fixed_repeat(uint8_t fixed_value, EPD_stage stage);
+ void frame_data_repeat(const uint8_t *new_image, EPD_stage stage);
+#if defined(EPD_ENABLE_EXTRA_SRAM)
+ void frame_sram_repeat(const uint8_t *new_image, EPD_stage stage);
+#endif
+ void frame_cb_repeat(uint32_t address, EPD_reader *reader, EPD_stage stage);
+
+ // convert temperature to compensation factor
+ int temperature_to_factor_10x(int temperature);
+
+ // single line display - very low-level
+ // also has to handle AVR progmem
+ void line(uint16_t line, const uint8_t *data, uint8_t fixed_value, bool read_progmem, EPD_stage stage);
+
+ // inline static void attachInterrupt();
+ // inline static void detachInterrupt();
+
+ EPD_Class(EPD_size size,
+ PinName panel_on_pin,
+ PinName border_pin,
+ PinName discharge_pin,
+ PinName pwm_pin,
+ PinName reset_pin,
+ PinName busy_pin,
+ PinName chip_select_pin,
+ PinName mosi,
+ PinName miso,
+ PinName sck);
+
+};
+
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/EaEpaper/EaEpaper.cpp Wed Jul 02 13:19:34 2014 +0000
@@ -0,0 +1,353 @@
+
+#include "EaEpaper.h"
+
+#define EA_IMG_BUF_SZ (1536) // 128 x 96 / 8 = 1536
+
+#define LM75A_ADDRESS (0x92) // 0x49 << 1
+#define LM75A_CMD_TEMP 0x00
+
+static uint8_t _oldImage[EA_IMG_BUF_SZ];
+static uint8_t _newImage[EA_IMG_BUF_SZ];
+
+EaEpaper::EaEpaper(PinName p_on, PinName border, PinName discharge, PinName reset, PinName busy, PinName cs,
+ PinName pwm,
+ PinName mosi, PinName miso, PinName sck,
+ PinName sda, PinName scl,
+ const char* name):
+ epd_(EPD_1_44,
+ p_on, // panel_on_pin
+ border, // border_pin
+ discharge, // discharge_pin
+ pwm, // pwm_pin
+ reset, // reset_pin
+ busy, // busy_pin
+ cs, // chip_select_pin
+ mosi, // mosi
+ miso, // miso
+ sck), // sck
+ i2c_(sda, scl),
+ GraphicsDisplay(name)
+{
+ draw_mode = NORMAL;
+ memset(_oldImage, 0, EA_IMG_BUF_SZ);
+ memset(_newImage, 0, EA_IMG_BUF_SZ);
+}
+
+
+int EaEpaper::width()
+{
+ return 264;
+}
+
+int EaEpaper::height()
+{
+ return 176;
+}
+
+
+// erase pixel after power up
+void EaEpaper::clear()
+{
+ epd_.begin();
+ epd_.setFactor(readTemperature()/100);
+ epd_.clear();
+ epd_.end();
+
+ memset(_oldImage, 0, EA_IMG_BUF_SZ);
+ memset(_newImage, 0, EA_IMG_BUF_SZ);
+}
+
+// update screen _newImage -> _oldImage
+void EaEpaper::write_disp(void)
+{
+ epd_.begin();
+ epd_.setFactor(readTemperature()/100);
+ epd_.image(_oldImage, _newImage);
+ epd_.end();
+
+ memcpy(_oldImage, _newImage, EA_IMG_BUF_SZ);
+}
+
+// read LM75A sensor on board to calculate display speed
+int32_t EaEpaper::readTemperature()
+{
+ char buf[2];
+ int32_t t = 0;
+ char reg = LM75A_CMD_TEMP;
+
+ i2c_.write(LM75A_ADDRESS, ®, 1);
+ i2c_.read(LM75A_ADDRESS, buf, 2);
+
+ t = ((buf[0] << 8) | (buf[1]));
+
+ return ((t * 100) >> 8);
+}
+
+// set one pixel in buffer _newImage
+
+void EaEpaper::pixel(int x, int y, int color)
+{
+ // first check parameter
+ if(x > 263 || y > 175 || x < 0 || y < 0) return;
+
+ if(draw_mode == NORMAL) {
+ if(color == 0)
+ _newImage[(x / 8) + ((y-1) * 16)] &= ~(1 << (x%8)); // erase pixel
+ else
+ _newImage[(x / 8) + ((y-1) * 16)] |= (1 << (x%8)); // set pixel
+ } else { // XOR mode
+ if(color == 1)
+ _newImage[(x / 8) + ((y-1) * 16)] ^= (1 << (x%8)); // xor pixel
+ }
+}
+
+// clear screen
+void EaEpaper::cls(void)
+{
+ memset(_newImage, 0, EA_IMG_BUF_SZ); // clear display buffer
+}
+
+// print line
+void EaEpaper::line(int x0, int y0, int x1, int y1, int color)
+{
+ int dx = 0, dy = 0;
+ int dx_sym = 0, dy_sym = 0;
+ int dx_x2 = 0, dy_x2 = 0;
+ int di = 0;
+
+ dx = x1-x0;
+ dy = y1-y0;
+
+ if (dx > 0) {
+ dx_sym = 1;
+ } else {
+ dx_sym = -1;
+ }
+
+ if (dy > 0) {
+ dy_sym = 1;
+ } else {
+ dy_sym = -1;
+ }
+
+ dx = dx_sym*dx;
+ dy = dy_sym*dy;
+
+ dx_x2 = dx*2;
+ dy_x2 = dy*2;
+
+ if (dx >= dy) {
+ di = dy_x2 - dx;
+ while (x0 != x1) {
+
+ pixel(x0, y0, color);
+ x0 += dx_sym;
+ if (di<0) {
+ di += dy_x2;
+ } else {
+ di += dy_x2 - dx_x2;
+ y0 += dy_sym;
+ }
+ }
+ pixel(x0, y0, color);
+ } else {
+ di = dx_x2 - dy;
+ while (y0 != y1) {
+ pixel(x0, y0, color);
+ y0 += dy_sym;
+ if (di < 0) {
+ di += dx_x2;
+ } else {
+ di += dx_x2 - dy_x2;
+ x0 += dx_sym;
+ }
+ }
+ pixel(x0, y0, color);
+ }
+}
+
+// print rect
+void EaEpaper::rect(int x0, int y0, int x1, int y1, int color)
+{
+
+ if (x1 > x0) line(x0,y0,x1,y0,color);
+ else line(x1,y0,x0,y0,color);
+
+ if (y1 > y0) line(x0,y0,x0,y1,color);
+ else line(x0,y1,x0,y0,color);
+
+ if (x1 > x0) line(x0,y1,x1,y1,color);
+ else line(x1,y1,x0,y1,color);
+
+ if (y1 > y0) line(x1,y0,x1,y1,color);
+ else line(x1,y1,x1,y0,color);
+}
+
+// print filled rect
+void EaEpaper::fillrect(int x0, int y0, int x1, int y1, int color)
+{
+ int l,c,i;
+ if(x0 > x1) {
+ i = x0;
+ x0 = x1;
+ x1 = i;
+ }
+
+ if(y0 > y1) {
+ i = y0;
+ y0 = y1;
+ y1 = i;
+ }
+
+ for(l = x0; l<= x1; l ++) {
+ for(c = y0; c<= y1; c++) {
+ pixel(l,c,color);
+ }
+ }
+}
+
+// print circle
+void EaEpaper::circle(int x0, int y0, int r, int color)
+{
+ int x = -r, y = 0, err = 2-2*r, e2;
+ do {
+ pixel(x0-x, y0+y,color);
+ pixel(x0+x, y0+y,color);
+ pixel(x0+x, y0-y,color);
+ pixel(x0-x, y0-y,color);
+ e2 = err;
+ if (e2 <= y) {
+ err += ++y*2+1;
+ if (-x == y && e2 <= x) e2 = 0;
+ }
+ if (e2 > x) err += ++x*2+1;
+ } while (x <= 0);
+
+}
+
+// print filled circle
+void EaEpaper::fillcircle(int x0, int y0, int r, int color)
+{
+ int x = -r, y = 0, err = 2-2*r, e2;
+ do {
+ line(x0-x, y0-y, x0-x, y0+y, color);
+ line(x0+x, y0-y, x0+x, y0+y, color);
+ e2 = err;
+ if (e2 <= y) {
+ err += ++y*2+1;
+ if (-x == y && e2 <= x) e2 = 0;
+ }
+ if (e2 > x) err += ++x*2+1;
+ } while (x <= 0);
+}
+
+// set drawing mode
+void EaEpaper::setmode(int mode)
+{
+ draw_mode = mode;
+}
+
+// set cursor position
+void EaEpaper::locate(int x, int y)
+{
+ char_x = x;
+ char_y = y;
+}
+
+// calc char columns
+int EaEpaper::columns()
+{
+ return width() / font[1];
+}
+
+// calc char rows
+int EaEpaper::rows()
+{
+ return height() / font[2];
+}
+
+// print char
+int EaEpaper::_putc(int value)
+{
+ if (value == '\n') { // new line
+ char_x = 0;
+ char_y = char_y + font[2];
+ if (char_y >= height() - font[2]) {
+ char_y = 0;
+ }
+ } else {
+ character(char_x, char_y, value);
+ }
+ return value;
+}
+
+// paint char out of font
+void EaEpaper::character(int x, int y, int c)
+{
+ unsigned int hor,vert,offset,bpl,j,i,b;
+ unsigned char* zeichen;
+ unsigned char z,w;
+
+ if ((c < 31) || (c > 127)) return; // test char range
+
+ // read font parameter from start of array
+ offset = font[0]; // bytes / char
+ hor = font[1]; // get hor size of font
+ vert = font[2]; // get vert size of font
+ bpl = font[3]; // bytes per line
+
+ if (char_x + hor > width()) {
+ char_x = 0;
+ char_y = char_y + vert;
+ if (char_y >= height() - font[2]) {
+ char_y = 0;
+ }
+ }
+
+ zeichen = &font[((c -32) * offset) + 4]; // start of char bitmap
+ w = zeichen[0]; // width of actual char
+ // construct the char into the buffer
+ for (j=0; j<vert; j++) { // vert line
+ for (i=0; i<hor; i++) { // horz line
+ z = zeichen[bpl * i + ((j & 0xF8) >> 3)+1];
+ b = 1 << (j & 0x07);
+ if (( z & b ) == 0x00) {
+ pixel(x+i,y+j,0);
+ } else {
+ pixel(x+i,y+j,1);
+ }
+
+ }
+ }
+
+ char_x += w;
+}
+
+// set actual font
+void EaEpaper::set_font(unsigned char* f)
+{
+ font = f;
+}
+
+void EaEpaper::print_bm(Bitmap bm, int x, int y)
+{
+ int h,v,b;
+ char d;
+
+ for(v=0; v < bm.ySize; v++) { // lines
+ for(h=0; h < bm.xSize; h++) { // pixel
+ if(h + x > width()) break;
+ if(v + y > height()) break;
+ d = bm.data[bm.Byte_in_Line * v + ((h & 0xF8) >> 3)];
+ b = 0x80 >> (h & 0x07);
+ if((d & b) == 0) {
+ pixel(x+h,y+v,0);
+ } else {
+ pixel(x+h,y+v,1);
+ }
+ }
+ }
+
+}
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/EaEpaper/EaEpaper.h Wed Jul 02 13:19:34 2014 +0000
@@ -0,0 +1,260 @@
+/* mbed library for 264*176 pixel 2.7 INCH E-PAPER DISPLAY from Pervasive Displays
+ * Copyright (c) 2013 Peter Drescher - DC2PD
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+
+// 09.11.2013 initial Version
+
+#ifndef EAEPAPER_H
+#define EAEPAPER_H
+
+/**
+ * Includes
+ */
+#include "mbed.h"
+#include "EPD.h"
+#include "GraphicsDisplay.h"
+
+// we have to double buffer the display
+#define EA_IMG_BUF_SZ (1536) // 264 x 176 / 8 = 5808
+
+/** Draw mode
+ * NORMAl
+ * XOR set pixel by xor of the screen
+ */
+enum {NORMAL,XOR};
+
+/** Bitmap
+ */
+struct Bitmap{
+ int xSize;
+ int ySize;
+ int Byte_in_Line;
+ char* data;
+ };
+
+/* color definitions */
+#define Black 0x0
+#define White 0x1
+
+/** Display control class, based on GraphicsDisplay and TextDisplay
+ *
+ * Example with pinning for KL25Z:
+ * @code
+ * #include "mbed.h"
+ * #include "EaEpaper.h"
+ * #include "Arial28x28.h"
+ * #include "Arial12x12.h"
+ * #include "font_big.h"
+ * #include "graphics.h"
+
+ * // the E-Paper board from embedded artists has a LM75 temp sensor to compensate the temperature effect. If it is cold the display reacts slower.
+ * // The LM75 need a I2C -> 2 pins : sda and scl
+ * // The display data is written via SPI -> 3 pins : mosi,miso,sck
+ * // There are also some control signals
+ * // The pwm pin has to be connected to a PWM enabled pin : pwm
+ * // The other signals are connected to normal IO`s
+ * //
+ * EaEpaper epaper(PTD7, // PWR_CTRL
+ * PTD6, // BORDER
+ * PTE31, // DISCHARGE
+ * PTA17, // RESET_DISP
+ * PTA16, // BUSY
+ * PTC17, // SSEL
+ * PTD4, // PWM
+ * PTD2,PTD3,PTD1, // MOSI,MISO,SCLK
+ * PTE0,PTE1); // SDA,SCL
+ *
+ * int main() {
+ *
+ * epaper.cls(); // clear screen
+ * epaper.set_font((unsigned char*) Arial28x28); // select the font
+ * epaper.locate(5,20); // set cursor
+ * epaper.printf("Hello Mbed"); // print text
+ * epaper.rect(3,15,150,50,1); // draw frame
+ * epaper.write_disp(); // update screen
+ *
+ * @endcode
+ */
+
+
+class EaEpaper : public GraphicsDisplay {
+
+public:
+
+ /**
+ * Constructor.
+ */
+ EaEpaper(PinName p_on, PinName border, PinName discharge, PinName reset, PinName busy, PinName cs, // IO-Pins
+ PinName pwm, // PWM Pin
+ PinName mosi, PinName miso, PinName sck, // SPI
+ PinName sda, PinName scl, // I2C
+ const char* name ="E_Paper");
+
+ /** Get the width of the screen in pixel
+ *
+ * @param
+ * @returns width of screen in pixel
+ *
+ */
+ virtual int width();
+
+ /** Get the height of the screen in pixel
+ *
+ * @returns height of screen in pixel
+ *
+ */
+ virtual int height();
+
+
+ /**
+ * Clear the display
+ */
+ void clear();
+
+ /**
+ * Write image buffer to display
+ */
+ void write_disp(void);
+
+ /**
+ * set or reset a single pixel
+ *
+ * @param x horizontal position
+ * @param y vertical position
+ * @param color : 0 white, 1 black
+ */
+ virtual void pixel(int x, int y, int color);
+
+ /** Fill the screen with white
+ *
+ */
+ virtual void cls(void);
+
+ /** draw a 1 pixel line
+ *
+ * @param x0,y0 start point
+ * @param x1,y1 stop point
+ * @param color : 0 white, 1 black
+ */
+ void line(int x0, int y0, int x1, int y1, int color);
+
+ /** draw a rect
+ *
+ * @param x0,y0 top left corner
+ * @param x1,y1 down right corner
+ * @param color : 0 white, 1 black
+ */
+ void rect(int x0, int y0, int x1, int y1, int color);
+
+ /** draw a filled rect
+ *
+ * @param x0,y0 top left corner
+ * @param x1,y1 down right corner
+ * @param color : 0 white, 1 black
+ */
+ void fillrect(int x0, int y0, int x1, int y1, int color);
+
+ /** draw a circle
+ *
+ * @param x0,y0 center
+ * @param r radius
+ * @param color : 0 white, 1 black *
+ */
+ void circle(int x0, int y0, int r, int color);
+
+ /** draw a filled circle
+ *
+ * @param x0,y0 center
+ * @param r radius
+ * @param color : 0 white, 1 black *
+ */
+ void fillcircle(int x0, int y0, int r, int color);
+
+ /** set drawing mode
+ * @param NORMAL : paint normal color, XOR : paint XOR of current pixels
+ */
+ void setmode(int mode);
+
+ /** setup cursor position
+ *
+ * @param x x-position (top left)
+ * @param y y-position
+ */
+ virtual void locate(int x, int y);
+
+ /** calculate the max number of char in a line
+ *
+ * @returns max columns
+ * depends on actual font size
+ */
+ virtual int columns();
+
+ /** calculate the max number of columns
+ *
+ * @returns max column
+ * depends on actual font size
+ */
+ virtual int rows();
+
+ /** put a char on the screen
+ *
+ * @param value char to print
+ * @returns printed char
+ */
+ virtual int _putc(int value);
+
+ /** paint a character on given position out of the active font to the screen buffer
+ *
+ * @param x x-position (top left)
+ * @param y y-position
+ * @param c char code
+ */
+ virtual void character(int x, int y, int c);
+
+ /** select the font to use
+ *
+ * @param f pointer to font array
+ *
+ * font array can created with GLCD Font Creator from http://www.mikroe.com
+ * you have to add 4 parameter at the beginning of the font array to use:
+ * - the number of byte / char
+ * - the vertial size in pixel
+ * - the horizontal size in pixel
+ * - the number of byte per vertical line
+ * you also have to change the array to char[]
+ */
+ void set_font(unsigned char* f);
+
+ /** print bitmap to buffer
+ *
+ * @param bm struct Bitmap in flash
+ * @param x x start
+ * @param y y start
+ *
+ */
+ void print_bm(Bitmap bm, int x, int y);
+
+
+ unsigned char* font;
+ unsigned int draw_mode;
+
+ private:
+
+ EPD_Class epd_;
+ I2C i2c_;
+ unsigned int char_x;
+ unsigned int char_y;
+ int32_t readTemperature();
+
+};
+
+ #endif /* EAEPAPER_H */
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/EaEpaper/GraphicsDisplay.cpp Wed Jul 02 13:19:34 2014 +0000
@@ -0,0 +1,176 @@
+/* mbed GraphicsDisplay Display Library Base Class
+ * Copyright (c) 2007-2009 sford
+ * Released under the MIT License: http://mbed.org/license/mit
+ */
+
+#include "GraphicsDisplay.h"
+
+const unsigned char FONT8x8[97][8] = {
+0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00, // columns, rows, num_bytes_per_char
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // space 0x20
+0x30,0x78,0x78,0x30,0x30,0x00,0x30,0x00, // !
+0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00, // "
+0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00, // #
+0x18,0x3E,0x60,0x3C,0x06,0x7C,0x18,0x00, // $
+0x00,0x63,0x66,0x0C,0x18,0x33,0x63,0x00, // %
+0x1C,0x36,0x1C,0x3B,0x6E,0x66,0x3B,0x00, // &
+0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00, // '
+0x0C,0x18,0x30,0x30,0x30,0x18,0x0C,0x00, // (
+0x30,0x18,0x0C,0x0C,0x0C,0x18,0x30,0x00, // )
+0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00, // *
+0x00,0x30,0x30,0xFC,0x30,0x30,0x00,0x00, // +
+0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30, // ,
+0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00, // -
+0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00, // .
+0x03,0x06,0x0C,0x18,0x30,0x60,0x40,0x00, // / (forward slash)
+0x3E,0x63,0x63,0x6B,0x63,0x63,0x3E,0x00, // 0 0x30
+0x18,0x38,0x58,0x18,0x18,0x18,0x7E,0x00, // 1
+0x3C,0x66,0x06,0x1C,0x30,0x66,0x7E,0x00, // 2
+0x3C,0x66,0x06,0x1C,0x06,0x66,0x3C,0x00, // 3
+0x0E,0x1E,0x36,0x66,0x7F,0x06,0x0F,0x00, // 4
+0x7E,0x60,0x7C,0x06,0x06,0x66,0x3C,0x00, // 5
+0x1C,0x30,0x60,0x7C,0x66,0x66,0x3C,0x00, // 6
+0x7E,0x66,0x06,0x0C,0x18,0x18,0x18,0x00, // 7
+0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00, // 8
+0x3C,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00, // 9
+0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00, // :
+0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x30, // ;
+0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00, // <
+0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00, // =
+0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00, // >
+0x3C,0x66,0x06,0x0C,0x18,0x00,0x18,0x00, // ?
+0x3E,0x63,0x6F,0x69,0x6F,0x60,0x3E,0x00, // @ 0x40
+0x18,0x3C,0x66,0x66,0x7E,0x66,0x66,0x00, // A
+0x7E,0x33,0x33,0x3E,0x33,0x33,0x7E,0x00, // B
+0x1E,0x33,0x60,0x60,0x60,0x33,0x1E,0x00, // C
+0x7C,0x36,0x33,0x33,0x33,0x36,0x7C,0x00, // D
+0x7F,0x31,0x34,0x3C,0x34,0x31,0x7F,0x00, // E
+0x7F,0x31,0x34,0x3C,0x34,0x30,0x78,0x00, // F
+0x1E,0x33,0x60,0x60,0x67,0x33,0x1F,0x00, // G
+0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x00, // H
+0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00, // I
+0x0F,0x06,0x06,0x06,0x66,0x66,0x3C,0x00, // J
+0x73,0x33,0x36,0x3C,0x36,0x33,0x73,0x00, // K
+0x78,0x30,0x30,0x30,0x31,0x33,0x7F,0x00, // L
+0x63,0x77,0x7F,0x7F,0x6B,0x63,0x63,0x00, // M
+0x63,0x73,0x7B,0x6F,0x67,0x63,0x63,0x00, // N
+0x3E,0x63,0x63,0x63,0x63,0x63,0x3E,0x00, // O
+0x7E,0x33,0x33,0x3E,0x30,0x30,0x78,0x00, // P 0x50
+0x3C,0x66,0x66,0x66,0x6E,0x3C,0x0E,0x00, // Q
+0x7E,0x33,0x33,0x3E,0x36,0x33,0x73,0x00, // R
+0x3C,0x66,0x30,0x18,0x0C,0x66,0x3C,0x00, // S
+0x7E,0x5A,0x18,0x18,0x18,0x18,0x3C,0x00, // T
+0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x00, // U
+0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00, // V
+0x63,0x63,0x63,0x6B,0x7F,0x77,0x63,0x00, // W
+0x63,0x63,0x36,0x1C,0x1C,0x36,0x63,0x00, // X
+0x66,0x66,0x66,0x3C,0x18,0x18,0x3C,0x00, // Y
+0x7F,0x63,0x46,0x0C,0x19,0x33,0x7F,0x00, // Z
+0x3C,0x30,0x30,0x30,0x30,0x30,0x3C,0x00, // [
+0x60,0x30,0x18,0x0C,0x06,0x03,0x01,0x00, // \ (back slash)
+0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00, // ]
+0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00, // ^
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF, // _
+0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00, // ` 0x60
+0x00,0x00,0x3C,0x06,0x3E,0x66,0x3B,0x00, // a
+0x70,0x30,0x3E,0x33,0x33,0x33,0x6E,0x00, // b
+0x00,0x00,0x3C,0x66,0x60,0x66,0x3C,0x00, // c
+0x0E,0x06,0x3E,0x66,0x66,0x66,0x3B,0x00, // d
+0x00,0x00,0x3C,0x66,0x7E,0x60,0x3C,0x00, // e
+0x1C,0x36,0x30,0x78,0x30,0x30,0x78,0x00, // f
+0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x7C, // g
+0x70,0x30,0x36,0x3B,0x33,0x33,0x73,0x00, // h
+0x18,0x00,0x38,0x18,0x18,0x18,0x3C,0x00, // i
+0x06,0x00,0x06,0x06,0x06,0x66,0x66,0x3C, // j
+0x70,0x30,0x33,0x36,0x3C,0x36,0x73,0x00, // k
+0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00, // l
+0x00,0x00,0x66,0x7F,0x7F,0x6B,0x63,0x00, // m
+0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x00, // n
+0x00,0x00,0x3C,0x66,0x66,0x66,0x3C,0x00, // o
+0x00,0x00,0x6E,0x33,0x33,0x3E,0x30,0x78, // p
+0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x0F, // q
+0x00,0x00,0x6E,0x3B,0x33,0x30,0x78,0x00, // r
+0x00,0x00,0x3E,0x60,0x3C,0x06,0x7C,0x00, // s
+0x08,0x18,0x3E,0x18,0x18,0x1A,0x0C,0x00, // t
+0x00,0x00,0x66,0x66,0x66,0x66,0x3B,0x00, // u
+0x00,0x00,0x66,0x66,0x66,0x3C,0x18,0x00, // v
+0x00,0x00,0x63,0x6B,0x7F,0x7F,0x36,0x00, // w
+0x00,0x00,0x63,0x36,0x1C,0x36,0x63,0x00, // x
+0x00,0x00,0x66,0x66,0x66,0x3E,0x06,0x7C, // y
+0x00,0x00,0x7E,0x4C,0x18,0x32,0x7E,0x00, // z
+0x0E,0x18,0x18,0x70,0x18,0x18,0x0E,0x00, // {
+0x0C,0x0C,0x0C,0x00,0x0C,0x0C,0x0C,0x00, // |
+0x70,0x18,0x18,0x0E,0x18,0x18,0x70,0x00, // }
+0x3B,0x6E,0x00,0x00,0x00,0x00,0x00,0x00, // ~
+0x1C,0x36,0x36,0x1C,0x00,0x00,0x00,0x00}; // DEL
+
+GraphicsDisplay::GraphicsDisplay(const char *name):TextDisplay(name) {
+ foreground(0xFFFF);
+ background(0x0000);
+}
+
+void GraphicsDisplay::character(int column, int row, int value) {
+ blitbit(column * 8, row * 8, 8, 8, (char*)&(FONT8x8[value - 0x1F][0]));
+}
+
+void GraphicsDisplay::window(int x, int y, int w, int h) {
+ // current pixel location
+ _x = x;
+ _y = y;
+ // window settings
+ _x1 = x;
+ _x2 = x + w - 1;
+ _y1 = y;
+ _y2 = y + h - 1;
+}
+
+void GraphicsDisplay::putp(int colour) {
+ // put pixel at current pixel location
+ pixel(_x, _y, colour);
+ // update pixel location based on window settings
+ _x++;
+ if(_x > _x2) {
+ _x = _x1;
+ _y++;
+ if(_y > _y2) {
+ _y = _y1;
+ }
+ }
+}
+
+void GraphicsDisplay::fill(int x, int y, int w, int h, int colour) {
+ window(x, y, w, h);
+ for(int i=0; i<w*h; i++) {
+ putp(colour);
+ }
+}
+
+void GraphicsDisplay::cls() {
+ fill(0, 0, width(), height(), _background);
+}
+
+void GraphicsDisplay::blit(int x, int y, int w, int h, const int *colour) {
+ window(x, y, w, h);
+ for(int i=0; i<w*h; i++) {
+ putp(colour[i]);
+ }
+}
+
+void GraphicsDisplay::blitbit(int x, int y, int w, int h, const char* colour) {
+ window(x, y, w, h);
+ for(int i = 0; i < w*h; i++) {
+ char byte = colour[i >> 3];
+ int offset = i & 0x7;
+ int c = ((byte << offset) & 0x80) ? _foreground : _background;
+ putp(c);
+ }
+}
+
+int GraphicsDisplay::columns() {
+ return width() / 8;
+}
+
+int GraphicsDisplay::rows() {
+ return height() / 8;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/EaEpaper/GraphicsDisplay.h Wed Jul 02 13:19:34 2014 +0000
@@ -0,0 +1,55 @@
+/* mbed GraphicsDisplay Display Library Base Class
+ * Copyright (c) 2007-2009 sford
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * A library for providing a common base class for Graphics displays
+ * To port a new display, derive from this class and implement
+ * the constructor (setup the display), pixel (put a pixel
+ * at a location), width and height functions. Everything else
+ * (locate, printf, putc, cls, window, putp, fill, blit, blitbit)
+ * will come for free. You can also provide a specialised implementation
+ * of window and putp to speed up the results
+ */
+
+#ifndef MBED_GRAPHICSDISPLAY_H
+#define MBED_GRAPHICSDISPLAY_H
+
+#include "TextDisplay.h"
+
+class GraphicsDisplay : public TextDisplay {
+
+public:
+
+ GraphicsDisplay(const char* name);
+
+ virtual void pixel(int x, int y, int colour) = 0;
+ virtual int width() = 0;
+ virtual int height() = 0;
+
+ virtual void window(int x, int y, int w, int h);
+ virtual void putp(int colour);
+
+ virtual void cls();
+ virtual void fill(int x, int y, int w, int h, int colour);
+ virtual void blit(int x, int y, int w, int h, const int *colour);
+ virtual void blitbit(int x, int y, int w, int h, const char* colour);
+
+ virtual void character(int column, int row, int value);
+ virtual int columns();
+ virtual int rows();
+
+protected:
+
+ // pixel location
+ short _x;
+ short _y;
+
+ // window location
+ short _x1;
+ short _x2;
+ short _y1;
+ short _y2;
+
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/EaEpaper/TextDisplay.cpp Wed Jul 02 13:19:34 2014 +0000
@@ -0,0 +1,77 @@
+/* mbed TextDisplay Display Library Base Class
+ * Copyright (c) 2007-2009 sford
+ * Released under the MIT License: http://mbed.org/license/mit
+ */
+
+#include "TextDisplay.h"
+
+TextDisplay::TextDisplay(const char *name) : Stream(name){
+ _row = 0;
+ _column = 0;
+ if (name == NULL) {
+ _path = NULL;
+ } else {
+ _path = new char[strlen(name) + 2];
+ sprintf(_path, "/%s", name);
+ }
+}
+
+int TextDisplay::_putc(int value) {
+ if(value == '\n') {
+ _column = 0;
+ _row++;
+ if(_row >= rows()) {
+ _row = 0;
+ }
+ } else {
+ character(_column, _row, value);
+ _column++;
+ if(_column >= columns()) {
+ _column = 0;
+ _row++;
+ if(_row >= rows()) {
+ _row = 0;
+ }
+ }
+ }
+ return value;
+}
+
+// crude cls implementation, should generally be overwritten in derived class
+void TextDisplay::cls() {
+ locate(0, 0);
+ for(int i=0; i<columns()*rows(); i++) {
+ putc(' ');
+ }
+}
+
+void TextDisplay::locate(int column, int row) {
+ _column = column;
+ _row = row;
+}
+
+int TextDisplay::_getc() {
+ return -1;
+}
+
+void TextDisplay::foreground(uint16_t colour) {
+ _foreground = colour;
+}
+
+void TextDisplay::background(uint16_t colour) {
+ _background = colour;
+}
+
+bool TextDisplay::claim (FILE *stream) {
+ if ( _path == NULL) {
+ fprintf(stderr, "claim requires a name to be given in the instantioator of the TextDisplay instance!\r\n");
+ return false;
+ }
+ if (freopen(_path, "w", stream) == NULL) {
+ // Failed, should not happen
+ return false;
+ }
+ // make sure we use line buffering
+ setvbuf(stdout, NULL, _IOLBF, columns());
+ return true;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/EaEpaper/TextDisplay.h Wed Jul 02 13:19:34 2014 +0000
@@ -0,0 +1,80 @@
+/* mbed TextDisplay Library Base Class
+ * Copyright (c) 2007-2009 sford
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * A common base class for Text displays
+ * To port a new display, derive from this class and implement
+ * the constructor (setup the display), character (put a character
+ * at a location), rows and columns (number of rows/cols) functions.
+ * Everything else (locate, printf, putc, cls) will come for free
+ *
+ * The model is the display will wrap at the right and bottom, so you can
+ * keep writing and will always get valid characters. The location is
+ * maintained internally to the class to make this easy
+ */
+
+#ifndef MBED_TEXTDISPLAY_H
+#define MBED_TEXTDISPLAY_H
+
+#include "mbed.h"
+
+class TextDisplay : public Stream {
+public:
+
+ // functions needing implementation in derived implementation class
+ /** Create a TextDisplay interface
+ *
+ * @param name The name used in the path to access the strean through the filesystem
+ */
+ TextDisplay(const char *name = NULL);
+
+ /** output a character at the given position
+ *
+ * @param column column where charater must be written
+ * @param row where character must be written
+ * @param c the character to be written to the TextDisplay
+ */
+ virtual void character(int column, int row, int c) = 0;
+
+ /** return number if rows on TextDisplay
+ * @result number of rows
+ */
+ virtual int rows() = 0;
+
+ /** return number if columns on TextDisplay
+ * @result number of rows
+ */
+ virtual int columns() = 0;
+
+ // functions that come for free, but can be overwritten
+
+ /** redirect output from a stream (stoud, sterr) to display
+ * @param stream stream that shall be redirected to the TextDisplay
+ */
+ virtual bool claim (FILE *stream);
+
+ /** clear screen
+ */
+ virtual void cls();
+ virtual void locate(int column, int row);
+ virtual void foreground(uint16_t colour);
+ virtual void background(uint16_t colour);
+ // putc (from Stream)
+ // printf (from Stream)
+
+protected:
+
+ virtual int _putc(int value);
+ virtual int _getc();
+
+ // character location
+ uint16_t _column;
+ uint16_t _row;
+
+ // colours
+ uint16_t _foreground;
+ uint16_t _background;
+ char *_path;
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TFT_fonts.lib Wed Jul 02 13:19:34 2014 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/dreschpe/code/TFT_fonts/#76774250fcec
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Wed Jul 02 13:19:34 2014 +0000
@@ -0,0 +1,283 @@
+#include "mbed.h"
+#include "DebouncedInterrupt.h"
+#include "EaEpaper.h"
+#include "Arial28x28.h"
+#include "Arial12x12.h"
+
+//I/O Initialisation
+DigitalOut myled(LED1);
+DigitalOut motor(P0_23);
+#define BUTTON_INTERRUPT_DEBOUNCE_TIME_MS 150
+DebouncedInterrupt buttonOne (P0_16);
+DebouncedInterrupt buttonTwo (P0_17);
+
+//Epaper Init
+EaEpaper epaper(P0_0, //PWR_CONTROL
+ P0_1, //BORDER CONTROL
+ P0_2, //DISCHARGE
+ P0_3, //RESET
+ P0_4, //BUSY
+ P0_5, //SSEL
+ P0_6, //PWM
+ P0_12,P0_13,P0_15, //MOSI,MISO,SCLK
+ P0_22,P0_20);//SDA, SDL
+
+//Notification Data struct
+#define NOTIFICATION_TEXT_MAX_LENGTH 20
+#define NOTIFICATION_TYPE_CALL 0x01
+#define NOTIFICATION_TYPE_SMS 0x02
+#define NOTIFICATION_TYPE_EMAIL 0x03
+#define NOTIFICATION_TYPE_EVENT 0x04
+#define NOTIFICATION_STATE_DELETED 0x00
+#define NOTIFICATION_STATE_UNREAD 0x01
+#define NOTIFICATION_STATE_READ 0x02
+struct Notification{
+ uint8_t type;
+ uint8_t state;
+ char primary_text[NOTIFICATION_TEXT_MAX_LENGTH];
+ char secondary_text[NOTIFICATION_TEXT_MAX_LENGTH];
+ };
+
+//notification storage
+#define MAX_NOTIFICATIONS 20
+Notification notifications[MAX_NOTIFICATIONS];
+uint8_t notification_count = 0;
+int visible_notification_index = -1;
+
+//States
+uint8_t needs_display_update = 0;
+uint8_t has_unread = 0;
+
+//For LED
+#define LED_BLINK_TIME_MS 500
+uint8_t led_on = 0;
+Timer led_timer;
+
+//For Buzzer
+#define BUZZ_TIME_MS 200
+#define MAX_BUZZ_COUNT 3
+uint8_t buzz_count = MAX_BUZZ_COUNT;
+Timer buzz_timer;
+
+void setType(Notification* note, uint8_t type) {
+ note->type = type;
+}
+
+uint8_t isCall(Notification note) {
+ return note.type == NOTIFICATION_TYPE_CALL;
+}
+
+uint8_t isSMS(Notification note) {
+ return note.type == NOTIFICATION_TYPE_SMS;
+}
+
+uint8_t isEmail(Notification note) {
+ return note.type == NOTIFICATION_TYPE_EMAIL;
+}
+
+uint8_t isEvent(Notification note) {
+ return note.type == NOTIFICATION_TYPE_EVENT;
+}
+
+void setState(Notification* note, uint8_t state) {
+ note->state = state;
+}
+
+uint8_t isDeleted(Notification note) {
+ return note.state == NOTIFICATION_STATE_DELETED;
+}
+
+uint8_t isUnread(Notification note) {
+ return note.state == NOTIFICATION_STATE_UNREAD;
+}
+
+uint8_t isRead(Notification note) {
+ return note.state == NOTIFICATION_STATE_READ;
+}
+
+//Update Display to show current notification...
+void doDisplayUpdate() {
+ epaper.cls();
+ if(visible_notification_index >= 0) {
+ //Write current notification...
+ epaper.set_font((unsigned char*)Arial12x12);
+ epaper.locate(5,5);
+ epaper.printf(notifications[visible_notification_index].primary_text);
+ epaper.locate(5,15);
+ epaper.printf(notifications[visible_notification_index].secondary_text);
+ } else {
+ //no notifications...
+ //Write current notification...
+ epaper.set_font((unsigned char*)Arial12x12);
+ epaper.locate(5,5);
+ epaper.printf("No Notifications");
+ }
+ epaper.write_disp();
+ needs_display_update = 0;
+}
+
+//Request a display update..
+void requestDisplayUpdate() {
+ needs_display_update = 1;
+}
+
+//Starts buzz pattern...
+void startBuzz() {
+ //Buzz
+ buzz_count = 0;
+ buzz_timer.reset();
+ buzz_timer.start();
+}
+
+
+//Add Notification...
+int addNotification(Notification note) {
+ //Find insertion point...
+ uint8_t index = 0;
+ for(index = 0; index < MAX_NOTIFICATIONS; index++) {
+ if(isDeleted(notifications[index])) {
+ //Here...
+ break;
+ }
+ }
+ //If here, didn't find insertion point... wrap to beginning.
+ if(index >= MAX_NOTIFICATIONS) index = 0;
+ notifications[index] = note;
+ //Set buzzer
+ startBuzz();
+ //Set unread
+ if(isUnread(note)) has_unread = 1;
+ return index;
+}
+
+void deleteNotification(int index) {
+ setState(¬ifications[index], NOTIFICATION_STATE_DELETED);
+ //Shift array elements left...
+ int i = 0;
+ for (i = index + 1; i < MAX_NOTIFICATIONS; i++) {
+ notifications[i - 1] = notifications[i];
+ }
+}
+
+void checkUnread(){
+ uint8_t i = 0;
+ led_timer.stop();
+ has_unread = 0;
+ for(i = 0; i < MAX_NOTIFICATIONS; i++) {
+ if(isUnread(notifications[i])) {
+ has_unread = 1;
+ led_timer.reset();
+ led_timer.start();
+ break;
+ }
+ }
+}
+
+//Button One Handler
+void buttonOnePressed(){
+ if(visible_notification_index >= 0) {
+ //Increment index, wrap to beginning if last.
+ visible_notification_index++;
+ if(visible_notification_index >= MAX_NOTIFICATIONS || isDeleted(notifications[visible_notification_index])) {
+ visible_notification_index = 0;
+ if(isDeleted(notifications[visible_notification_index])) {
+ //Still deleted... none...
+ visible_notification_index = -1;
+ }
+ }
+ //Trigger display update...
+ requestDisplayUpdate();
+ }
+}
+
+//Button Two handler
+void buttonTwoPressed(){
+ if(visible_notification_index >= 0) {
+ if(!isDeleted(notifications[visible_notification_index])) {
+ //Exists.
+ if(isUnread(notifications[visible_notification_index])) {
+ //Toggle to 'read'
+ setState(¬ifications[visible_notification_index], NOTIFICATION_STATE_READ);
+ checkUnread();
+ } else if (isRead(notifications[visible_notification_index])) {
+ //Already 'read'... delete, this also shifts remaining notifications down...
+ deleteNotification(visible_notification_index);
+ //If current is deleted...
+ if(isDeleted(notifications[visible_notification_index])) {
+ //We're at end, so wrap...
+ visible_notification_index = 0;
+ if(isDeleted(notifications[visible_notification_index])) {
+ //Still deleted... so there are none...
+ visible_notification_index = -1;
+ }
+ }
+ //Otherwise, we've got one, so we should be ok...
+ }
+
+ //Trigger display update...
+ requestDisplayUpdate();
+ }
+ }
+}
+
+//Initialise notification data...
+void initNotificationData() {
+ //For debug purposes...
+ notifications[0].type = NOTIFICATION_TYPE_CALL;
+ notifications[0].state = NOTIFICATION_STATE_UNREAD;
+ strcpy(notifications[0].primary_text,"Eric Gowland");
+ strcpy(notifications[0].secondary_text, "07770909177");
+
+ notifications[1].type = NOTIFICATION_TYPE_EMAIL;
+ notifications[1].state = NOTIFICATION_STATE_UNREAD;
+ strcpy(notifications[1].primary_text, "Dear Sir I have $US");
+ strcpy(notifications[1].secondary_text, "not@scam.net");
+
+ //Set location, etc.
+ visible_notification_index = 0;
+ checkUnread();
+ requestDisplayUpdate();
+ startBuzz();
+}
+
+//Main Program Function
+int main() {
+ //Init Data
+ initNotificationData();
+ //Attach interrupt handlers...
+ buttonOne.attach(buttonOnePressed, IRQ_RISE, BUTTON_INTERRUPT_DEBOUNCE_TIME_MS);
+ buttonTwo.attach(buttonTwoPressed, IRQ_RISE, BUTTON_INTERRUPT_DEBOUNCE_TIME_MS);
+ //Request display update...
+ requestDisplayUpdate();
+ while(1) {
+ if(needs_display_update){
+ doDisplayUpdate();
+ } else {
+ //If state hasn't changed, just action timers...
+ //Unread LED
+ if(has_unread) {
+ //LED flashing...
+ if(led_timer.read_ms() > LED_BLINK_TIME_MS) {
+ myled = !myled;
+ led_timer.reset();
+ }
+ } else {
+ myled = 0;
+ led_timer.stop();
+ }
+
+ //Buzz
+ if(buzz_count < MAX_BUZZ_COUNT) {
+ //Buzzing...
+ if(buzz_timer.read_ms() > BUZZ_TIME_MS) {
+ motor = !motor;
+ if(!motor) buzz_count++;
+ buzz_timer.reset();
+ }
+ } else {
+ motor = 0;
+ buzz_timer.stop();
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Wed Jul 02 13:19:34 2014 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/024bf7f99721 \ No newline at end of file
