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: Final HCSR04 TB6612FNG
Revision 97:b483e656bd14, committed 2019-06-16
- Comitter:
- eunmango
- Date:
- Sun Jun 16 04:44:35 2019 +0000
- Parent:
- 96:ec3a2da01f40
- Commit message:
- t
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HCSR04.lib Sun Jun 16 04:44:35 2019 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/teams/Embedded-Class-Final-Project1/code/HCSR04/#b3401c36a10b
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/IRremote.lib Sun Jun 16 04:44:35 2019 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/teams/Embedded-Class-Final-Project/code/Final/#0650578366fd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TB6612FNG.lib Sun Jun 16 04:44:35 2019 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/Pinski1/code/TB6612FNG/#7f18197d1210
--- a/main.cpp Fri May 31 13:00:04 2019 +0100
+++ b/main.cpp Sun Jun 16 04:44:35 2019 +0000
@@ -1,32 +1,432 @@
-/* mbed Microcontroller Library
- * Copyright (c) 2018 ARM Limited
- * SPDX-License-Identifier: Apache-2.0
- */
+#include "mbed.h"
+#include <iostream>
+#include "HCSR04.h"
+#include <list>
+#include <string.h>
+#include <IRremote.h>
+#include "TB6612FNG.h"
+//#define PCF8574_ADDR (0x40)
+#define LEFT 127
+#define RIGHT 191
+#define NUMSENSORS 5
+#define MAX 1023
+#define MIN 0
+#define TRU 1
+#define FALS 0
+#define MaxSpeed 255// max speed of the robot
+#define BaseSpeed 155
+#define speedt 180
+
+#include "SSD1306-Library.h"
+#include "FreeSans9pt7b.h"
+#include <time.h>
+#include <math.h>
+
+#define KEY2 0xFF18E7 //Key:2
+#define KEY8 0xFF52AD //Key:8
+#define KEY4 0xFF08F7 //Key:4
+#define KEY6 0xFF5AA5 //Key:6
+#define KEY1 0xFF0CF3 //Key:1
+#define KEY3 0xFF5EA1 //Key:3
+#define KEY5 0xFF1CE3 //Key:5
+
+
+//I2C i2c(I2C_SDA, I2C_SCL); //D15,D14
+SPI spi(D11, D12, D13);
+DigitalOut cs(D10,1);
+Serial pc(PA_2, PA_3, 115200); //D1 D0
+IRrecv irrecv(D4);
+
+
+int mode=1;
+int index=0;
+int rx_buffer[10];
+char arr[16];
+volatile int flag = 0;
+float interval=0.1; //100ms
+decode_results result;
+
+
+
+/////////sensors////////////
+
+int temp=0;
+int calibratedMin[NUMSENSORS];
+int calibratedMax[NUMSENSORS];
+unsigned int sensor_values[NUMSENSORS];
+int in_line[NUMSENSORS];
+int ultra_flag=0;
+float position;
+
+/////////sensors////////////
+
+/////////Ultrasonic////////////
+Ultrasonic ultra(D3, D2);
+int ultra_result=10;
+/////////Ultrasonic////////////
+
+
+//////////motor////////////
+PwmOut motor_pwmA(PB_10); //D6
+PwmOut motor_pwmb(PB_4); // D5
+AnalogIn rightMotor2(A0);
+AnalogIn rightMotor1(A1);
+AnalogIn leftMotor2(A3);
+AnalogIn leftMotor1(A2);
+
+TB6612FNG leftmotor(PB_10, A1, A0);
+TB6612FNG rightmotor(PB_4, A2, A3);
+float last_proportional;
+float integral;
+float kp = 0.5;
+float kd = 0.1;
+int lastError;
+//////////motor////////////
+
+void IRForward(void)
+{
+ leftmotor.setSpeed(0.1);
+ rightmotor.setSpeed(0.1);
+
+}
+
+void ultraLeft(){
+ leftmotor.setSpeed(-0.13);
+ rightmotor.setSpeed(0.15);
+}
+
+void left(void)
+{
+ leftmotor.setSpeed(0.03);
+ rightmotor.setSpeed(0.15);
+}
+
+
+void right(void)
+{
+ leftmotor.setSpeed(0.15);
+ rightmotor.setSpeed(0.03);
+}
+
+void stop(void)
+{
+ leftmotor.setSpeed(0);
+ rightmotor.setSpeed(0);
+}
+
+void CalibrationMotor(void)
+{
+ leftmotor.setSpeed(0.15);
+ rightmotor.setSpeed(-0.15);
+}
+
+void backward(void)
+{
+ leftmotor.setSpeed(-0.1);
+ rightmotor.setSpeed(-0.1);
+}
+
-#include "mbed.h"
-#include "stats_report.h"
+//bool pcf8574_write(uint8_t data){
+// return i2c.write(PCF8574_ADDR, (char*) &data, 1, 0) == 0;
+//}
+//
+//bool pcf8574_read(uint8_t* data){
+// return i2c.read(PCF8574_ADDR, (char*) data, 1, 0) == 0;
+//}
+//
+//int pcf8574_test(uint8_t value){
+//
+// int ret;
+// uint8_t data=0;
+//
+// ret = pcf8574_write(value);
+// if(!ret) return -1;
+//
+// ret = pcf8574_read(&data);
+// if(!ret) return -2;
+//
+// return data;
+//}
+//
+//void detected(void)
+//{
+// pcf8574_test(0xff);
+// while(pcf8574_test(0xff)<255) pcf8574_test(0x00);
+//}
+
+int state=0; //0:forward / 1:left / 2:right
+int cnt=0;
+ int period_us;
+ int beat_ms;
-DigitalOut led1(LED1);
+void TRSensors(void) {
+
+ for(int i=0; i< NUMSENSORS ; i++) {
+ calibratedMin[i]= MAX;
+ calibratedMax[i] = MIN;
+ }
+
+}
+
+void set_TLC1543 (void) {
+
+ int value;
+ for(int i=0; i<6 ; i++){
+ cs=0;
+ wait_us(2);
+ value=spi.write(i<<12);
+ cs=1;
+ wait_us(21);
+ cs=0;
+ wait_us(2);
+ value=spi.write(i<<12);
+ //pc.printf("%d th : 0x%X\r\n", i, value);
+ cs=1;
+ wait_us(21);
+ sensor_values[i]=value;
+ }
+}
+
+void calibrate(void){
+ int i;
+
+ unsigned int max_sensor_values[NUMSENSORS];
+ unsigned int min_sensor_values[NUMSENSORS];
+
+ int j;
+ for(j=0; j <10 ; j++){
+ set_TLC1543();
+ for(i=0; i<NUMSENSORS; i++){
+ if(j==0 || max_sensor_values[i] < sensor_values[i]) max_sensor_values[i] = sensor_values[i];
+ if(j==0 || min_sensor_values[i] > sensor_values[i]) min_sensor_values[i] = sensor_values[i];
+ }
+ }
+
+ for(i=0; i<NUMSENSORS; i++){
+ if(min_sensor_values[i] > calibratedMax[i]) calibratedMax[i] = min_sensor_values[i];
+ if(max_sensor_values[i] < calibratedMin[i]) calibratedMin[i] = max_sensor_values[i];
+ }
+
+}
-#define SLEEP_TIME 500 // (msec)
-#define PRINT_AFTER_N_LOOPS 20
+void readCalibrated(){
+ int i;
+ set_TLC1543();
+ for(i=0; i<NUMSENSORS ; i++){
+ //unsigned int calmin, calmax;
+ unsigned int denominator;
+ denominator = calibratedMax[i] - calibratedMin[i];
+ signed int x =0;
+ if(denominator !=0) {
+ x = ( ( (signed long)sensor_values[i] ) -calibratedMin[i]) * 1000 / denominator;
+ }
+ if(x<0) x=0;
+ else if(x>1000) x= 1000;
+ else sensor_values[i] = x;
+ }
+}
-// main() runs in its own thread in the OS
+int readLine() {
+ unsigned char i, on_line =0;
+ unsigned long avg;
+ unsigned int sum;
+ static int last_value=0;
+
+ readCalibrated();
+ avg =0; sum =0;
+ for(i=0; i< NUMSENSORS; i++){
+ int value = sensor_values[i];
+ value = 1000-value;
+ sensor_values[i]=value;
+ in_line[i]=FALS;
+ if(value > 300) {
+ on_line =1;
+ in_line[i]=TRU;
+ }
+ //if(value > calibratedMin[i]) on_line=1;
+ if(value > 50){
+ avg += (long)(value)*(i*1000);
+ sum += value;
+ }
+ }
+
+ if(!on_line){
+ if(last_value < (NUMSENSORS-1)*1000/2) return 0;
+ else return ( NUMSENSORS-1 ) * 1000;
+ }
+
+ last_value = avg/sum;
+
+ return last_value;
+
+}
+
+/****************************************************************
+before running, set up tlc1543, calibrate **********************/
+void settlc1543(){
+ cs =1;
+ spi.format(16,0);
+ spi.frequency(2000000);
+ pc.printf("test\r\n");
+ //pc.attach(callback(&rx_cb));
+
+ TRSensors();
+ for(int i=0; i<10; i++) {
+ calibrate();
+ wait(0.4);
+ }
+// pc.printf("calibrate done\r\n");
+ for(int i=0; i<NUMSENSORS; i++) {
+// pc.printf("Calibration Min: %d Max: %d\r\n", calibratedMin[i], calibratedMax[i] );
+ }
+}
+
+
+void rx_cb(void) {
+
+ int ch;
+ ch = pc.getc();
+ rx_buffer[index]=ch;
+ index++;
+ pc.putc(ch);
+ if(ch==0x0D) {
+ pc.putc(0x0A);
+ flag=1;
+ index=0;
+ }
+
+
+}
+
+
int main()
{
- SystemReport sys_state( SLEEP_TIME * PRINT_AFTER_N_LOOPS /* Loop delay time in ms */);
+ clock_t t;
+ int f;
+ char displaySentence[40] = "Time is ";
+ char time[20];
+ irrecv.enableIRIn();
+// mu.startUpdates();//start mesuring the distance
+ int data;
+
+ SSD1306 display = SSD1306();
+
+ while(1){
+
+ if(irrecv.decode(&result)){
+ pc.printf("%X\r\n",result.value);
+ irrecv.resume();
+
+ if(result.value == KEY1){ // 1
+ break;
+ }
+ if(result.value == KEY2){ // 2
+ IRForward();
+ }
+ if(result.value == KEY3){ // 3
+ CalibrationMotor();
+ settlc1543();
+
+ }
+ if(result.value == KEY6){ // 6
+ right();
- int count = 0;
- while (true) {
- // Blink LED and wait 0.5 seconds
- led1 = !led1;
- wait_ms(SLEEP_TIME);
+ }
+ if(result.value == KEY4){ // 4
+ left();
+ }
+ if(result.value == KEY8 ){ // 8
+ backward();
+ }
+ if(result.value == KEY5){ // 5
+ stop();
+ }
+ }
+
+ }
+
+
+
+ t=clock();
+ pc.printf("Hello PCF8574\n");
+ while (1) {
+
+ ultra_result = ultra.distance();
+ if(ultra_result > 0 && ultra_result < 14) {
+ if(in_line[0]==TRU && in_line[1]==TRU ){
+ stop();
+ mode = 2;
+ }
+
+ }
+
- if ((0 == count) || (PRINT_AFTER_N_LOOPS == count)) {
- // Following the main thread wait, report on the current system status
- sys_state.report_state();
- count = 0;
- }
- ++count;
+ if(mode == 1){
+ pc.printf("enter\r\n");
+ position = (float)readLine();
+ pc.printf("position: %f\r\n", position);
+ float proportional =(float)(position-2000.0); //e(t)
+ float derivative = (float)(proportional - last_proportional);
+ integral += proportional;
+ last_proportional = proportional;//
+ //pid 15/60000/2 - 85%
+ float power_difference = proportional/16.0+ (float)integral/
+ 60000.0+ derivative*2.0; //integral 변수 커지고 작아지는 값 확인하
+ pc.printf("proportional : %f integral %f derivative : %f \r\n", proportional, integral, derivative);
+ const int maximum = 255;
+ const int base = 155;
+ pc.printf("power_difference is %f\r\n" , power_difference);
+ if(power_difference > base ) power_difference = base;
+ if(power_difference < -base) power_difference = -base;
+
+
+
+ if(power_difference < 0){ //오른쪽으로 빠
+ // rightmotor.setSpeed((float)(base + power_difference) / (float)maximum);
+ // leftmotor.setSpeed((float)base-power_difference/(float)maximum);
+ pc.printf("right : left %f, right %f \r\n",(float)(base+power_difference) / (float)maximum , (float)(base) / (float)maximum );
+ rightmotor.setSpeed((float)(base) / (float)maximum);
+ leftmotor.setSpeed((float)(base+power_difference) / (float)maximum );
+ } else{// 왼//쪽으로 빠짐.
+ // rightmotor.setSpeed((float)(base + power_difference) / (float)maximum);
+ // leftmotor.setSpeed((float)base-power_difference/(float)maximum);
+ pc.printf("left : left %f, right %f \r\n",(float)(base) / (float)maximum , (float)(base -power_difference) / (float)maximum );
+ leftmotor.setSpeed((float)(base) / (float)maximum);
+ rightmotor.setSpeed((float)(base -power_difference) / (float)maximum);
+
+ }
+
+ if(in_line[0]&&in_line[1]&&in_line[2]&&in_line[3]&&in_line[4]){
+ leftmotor.setSpeed(0);
+ rightmotor.setSpeed(0);
+ pc.printf("stop\r\n");
+ //시간 모니터에 출력.
+ break;
+ }
+ }
+
+ if(mode == 2){
+ ultra_result = ultra.distance();
+
+ for(int i=0; i<50; i++){
+ data = readLine();
+ if(in_line[2]==TRU && in_line[1]==FALS && in_line[3]==FALS && in_line[0]==FALS && in_line[4]==FALS)
+ {
+ mode=1;
+ break;
+ }
+ ultraLeft();
+ }
+ }
}
-}
+ display.begin(true);
+ display.setTextSize(1);
+ display.setTextColor(WHITE);
+ display.setCursor(0,0);
+ t=clock()-t;
+ sprintf(time, "%f ms", (float)t*10);
+ strcat(displaySentence, time);
+ display.println(displaySentence);
+ display.display();
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/oled/Adafruit_GFX.cpp Sun Jun 16 04:44:35 2019 +0000
@@ -0,0 +1,752 @@
+/*
+This is the core graphics library for all our displays, providing a common
+set of graphics primitives (points, lines, circles, etc.). It needs to be
+paired with a hardware-specific library for each display device we carry
+(to handle the lower-level functions).
+
+Adafruit invests time and resources providing this open source code, please
+support Adafruit & open-source hardware by purchasing products from Adafruit!
+
+Copyright (c) 2013 Adafruit Industries. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "Adafruit_GFX.h"
+#include "glcdfont.c"
+
+// Many (but maybe not all) non-AVR board installs define macros
+// for compatibility with existing PROGMEM-reading AVR code.
+// Do our own checks and defines here for good measure...
+
+#ifndef pgm_read_byte
+ #define pgm_read_byte(addr) (*(const unsigned char *)(addr))
+#endif
+#ifndef pgm_read_word
+ #define pgm_read_word(addr) (*(const unsigned short *)(addr))
+#endif
+#ifndef pgm_read_dword
+ #define pgm_read_dword(addr) (*(const unsigned long *)(addr))
+#endif
+
+// Pointers are a peculiar case...typically 16-bit on AVR boards,
+// 32 bits elsewhere. Try to accommodate both...
+
+#if !defined(__INT_MAX__) || (__INT_MAX__ > 0xFFFF)
+ #define pgm_read_pointer(addr) ((void *)pgm_read_dword(addr))
+#else
+ #define pgm_read_pointer(addr) ((void *)pgm_read_word(addr))
+#endif
+
+#ifndef min
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef _swap_int16_t
+#define _swap_int16_t(a, b) { int16_t t = a; a = b; b = t; }
+#endif
+
+Adafruit_GFX::Adafruit_GFX(int16_t w, int16_t h):
+ WIDTH(w), HEIGHT(h)
+{
+ _width = WIDTH;
+ _height = HEIGHT;
+ rotation = 0;
+ cursor_y = cursor_x = 0;
+ textsize = 1;
+ textcolor = textbgcolor = 0xFFFF;
+ wrap = true;
+ gfxFont = NULL;
+}
+
+// Draw a circle outline
+void Adafruit_GFX::drawCircle(int16_t x0, int16_t y0, int16_t r,
+ uint16_t color) {
+ int16_t f = 1 - r;
+ int16_t ddF_x = 1;
+ int16_t ddF_y = -2 * r;
+ int16_t x = 0;
+ int16_t y = r;
+
+ drawPixel(x0 , y0+r, color);
+ drawPixel(x0 , y0-r, color);
+ drawPixel(x0+r, y0 , color);
+ drawPixel(x0-r, y0 , color);
+
+ while (x<y) {
+ if (f >= 0) {
+ y--;
+ ddF_y += 2;
+ f += ddF_y;
+ }
+ x++;
+ ddF_x += 2;
+ f += ddF_x;
+
+ drawPixel(x0 + x, y0 + y, color);
+ drawPixel(x0 - x, y0 + y, color);
+ drawPixel(x0 + x, y0 - y, color);
+ drawPixel(x0 - x, y0 - y, color);
+ drawPixel(x0 + y, y0 + x, color);
+ drawPixel(x0 - y, y0 + x, color);
+ drawPixel(x0 + y, y0 - x, color);
+ drawPixel(x0 - y, y0 - x, color);
+ }
+}
+
+void Adafruit_GFX::drawCircleHelper( int16_t x0, int16_t y0,
+ int16_t r, uint8_t cornername, uint16_t color) {
+ int16_t f = 1 - r;
+ int16_t ddF_x = 1;
+ int16_t ddF_y = -2 * r;
+ int16_t x = 0;
+ int16_t y = r;
+
+ while (x<y) {
+ if (f >= 0) {
+ y--;
+ ddF_y += 2;
+ f += ddF_y;
+ }
+ x++;
+ ddF_x += 2;
+ f += ddF_x;
+ if (cornername & 0x4) {
+ drawPixel(x0 + x, y0 + y, color);
+ drawPixel(x0 + y, y0 + x, color);
+ }
+ if (cornername & 0x2) {
+ drawPixel(x0 + x, y0 - y, color);
+ drawPixel(x0 + y, y0 - x, color);
+ }
+ if (cornername & 0x8) {
+ drawPixel(x0 - y, y0 + x, color);
+ drawPixel(x0 - x, y0 + y, color);
+ }
+ if (cornername & 0x1) {
+ drawPixel(x0 - y, y0 - x, color);
+ drawPixel(x0 - x, y0 - y, color);
+ }
+ }
+}
+
+void Adafruit_GFX::fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color) {
+ drawFastVLine(x0, y0-r, 2*r+1, color);
+ fillCircleHelper(x0, y0, r, 3, 0, color);
+}
+
+// Used to do circles and roundrects
+void Adafruit_GFX::fillCircleHelper(int16_t x0, int16_t y0, int16_t r,
+ uint8_t cornername, int16_t delta, uint16_t color) {
+
+ int16_t f = 1 - r;
+ int16_t ddF_x = 1;
+ int16_t ddF_y = -2 * r;
+ int16_t x = 0;
+ int16_t y = r;
+
+ while (x<y) {
+ if (f >= 0) {
+ y--;
+ ddF_y += 2;
+ f += ddF_y;
+ }
+ x++;
+ ddF_x += 2;
+ f += ddF_x;
+
+ if (cornername & 0x1) {
+ drawFastVLine(x0+x, y0-y, 2*y+1+delta, color);
+ drawFastVLine(x0+y, y0-x, 2*x+1+delta, color);
+ }
+ if (cornername & 0x2) {
+ drawFastVLine(x0-x, y0-y, 2*y+1+delta, color);
+ drawFastVLine(x0-y, y0-x, 2*x+1+delta, color);
+ }
+ }
+}
+
+// Bresenham's algorithm - thx wikpedia
+void Adafruit_GFX::drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1,
+ uint16_t color) {
+ int16_t steep = abs(y1 - y0) > abs(x1 - x0);
+ if (steep) {
+ _swap_int16_t(x0, y0);
+ _swap_int16_t(x1, y1);
+ }
+
+ if (x0 > x1) {
+ _swap_int16_t(x0, x1);
+ _swap_int16_t(y0, y1);
+ }
+
+ int16_t dx, dy;
+ dx = x1 - x0;
+ dy = abs(y1 - y0);
+
+ int16_t err = dx / 2;
+ int16_t ystep;
+
+ if (y0 < y1) {
+ ystep = 1;
+ } else {
+ ystep = -1;
+ }
+
+ for (; x0<=x1; x0++) {
+ if (steep) {
+ drawPixel(y0, x0, color);
+ } else {
+ drawPixel(x0, y0, color);
+ }
+ err -= dy;
+ if (err < 0) {
+ y0 += ystep;
+ err += dx;
+ }
+ }
+}
+
+// Draw a rectangle
+void Adafruit_GFX::drawRect(int16_t x, int16_t y, int16_t w, int16_t h,
+ uint16_t color) {
+ drawFastHLine(x, y, w, color);
+ drawFastHLine(x, y+h-1, w, color);
+ drawFastVLine(x, y, h, color);
+ drawFastVLine(x+w-1, y, h, color);
+}
+
+void Adafruit_GFX::drawFastVLine(int16_t x, int16_t y,
+ int16_t h, uint16_t color) {
+ // Update in subclasses if desired!
+ drawLine(x, y, x, y+h-1, color);
+}
+
+void Adafruit_GFX::drawFastHLine(int16_t x, int16_t y,
+ int16_t w, uint16_t color) {
+ // Update in subclasses if desired!
+ drawLine(x, y, x+w-1, y, color);
+}
+
+void Adafruit_GFX::fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
+ uint16_t color) {
+ // Update in subclasses if desired!
+ for (int16_t i=x; i<x+w; i++) {
+ drawFastVLine(i, y, h, color);
+ }
+}
+
+void Adafruit_GFX::fillScreen(uint16_t color) {
+ fillRect(0, 0, _width, _height, color);
+}
+
+// Draw a rounded rectangle
+void Adafruit_GFX::drawRoundRect(int16_t x, int16_t y, int16_t w,
+ int16_t h, int16_t r, uint16_t color) {
+ // smarter version
+ drawFastHLine(x+r , y , w-2*r, color); // Top
+ drawFastHLine(x+r , y+h-1, w-2*r, color); // Bottom
+ drawFastVLine(x , y+r , h-2*r, color); // Left
+ drawFastVLine(x+w-1, y+r , h-2*r, color); // Right
+ // draw four corners
+ drawCircleHelper(x+r , y+r , r, 1, color);
+ drawCircleHelper(x+w-r-1, y+r , r, 2, color);
+ drawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color);
+ drawCircleHelper(x+r , y+h-r-1, r, 8, color);
+}
+
+// Fill a rounded rectangle
+void Adafruit_GFX::fillRoundRect(int16_t x, int16_t y, int16_t w,
+ int16_t h, int16_t r, uint16_t color) {
+ // smarter version
+ fillRect(x+r, y, w-2*r, h, color);
+
+ // draw four corners
+ fillCircleHelper(x+w-r-1, y+r, r, 1, h-2*r-1, color);
+ fillCircleHelper(x+r , y+r, r, 2, h-2*r-1, color);
+}
+
+// Draw a triangle
+void Adafruit_GFX::drawTriangle(int16_t x0, int16_t y0,
+ int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color) {
+ drawLine(x0, y0, x1, y1, color);
+ drawLine(x1, y1, x2, y2, color);
+ drawLine(x2, y2, x0, y0, color);
+}
+
+// Fill a triangle
+void Adafruit_GFX::fillTriangle(int16_t x0, int16_t y0,
+ int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color) {
+
+ int16_t a, b, y, last;
+
+ // Sort coordinates by Y order (y2 >= y1 >= y0)
+ if (y0 > y1) {
+ _swap_int16_t(y0, y1); _swap_int16_t(x0, x1);
+ }
+ if (y1 > y2) {
+ _swap_int16_t(y2, y1); _swap_int16_t(x2, x1);
+ }
+ if (y0 > y1) {
+ _swap_int16_t(y0, y1); _swap_int16_t(x0, x1);
+ }
+
+ if(y0 == y2) { // Handle awkward all-on-same-line case as its own thing
+ a = b = x0;
+ if(x1 < a) a = x1;
+ else if(x1 > b) b = x1;
+ if(x2 < a) a = x2;
+ else if(x2 > b) b = x2;
+ drawFastHLine(a, y0, b-a+1, color);
+ return;
+ }
+
+ int16_t
+ dx01 = x1 - x0,
+ dy01 = y1 - y0,
+ dx02 = x2 - x0,
+ dy02 = y2 - y0,
+ dx12 = x2 - x1,
+ dy12 = y2 - y1;
+ int32_t
+ sa = 0,
+ sb = 0;
+
+ // For upper part of triangle, find scanline crossings for segments
+ // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1
+ // is included here (and second loop will be skipped, avoiding a /0
+ // error there), otherwise scanline y1 is skipped here and handled
+ // in the second loop...which also avoids a /0 error here if y0=y1
+ // (flat-topped triangle).
+ if(y1 == y2) last = y1; // Include y1 scanline
+ else last = y1-1; // Skip it
+
+ for(y=y0; y<=last; y++) {
+ a = x0 + sa / dy01;
+ b = x0 + sb / dy02;
+ sa += dx01;
+ sb += dx02;
+ /* longhand:
+ a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
+ b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
+ */
+ if(a > b) _swap_int16_t(a,b);
+ drawFastHLine(a, y, b-a+1, color);
+ }
+
+ // For lower part of triangle, find scanline crossings for segments
+ // 0-2 and 1-2. This loop is skipped if y1=y2.
+ sa = dx12 * (y - y1);
+ sb = dx02 * (y - y0);
+ for(; y<=y2; y++) {
+ a = x1 + sa / dy12;
+ b = x0 + sb / dy02;
+ sa += dx12;
+ sb += dx02;
+ /* longhand:
+ a = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
+ b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
+ */
+ if(a > b) _swap_int16_t(a,b);
+ drawFastHLine(a, y, b-a+1, color);
+ }
+}
+
+
+// Draw a 1-bit image (bitmap) at the specified (x,y) position from the
+// provided bitmap buffer using the specified
+// foreground color (unset bits are transparent).
+void Adafruit_GFX::drawBitmap(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;
+ uint8_t byte;
+
+ for(j=0; j<h; j++) {
+ for(i=0; i<w; i++ ) {
+ if(i & 7) byte <<= 1;
+ else byte = bitmap[j * byteWidth + i / 8];
+ if(byte & 0x80) drawPixel(x+i, y+j, color);
+ }
+ }
+}
+
+// Draw a 1-bit image (bitmap) at the specified (x,y) position from the
+// provided bitmap buffer using the specified
+// foreground (for set bits) and background (for clear bits) colors.
+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;
+ uint8_t byte;
+
+ for(j=0; j<h; j++) {
+ for(i=0; i<w; i++ ) {
+ if(i & 7) byte <<= 1;
+ else byte = bitmap[j * byteWidth + i / 8];
+ if(byte & 0x80) 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;
+ uint8_t byte;
+
+ for(j=0; j<h; j++) {
+ for(i=0; i<w; i++ ) {
+ if(i & 7) byte >>= 1;
+ else byte = pgm_read_byte(bitmap + j * byteWidth + i / 8);
+ if(byte & 0x01) drawPixel(x+i, y+j, color);
+ }
+ }
+}
+
+size_t Adafruit_GFX::write(uint8_t c) {
+ if(!gfxFont) { // 'Classic' built-in font
+
+ if(c == '\n') {
+ cursor_y += textsize*8;
+ cursor_x = 0;
+ } else if(c == '\r') {
+ // skip em
+ } else {
+ if(wrap && ((cursor_x + textsize * 6) >= _width)) { // Heading off edge?
+ cursor_x = 0; // Reset x to zero
+ cursor_y += textsize * 8; // Advance y one line
+ }
+ drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize);
+ cursor_x += textsize * 6;
+ }
+
+ } else { // Custom font
+
+ if(c == '\n') {
+ cursor_x = 0;
+ cursor_y += (int16_t)textsize *
+ (uint8_t)pgm_read_byte(&gfxFont->yAdvance);
+ } else if(c != '\r') {
+ uint8_t first = pgm_read_byte(&gfxFont->first);
+ if((c >= first) && (c <= (uint8_t)pgm_read_byte(&gfxFont->last))) {
+ uint8_t c2 = c - pgm_read_byte(&gfxFont->first);
+ GFXglyph *glyph = &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c2]);
+ uint8_t w = pgm_read_byte(&glyph->width),
+ h = pgm_read_byte(&glyph->height);
+ if((w > 0) && (h > 0)) { // Is there an associated bitmap?
+ int16_t xo = (int8_t)pgm_read_byte(&glyph->xOffset); // sic
+ if(wrap && ((cursor_x + textsize * (xo + w)) >= _width)) {
+ // Drawing character would go off right edge; wrap to new line
+ cursor_x = 0;
+ cursor_y += (int16_t)textsize *
+ (uint8_t)pgm_read_byte(&gfxFont->yAdvance);
+ }
+ drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize);
+ }
+ cursor_x += pgm_read_byte(&glyph->xAdvance) * (int16_t)textsize;
+ }
+ }
+
+ }
+ return 1;
+}
+
+// Draw a character
+void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c,
+ uint16_t color, uint16_t bg, uint8_t size) {
+
+ if(!gfxFont) { // 'Classic' built-in font
+
+ if((x >= _width) || // Clip right
+ (y >= _height) || // Clip bottom
+ ((x + 6 * size - 1) < 0) || // Clip left
+ ((y + 8 * size - 1) < 0)) // Clip top
+ return;
+
+ for(int8_t i=0; i<6; i++ ) {
+ uint8_t line;
+ if(i < 5) line = pgm_read_byte(font+(c*5)+i);
+ else line = 0x0;
+ for(int8_t j=0; j<8; j++, line >>= 1) {
+ if(line & 0x1) {
+ if(size == 1) drawPixel(x+i, y+j, color);
+ else fillRect(x+(i*size), y+(j*size), size, size, color);
+ } else if(bg != color) {
+ if(size == 1) drawPixel(x+i, y+j, bg);
+ else fillRect(x+i*size, y+j*size, size, size, bg);
+ }
+ }
+ }
+
+ } else { // Custom font
+
+ // Character is assumed previously filtered by write() to eliminate
+ // newlines, returns, non-printable characters, etc. Calling drawChar()
+ // directly with 'bad' characters of font may cause mayhem!
+
+ c -= pgm_read_byte(&gfxFont->first);
+ GFXglyph *glyph = &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c]);
+ uint8_t *bitmap = (uint8_t *)pgm_read_pointer(&gfxFont->bitmap);
+
+ uint16_t bo = pgm_read_word(&glyph->bitmapOffset);
+ uint8_t w = pgm_read_byte(&glyph->width),
+ h = pgm_read_byte(&glyph->height),
+ xa = pgm_read_byte(&glyph->xAdvance);
+ int8_t xo = pgm_read_byte(&glyph->xOffset);
+ int8_t yo = pgm_read_byte(&glyph->yOffset);
+ uint8_t xx, yy, bits, bit = 0;
+ int16_t xo16, yo16;
+
+ if(size > 1) {
+ xo16 = xo;
+ yo16 = yo;
+ }
+
+ // Todo: Add character clipping here
+
+ // NOTE: THERE IS NO 'BACKGROUND' COLOR OPTION ON CUSTOM FONTS.
+ // THIS IS ON PURPOSE AND BY DESIGN. The background color feature
+ // has typically been used with the 'classic' font to overwrite old
+ // screen contents with new data. This ONLY works because the
+ // characters are a uniform size; it's not a sensible thing to do with
+ // proportionally-spaced fonts with glyphs of varying sizes (and that
+ // may overlap). To replace previously-drawn text when using a custom
+ // font, use the getTextBounds() function to determine the smallest
+ // rectangle encompassing a string, erase the area with fillRect(),
+ // then draw new text. This WILL infortunately 'blink' the text, but
+ // is unavoidable. Drawing 'background' pixels will NOT fix this,
+ // only creates a new set of problems. Have an idea to work around
+ // this (a canvas object type for MCUs that can afford the RAM and
+ // displays supporting setAddrWindow() and pushColors()), but haven't
+ // implemented this yet.
+
+ for(yy=0; yy<h; yy++) {
+ for(xx=0; xx<w; xx++) {
+ if(!(bit++ & 7)) {
+ bits = pgm_read_byte(&bitmap[bo++]);
+ }
+ if(bits & 0x80) {
+ if(size == 1) {
+ drawPixel(x+xo+xx, y+yo+yy, color);
+ } else {
+ fillRect(x+(xo16+xx)*size, y+(yo16+yy)*size, size, size, color);
+ }
+ }
+ bits <<= 1;
+ }
+ }
+
+ } // End classic vs custom font
+}
+
+void Adafruit_GFX::setCursor(int16_t x, int16_t y) {
+ cursor_x = x;
+ cursor_y = y;
+}
+
+int16_t Adafruit_GFX::getCursorX(void) const {
+ return cursor_x;
+}
+
+int16_t Adafruit_GFX::getCursorY(void) const {
+ return cursor_y;
+}
+
+void Adafruit_GFX::setTextSize(uint8_t s) {
+ textsize = (s > 0) ? s : 1;
+}
+
+void Adafruit_GFX::setTextColor(uint16_t c) {
+ // For 'transparent' background, we'll set the bg
+ // to the same as fg instead of using a flag
+ textcolor = textbgcolor = c;
+}
+
+void Adafruit_GFX::setTextColor(uint16_t c, uint16_t b) {
+ textcolor = c;
+ textbgcolor = b;
+}
+
+void Adafruit_GFX::setTextWrap(bool w) {
+ wrap = w;
+}
+
+uint8_t Adafruit_GFX::getRotation(void) const {
+ return rotation;
+}
+
+void Adafruit_GFX::setRotation(uint8_t x) {
+ rotation = (x & 3);
+ switch(rotation) {
+ case 0:
+ case 2:
+ _width = WIDTH;
+ _height = HEIGHT;
+ break;
+ case 1:
+ case 3:
+ _width = HEIGHT;
+ _height = WIDTH;
+ break;
+ }
+}
+
+
+void Adafruit_GFX::setFont(const GFXfont *f) {
+ if(f) { // Font struct pointer passed in?
+ if(!gfxFont) { // And no current font struct?
+ // Switching from classic to new font behavior.
+ // Move cursor pos down 6 pixels so it's on baseline.
+ cursor_y += 6;
+ }
+ } else if(gfxFont) { // NULL passed. Current font struct defined?
+ // Switching from new to classic font behavior.
+ // Move cursor pos up 6 pixels so it's at top-left of char.
+ cursor_y -= 6;
+ }
+ gfxFont = (GFXfont *)f;
+}
+
+// Pass string and a cursor position, returns UL corner and W,H.
+void Adafruit_GFX::getTextBounds(char *str, int16_t x, int16_t y,
+ int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h) {
+ uint8_t c; // Current character
+
+ *x1 = x;
+ *y1 = y;
+ *w = *h = 0;
+
+ if(gfxFont) {
+
+ GFXglyph *glyph;
+ uint8_t first = pgm_read_byte(&gfxFont->first),
+ last = pgm_read_byte(&gfxFont->last),
+ gw, gh, xa;
+ int8_t xo, yo;
+ int16_t minx = _width, miny = _height, maxx = -1, maxy = -1,
+ gx1, gy1, gx2, gy2, ts = (int16_t)textsize,
+ ya = ts * (uint8_t)pgm_read_byte(&gfxFont->yAdvance);
+
+ while((c = *str++)) {
+ if(c != '\n') { // Not a newline
+ if(c != '\r') { // Not a carriage return, is normal char
+ if((c >= first) && (c <= last)) { // Char present in current font
+ c -= first;
+ glyph = &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c]);
+ gw = pgm_read_byte(&glyph->width);
+ gh = pgm_read_byte(&glyph->height);
+ xa = pgm_read_byte(&glyph->xAdvance);
+ xo = pgm_read_byte(&glyph->xOffset);
+ yo = pgm_read_byte(&glyph->yOffset);
+ if(wrap && ((x + (((int16_t)xo + gw) * ts)) >= _width)) {
+ // Line wrap
+ x = 0; // Reset x to 0
+ y += ya; // Advance y by 1 line
+ }
+ gx1 = x + xo * ts;
+ gy1 = y + yo * ts;
+ gx2 = gx1 + gw * ts - 1;
+ gy2 = gy1 + gh * ts - 1;
+ if(gx1 < minx) minx = gx1;
+ if(gy1 < miny) miny = gy1;
+ if(gx2 > maxx) maxx = gx2;
+ if(gy2 > maxy) maxy = gy2;
+ x += xa * ts;
+ }
+ } // Carriage return = do nothing
+ } else { // Newline
+ x = 0; // Reset x
+ y += ya; // Advance y by 1 line
+ }
+ }
+ // End of string
+ *x1 = minx;
+ *y1 = miny;
+ if(maxx >= minx) *w = maxx - minx + 1;
+ if(maxy >= miny) *h = maxy - miny + 1;
+
+ } else { // Default font
+
+ uint16_t lineWidth = 0, maxWidth = 0; // Width of current, all lines
+
+ while((c = *str++)) {
+ if(c != '\n') { // Not a newline
+ if(c != '\r') { // Not a carriage return, is normal char
+ if(wrap && ((x + textsize * 6) >= _width)) {
+ x = 0; // Reset x to 0
+ y += textsize * 8; // Advance y by 1 line
+ if(lineWidth > maxWidth) maxWidth = lineWidth; // Save widest line
+ lineWidth = textsize * 6; // First char on new line
+ } else { // No line wrap, just keep incrementing X
+ lineWidth += textsize * 6; // Includes interchar x gap
+ }
+ } // Carriage return = do nothing
+ } else { // Newline
+ x = 0; // Reset x to 0
+ y += textsize * 8; // Advance y by 1 line
+ if(lineWidth > maxWidth) maxWidth = lineWidth; // Save widest line
+ lineWidth = 0; // Reset lineWidth for new line
+ }
+ }
+ // End of string
+ if(lineWidth) y += textsize * 8; // Add height of last (or only) line
+ if(lineWidth > maxWidth) maxWidth = lineWidth; // Is the last or only line the widest?
+ *w = maxWidth - 1; // Don't include last interchar x gap
+ *h = y - *y1;
+
+ } // End classic vs custom font
+}
+
+
+
+void Adafruit_GFX::print(const char* str) {
+ const char* p = str;
+ while (*p!=0)
+ write(*p++);
+}
+
+void Adafruit_GFX::println(const char* str) {
+ print(str);
+ write('\n');
+}
+
+// Return the size of the display (per current rotation)
+int16_t Adafruit_GFX::width(void) const {
+ return _width;
+}
+
+int16_t Adafruit_GFX::height(void) const {
+ return _height;
+}
+
+void Adafruit_GFX::invertDisplay(bool i) {
+ // Do nothing, must be subclassed if supported by hardware
+}
+
+
+/***************************************************************************/
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/oled/Adafruit_GFX.h Sun Jun 16 04:44:35 2019 +0000
@@ -0,0 +1,96 @@
+#ifndef _ADAFRUIT_GFX_H
+#define _ADAFRUIT_GFX_H
+
+#include <stdlib.h>
+
+#include "gfxfont.h"
+
+class Adafruit_GFX {
+
+ public:
+
+ Adafruit_GFX(int16_t w, int16_t h); // Constructor
+
+ // This MUST be defined by the subclass:
+ virtual void drawPixel(int16_t x, int16_t y, uint16_t color) = 0;
+
+ // These MAY be overridden by the subclass to provide device-specific
+ // optimized code. Otherwise 'generic' versions are used.
+ virtual void
+ drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color),
+ drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color),
+ drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color),
+ drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color),
+ fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color),
+ fillScreen(uint16_t color),
+ invertDisplay(bool i);
+
+ // These exist only with Adafruit_GFX (no subclass overrides)
+ void
+ drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color),
+ drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername,
+ uint16_t color),
+ fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color),
+ fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername,
+ int16_t delta, uint16_t color),
+ drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1,
+ int16_t x2, int16_t y2, uint16_t color),
+ fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1,
+ int16_t x2, int16_t y2, uint16_t color),
+ drawRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h,
+ int16_t radius, uint16_t color),
+ fillRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h,
+ int16_t radius, uint16_t color),
+
+ drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color),
+ drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg),
+
+ drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap,
+ int16_t w, int16_t h, uint16_t color),
+ drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color,
+ uint16_t bg, uint8_t size),
+ setCursor(int16_t x, int16_t y),
+ setTextColor(uint16_t c),
+ setTextColor(uint16_t c, uint16_t bg),
+ setTextSize(uint8_t s),
+ setTextWrap(bool w),
+ setRotation(uint8_t r),
+ cp437(bool x=true),
+ setFont(const GFXfont *f = NULL),
+ getTextBounds(char *string, int16_t x, int16_t y,
+ int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h),
+ getTextBounds(const char *s, int16_t x, int16_t y,
+ int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h),
+ print(const char* str),
+ println(const char* str);
+
+ virtual size_t write(uint8_t);
+
+ int16_t height(void) const;
+ int16_t width(void) const;
+
+ uint8_t getRotation(void) const;
+
+ // get current cursor position (get rotation safe maximum values, using: width() for x, height() for y)
+ int16_t getCursorX(void) const;
+ int16_t getCursorY(void) const;
+
+ protected:
+ const int16_t
+ WIDTH, HEIGHT; // This is the 'raw' display w/h - never changes
+ int16_t
+ _width, _height, // Display w/h as modified by current rotation
+ cursor_x, cursor_y;
+ uint16_t
+ textcolor, textbgcolor;
+ uint8_t
+ textsize,
+ rotation;
+ bool
+ wrap, // If set, 'wrap' text at right edge of display
+ _cp437; // If set, use correct CP437 charset (default is off)
+ GFXfont
+ *gfxFont;
+};
+
+#endif // _ADAFRUIT_GFX_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/oled/FreeSans9pt7b.h Sun Jun 16 04:44:35 2019 +0000
@@ -0,0 +1,201 @@
+const uint8_t FreeSans9pt7bBitmaps[] = {
+ 0xFF, 0xFF, 0xF8, 0xC0, 0xDE, 0xF7, 0x20, 0x09, 0x86, 0x41, 0x91, 0xFF,
+ 0x13, 0x04, 0xC3, 0x20, 0xC8, 0xFF, 0x89, 0x82, 0x61, 0x90, 0x10, 0x1F,
+ 0x14, 0xDA, 0x3D, 0x1E, 0x83, 0x40, 0x78, 0x17, 0x08, 0xF4, 0x7A, 0x35,
+ 0x33, 0xF0, 0x40, 0x20, 0x38, 0x10, 0xEC, 0x20, 0xC6, 0x20, 0xC6, 0x40,
+ 0xC6, 0x40, 0x6C, 0x80, 0x39, 0x00, 0x01, 0x3C, 0x02, 0x77, 0x02, 0x63,
+ 0x04, 0x63, 0x04, 0x77, 0x08, 0x3C, 0x0E, 0x06, 0x60, 0xCC, 0x19, 0x81,
+ 0xE0, 0x18, 0x0F, 0x03, 0x36, 0xC2, 0xD8, 0x73, 0x06, 0x31, 0xE3, 0xC4,
+ 0xFE, 0x13, 0x26, 0x6C, 0xCC, 0xCC, 0xC4, 0x66, 0x23, 0x10, 0x8C, 0x46,
+ 0x63, 0x33, 0x33, 0x32, 0x66, 0x4C, 0x80, 0x25, 0x7E, 0xA5, 0x00, 0x30,
+ 0xC3, 0x3F, 0x30, 0xC3, 0x0C, 0xD6, 0xF0, 0xC0, 0x08, 0x44, 0x21, 0x10,
+ 0x84, 0x42, 0x11, 0x08, 0x00, 0x3C, 0x66, 0x42, 0xC3, 0xC3, 0xC3, 0xC3,
+ 0xC3, 0xC3, 0xC3, 0x42, 0x66, 0x3C, 0x11, 0x3F, 0x33, 0x33, 0x33, 0x33,
+ 0x30, 0x3E, 0x31, 0xB0, 0x78, 0x30, 0x18, 0x1C, 0x1C, 0x1C, 0x18, 0x18,
+ 0x10, 0x08, 0x07, 0xF8, 0x3C, 0x66, 0xC3, 0xC3, 0x03, 0x06, 0x1C, 0x07,
+ 0x03, 0xC3, 0xC3, 0x66, 0x3C, 0x0C, 0x18, 0x71, 0x62, 0xC9, 0xA3, 0x46,
+ 0xFE, 0x18, 0x30, 0x60, 0xC0, 0x7F, 0x20, 0x10, 0x08, 0x08, 0x07, 0xF3,
+ 0x8C, 0x03, 0x01, 0x80, 0xF0, 0x6C, 0x63, 0xE0, 0x1E, 0x31, 0x98, 0x78,
+ 0x0C, 0x06, 0xF3, 0x8D, 0x83, 0xC1, 0xE0, 0xD0, 0x6C, 0x63, 0xE0, 0xFF,
+ 0x03, 0x02, 0x06, 0x04, 0x0C, 0x08, 0x18, 0x18, 0x18, 0x10, 0x30, 0x30,
+ 0x3E, 0x31, 0xB0, 0x78, 0x3C, 0x1B, 0x18, 0xF8, 0xC6, 0xC1, 0xE0, 0xF0,
+ 0x6C, 0x63, 0xE0, 0x3C, 0x66, 0xC2, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, 0x03,
+ 0x03, 0xC2, 0x66, 0x3C, 0xC0, 0x00, 0x30, 0xC0, 0x00, 0x00, 0x64, 0xA0,
+ 0x00, 0x81, 0xC7, 0x8E, 0x0C, 0x07, 0x80, 0x70, 0x0E, 0x01, 0x80, 0xFF,
+ 0x80, 0x00, 0x1F, 0xF0, 0x00, 0x70, 0x0E, 0x01, 0xC0, 0x18, 0x38, 0x71,
+ 0xC0, 0x80, 0x00, 0x3E, 0x31, 0xB0, 0x78, 0x30, 0x18, 0x18, 0x38, 0x18,
+ 0x18, 0x0C, 0x00, 0x00, 0x01, 0x80, 0x03, 0xF0, 0x06, 0x0E, 0x06, 0x01,
+ 0x86, 0x00, 0x66, 0x1D, 0xBB, 0x31, 0xCF, 0x18, 0xC7, 0x98, 0x63, 0xCC,
+ 0x31, 0xE6, 0x11, 0xB3, 0x99, 0xCC, 0xF7, 0x86, 0x00, 0x01, 0x80, 0x00,
+ 0x70, 0x40, 0x0F, 0xE0, 0x06, 0x00, 0xF0, 0x0F, 0x00, 0x90, 0x19, 0x81,
+ 0x98, 0x10, 0x83, 0x0C, 0x3F, 0xC2, 0x04, 0x60, 0x66, 0x06, 0xC0, 0x30,
+ 0xFF, 0x18, 0x33, 0x03, 0x60, 0x6C, 0x0D, 0x83, 0x3F, 0xC6, 0x06, 0xC0,
+ 0x78, 0x0F, 0x01, 0xE0, 0x6F, 0xF8, 0x1F, 0x86, 0x19, 0x81, 0xA0, 0x3C,
+ 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x68, 0x0D, 0x83, 0x18, 0x61, 0xF0,
+ 0xFF, 0x18, 0x33, 0x03, 0x60, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0,
+ 0x78, 0x0F, 0x03, 0x60, 0xCF, 0xF0, 0xFF, 0xE0, 0x30, 0x18, 0x0C, 0x06,
+ 0x03, 0xFD, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0F, 0xF8, 0xFF, 0xC0, 0xC0,
+ 0xC0, 0xC0, 0xC0, 0xFE, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x0F, 0x83,
+ 0x0E, 0x60, 0x66, 0x03, 0xC0, 0x0C, 0x00, 0xC1, 0xFC, 0x03, 0xC0, 0x36,
+ 0x03, 0x60, 0x73, 0x0F, 0x0F, 0x10, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C,
+ 0x07, 0x80, 0xFF, 0xFE, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x06,
+ 0xFF, 0xFF, 0xFF, 0xC0, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x07,
+ 0x8F, 0x1E, 0x27, 0x80, 0xC0, 0xD8, 0x33, 0x0C, 0x63, 0x0C, 0xC1, 0xB8,
+ 0x3F, 0x07, 0x30, 0xC3, 0x18, 0x63, 0x06, 0x60, 0x6C, 0x0C, 0xC0, 0xC0,
+ 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, 0xE0,
+ 0x3F, 0x01, 0xFC, 0x1F, 0xE0, 0xFD, 0x05, 0xEC, 0x6F, 0x63, 0x79, 0x13,
+ 0xCD, 0x9E, 0x6C, 0xF1, 0x47, 0x8E, 0x3C, 0x71, 0x80, 0xE0, 0x7C, 0x0F,
+ 0xC1, 0xE8, 0x3D, 0x87, 0x98, 0xF1, 0x1E, 0x33, 0xC3, 0x78, 0x6F, 0x07,
+ 0xE0, 0x7C, 0x0E, 0x0F, 0x81, 0x83, 0x18, 0x0C, 0xC0, 0x6C, 0x01, 0xE0,
+ 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1B, 0x01, 0x98, 0x0C, 0x60, 0xC0, 0xF8,
+ 0x00, 0xFF, 0x30, 0x6C, 0x0F, 0x03, 0xC0, 0xF0, 0x6F, 0xF3, 0x00, 0xC0,
+ 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x00, 0x0F, 0x81, 0x83, 0x18, 0x0C, 0xC0,
+ 0x6C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1B, 0x01, 0x98, 0x6C,
+ 0x60, 0xC0, 0xFB, 0x00, 0x08, 0xFF, 0x8C, 0x0E, 0xC0, 0x6C, 0x06, 0xC0,
+ 0x6C, 0x0C, 0xFF, 0x8C, 0x0E, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0,
+ 0x70, 0x3F, 0x18, 0x6C, 0x0F, 0x03, 0xC0, 0x1E, 0x01, 0xF0, 0x0E, 0x00,
+ 0xF0, 0x3C, 0x0D, 0x86, 0x3F, 0x00, 0xFF, 0x86, 0x03, 0x01, 0x80, 0xC0,
+ 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, 0xC0, 0x78, 0x0F,
+ 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01,
+ 0xB0, 0x61, 0xF0, 0xC0, 0x6C, 0x0D, 0x81, 0x10, 0x63, 0x0C, 0x61, 0x04,
+ 0x60, 0xCC, 0x19, 0x01, 0x60, 0x3C, 0x07, 0x00, 0x60, 0xC1, 0x81, 0x30,
+ 0xE1, 0x98, 0x70, 0xCC, 0x28, 0x66, 0x26, 0x21, 0x13, 0x30, 0xC8, 0x98,
+ 0x6C, 0x4C, 0x14, 0x34, 0x0A, 0x1A, 0x07, 0x07, 0x03, 0x03, 0x80, 0x81,
+ 0x80, 0x60, 0x63, 0x0C, 0x30, 0xC1, 0x98, 0x0F, 0x00, 0xE0, 0x06, 0x00,
+ 0xF0, 0x19, 0x01, 0x98, 0x30, 0xC6, 0x0E, 0x60, 0x60, 0xC0, 0x36, 0x06,
+ 0x30, 0xC3, 0x0C, 0x19, 0x81, 0xD8, 0x0F, 0x00, 0x60, 0x06, 0x00, 0x60,
+ 0x06, 0x00, 0x60, 0x06, 0x00, 0xFF, 0xC0, 0x60, 0x30, 0x0C, 0x06, 0x03,
+ 0x01, 0xC0, 0x60, 0x30, 0x18, 0x06, 0x03, 0x00, 0xFF, 0xC0, 0xFB, 0x6D,
+ 0xB6, 0xDB, 0x6D, 0xB6, 0xE0, 0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 0x84,
+ 0x10, 0x80, 0xED, 0xB6, 0xDB, 0x6D, 0xB6, 0xDB, 0xE0, 0x30, 0x60, 0xA2,
+ 0x44, 0xD8, 0xA1, 0x80, 0xFF, 0xC0, 0xC6, 0x30, 0x7E, 0x71, 0xB0, 0xC0,
+ 0x60, 0xF3, 0xDB, 0x0D, 0x86, 0xC7, 0x3D, 0xC0, 0xC0, 0x60, 0x30, 0x1B,
+ 0xCE, 0x36, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x7C, 0x6D, 0xE0, 0x3C,
+ 0x66, 0xC3, 0xC0, 0xC0, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, 0x03, 0x03, 0x03,
+ 0x3B, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, 0x3C, 0x66,
+ 0xC3, 0xC3, 0xFF, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, 0x36, 0x6F, 0x66, 0x66,
+ 0x66, 0x66, 0x60, 0x3B, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x67,
+ 0x3B, 0x03, 0x03, 0xC6, 0x7C, 0xC0, 0xC0, 0xC0, 0xDE, 0xE3, 0xC3, 0xC3,
+ 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xFF, 0xFF, 0xC0, 0x30, 0x03,
+ 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xE0, 0xC0, 0x60, 0x30, 0x18, 0x4C,
+ 0x46, 0x63, 0x61, 0xF0, 0xEC, 0x62, 0x31, 0x98, 0x6C, 0x30, 0xFF, 0xFF,
+ 0xFF, 0xC0, 0xDE, 0xF7, 0x1C, 0xF0, 0xC7, 0x86, 0x3C, 0x31, 0xE1, 0x8F,
+ 0x0C, 0x78, 0x63, 0xC3, 0x1E, 0x18, 0xC0, 0xDE, 0xE3, 0xC3, 0xC3, 0xC3,
+ 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
+ 0xC3, 0x66, 0x3C, 0xDE, 0x71, 0xB0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83,
+ 0xE3, 0x6F, 0x30, 0x18, 0x0C, 0x00, 0x3B, 0x67, 0xC3, 0xC3, 0xC3, 0xC3,
+ 0xC3, 0xC3, 0x67, 0x3B, 0x03, 0x03, 0x03, 0xDF, 0x31, 0x8C, 0x63, 0x18,
+ 0xC6, 0x00, 0x3E, 0xE3, 0xC0, 0xC0, 0xE0, 0x3C, 0x07, 0xC3, 0xE3, 0x7E,
+ 0x66, 0xF6, 0x66, 0x66, 0x66, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
+ 0xC3, 0xC3, 0xC7, 0x7B, 0xC1, 0xA0, 0x98, 0xCC, 0x42, 0x21, 0xB0, 0xD0,
+ 0x28, 0x1C, 0x0C, 0x00, 0xC6, 0x1E, 0x38, 0x91, 0xC4, 0xCA, 0x66, 0xD3,
+ 0x16, 0xD0, 0xA6, 0x87, 0x1C, 0x38, 0xC0, 0xC6, 0x00, 0x43, 0x62, 0x36,
+ 0x1C, 0x18, 0x1C, 0x3C, 0x26, 0x62, 0x43, 0xC1, 0x21, 0x98, 0xCC, 0x42,
+ 0x61, 0xB0, 0xD0, 0x38, 0x1C, 0x0C, 0x06, 0x03, 0x01, 0x03, 0x00, 0xFE,
+ 0x0C, 0x30, 0xC1, 0x86, 0x18, 0x20, 0xC1, 0xFC, 0x36, 0x66, 0x66, 0x6E,
+ 0xCE, 0x66, 0x66, 0x66, 0x30, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xC6, 0x66,
+ 0x66, 0x67, 0x37, 0x66, 0x66, 0x66, 0xC0, 0x61, 0x24, 0x38 };
+
+const GFXglyph FreeSans9pt7bGlyphs[] = {
+ { 0, 0, 0, 5, 0, 1 }, // 0x20 ' '
+ { 0, 2, 13, 6, 2, -12 }, // 0x21 '!'
+ { 4, 5, 4, 6, 1, -12 }, // 0x22 '"'
+ { 7, 10, 12, 10, 0, -11 }, // 0x23 '#'
+ { 22, 9, 16, 10, 1, -13 }, // 0x24 '$'
+ { 40, 16, 13, 16, 1, -12 }, // 0x25 '%'
+ { 66, 11, 13, 12, 1, -12 }, // 0x26 '&'
+ { 84, 2, 4, 4, 1, -12 }, // 0x27 '''
+ { 85, 4, 17, 6, 1, -12 }, // 0x28 '('
+ { 94, 4, 17, 6, 1, -12 }, // 0x29 ')'
+ { 103, 5, 5, 7, 1, -12 }, // 0x2A '*'
+ { 107, 6, 8, 11, 3, -7 }, // 0x2B '+'
+ { 113, 2, 4, 5, 2, 0 }, // 0x2C ','
+ { 114, 4, 1, 6, 1, -4 }, // 0x2D '-'
+ { 115, 2, 1, 5, 1, 0 }, // 0x2E '.'
+ { 116, 5, 13, 5, 0, -12 }, // 0x2F '/'
+ { 125, 8, 13, 10, 1, -12 }, // 0x30 '0'
+ { 138, 4, 13, 10, 3, -12 }, // 0x31 '1'
+ { 145, 9, 13, 10, 1, -12 }, // 0x32 '2'
+ { 160, 8, 13, 10, 1, -12 }, // 0x33 '3'
+ { 173, 7, 13, 10, 2, -12 }, // 0x34 '4'
+ { 185, 9, 13, 10, 1, -12 }, // 0x35 '5'
+ { 200, 9, 13, 10, 1, -12 }, // 0x36 '6'
+ { 215, 8, 13, 10, 0, -12 }, // 0x37 '7'
+ { 228, 9, 13, 10, 1, -12 }, // 0x38 '8'
+ { 243, 8, 13, 10, 1, -12 }, // 0x39 '9'
+ { 256, 2, 10, 5, 1, -9 }, // 0x3A ':'
+ { 259, 3, 12, 5, 1, -8 }, // 0x3B ';'
+ { 264, 9, 9, 11, 1, -8 }, // 0x3C '<'
+ { 275, 9, 4, 11, 1, -5 }, // 0x3D '='
+ { 280, 9, 9, 11, 1, -8 }, // 0x3E '>'
+ { 291, 9, 13, 10, 1, -12 }, // 0x3F '?'
+ { 306, 17, 16, 18, 1, -12 }, // 0x40 '@'
+ { 340, 12, 13, 12, 0, -12 }, // 0x41 'A'
+ { 360, 11, 13, 12, 1, -12 }, // 0x42 'B'
+ { 378, 11, 13, 13, 1, -12 }, // 0x43 'C'
+ { 396, 11, 13, 13, 1, -12 }, // 0x44 'D'
+ { 414, 9, 13, 11, 1, -12 }, // 0x45 'E'
+ { 429, 8, 13, 11, 1, -12 }, // 0x46 'F'
+ { 442, 12, 13, 14, 1, -12 }, // 0x47 'G'
+ { 462, 11, 13, 13, 1, -12 }, // 0x48 'H'
+ { 480, 2, 13, 5, 2, -12 }, // 0x49 'I'
+ { 484, 7, 13, 10, 1, -12 }, // 0x4A 'J'
+ { 496, 11, 13, 12, 1, -12 }, // 0x4B 'K'
+ { 514, 8, 13, 10, 1, -12 }, // 0x4C 'L'
+ { 527, 13, 13, 15, 1, -12 }, // 0x4D 'M'
+ { 549, 11, 13, 13, 1, -12 }, // 0x4E 'N'
+ { 567, 13, 13, 14, 1, -12 }, // 0x4F 'O'
+ { 589, 10, 13, 12, 1, -12 }, // 0x50 'P'
+ { 606, 13, 14, 14, 1, -12 }, // 0x51 'Q'
+ { 629, 12, 13, 13, 1, -12 }, // 0x52 'R'
+ { 649, 10, 13, 12, 1, -12 }, // 0x53 'S'
+ { 666, 9, 13, 11, 1, -12 }, // 0x54 'T'
+ { 681, 11, 13, 13, 1, -12 }, // 0x55 'U'
+ { 699, 11, 13, 12, 0, -12 }, // 0x56 'V'
+ { 717, 17, 13, 17, 0, -12 }, // 0x57 'W'
+ { 745, 12, 13, 12, 0, -12 }, // 0x58 'X'
+ { 765, 12, 13, 12, 0, -12 }, // 0x59 'Y'
+ { 785, 10, 13, 11, 1, -12 }, // 0x5A 'Z'
+ { 802, 3, 17, 5, 1, -12 }, // 0x5B '['
+ { 809, 5, 13, 5, 0, -12 }, // 0x5C '\'
+ { 818, 3, 17, 5, 0, -12 }, // 0x5D ']'
+ { 825, 7, 7, 8, 1, -12 }, // 0x5E '^'
+ { 832, 10, 1, 10, 0, 3 }, // 0x5F '_'
+ { 834, 4, 3, 5, 0, -12 }, // 0x60 '`'
+ { 836, 9, 10, 10, 1, -9 }, // 0x61 'a'
+ { 848, 9, 13, 10, 1, -12 }, // 0x62 'b'
+ { 863, 8, 10, 9, 1, -9 }, // 0x63 'c'
+ { 873, 8, 13, 10, 1, -12 }, // 0x64 'd'
+ { 886, 8, 10, 10, 1, -9 }, // 0x65 'e'
+ { 896, 4, 13, 5, 1, -12 }, // 0x66 'f'
+ { 903, 8, 14, 10, 1, -9 }, // 0x67 'g'
+ { 917, 8, 13, 10, 1, -12 }, // 0x68 'h'
+ { 930, 2, 13, 4, 1, -12 }, // 0x69 'i'
+ { 934, 4, 17, 4, 0, -12 }, // 0x6A 'j'
+ { 943, 9, 13, 9, 1, -12 }, // 0x6B 'k'
+ { 958, 2, 13, 4, 1, -12 }, // 0x6C 'l'
+ { 962, 13, 10, 15, 1, -9 }, // 0x6D 'm'
+ { 979, 8, 10, 10, 1, -9 }, // 0x6E 'n'
+ { 989, 8, 10, 10, 1, -9 }, // 0x6F 'o'
+ { 999, 9, 13, 10, 1, -9 }, // 0x70 'p'
+ { 1014, 8, 13, 10, 1, -9 }, // 0x71 'q'
+ { 1027, 5, 10, 6, 1, -9 }, // 0x72 'r'
+ { 1034, 8, 10, 9, 1, -9 }, // 0x73 's'
+ { 1044, 4, 12, 5, 1, -11 }, // 0x74 't'
+ { 1050, 8, 10, 10, 1, -9 }, // 0x75 'u'
+ { 1060, 9, 10, 9, 0, -9 }, // 0x76 'v'
+ { 1072, 13, 10, 13, 0, -9 }, // 0x77 'w'
+ { 1089, 8, 10, 9, 0, -9 }, // 0x78 'x'
+ { 1099, 9, 14, 9, 0, -9 }, // 0x79 'y'
+ { 1115, 7, 10, 9, 1, -9 }, // 0x7A 'z'
+ { 1124, 4, 17, 6, 1, -12 }, // 0x7B '{'
+ { 1133, 2, 17, 4, 2, -12 }, // 0x7C '|'
+ { 1138, 4, 17, 6, 1, -12 }, // 0x7D '}'
+ { 1147, 7, 3, 9, 1, -7 } }; // 0x7E '~'
+
+const GFXfont FreeSans9pt7b = {
+ (uint8_t *)FreeSans9pt7bBitmaps,
+ (GFXglyph *)FreeSans9pt7bGlyphs,
+ 0x20, 0x7E, 22 };
+
+// Approx. 1822 bytes
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/oled/SSD1306-Library.cpp Sun Jun 16 04:44:35 2019 +0000
@@ -0,0 +1,525 @@
+/*
+ * SSD1306-Library.cpp
+ *
+ * Created on: 19 Apr 2017
+ * Author: ebj
+ *
+ * I2C version
+ * CS GND
+ * DC GND for i2c addr 0x3C, VCC for addr 0x3D
+ * RES Vcc
+ */
+
+#include "mbed.h"
+
+#include "SSD1306-Library.h"
+
+extern Serial pc;
+
+extern "C" {
+}
+
+#define NUM_ELEMENTS(x) ((sizeof x)/(sizeof x[0]))
+
+
+I2C i2c(I2C_SDA, I2C_SCL);
+DigitalOut rst(D9); //D13); //reset pin on D13
+
+
+// the memory buffer for the LCD
+static uint8_t buffer[SSD1306_LCDHEIGHT * SSD1306_LCDWIDTH / 8];
+
+volatile uint8_t dma_pause = 0;
+
+SSD1306::SSD1306(int16_t w, int16_t h) : Adafruit_GFX(w, h) {
+}
+
+#define ssd1306_swap(a, b) { int16_t t = a; a = b; b = t; }
+
+void SSD1306::hw_setup() {
+ i2c.frequency(400000);
+}
+
+
+// the most basic function, set a single pixel
+void SSD1306::drawPixel(int16_t x, int16_t y, uint16_t color) {
+ if ((x < 0) || (x >= width()) || (y < 0) || (y >= height()))
+ return;
+
+ // check rotation, move pixel around if necessary
+ switch (rotation) {
+ case 1:
+ ssd1306_swap(x, y);
+ x = WIDTH - x - 1;
+ break;
+ case 2:
+ x = WIDTH - x - 1;
+ y = HEIGHT - y - 1;
+ break;
+ case 3:
+ ssd1306_swap(x, y);
+ y = HEIGHT - y - 1;
+ break;
+ }
+
+ // x is which column
+ uint8_t *p = &buffer[x + (y/8)*SSD1306_LCDWIDTH];
+ uint8_t v = 1 << (y & 7);
+
+ switch (color) {
+ case WHITE:
+ *p |= v;
+ break;
+ case BLACK:
+ *p &= ~v;
+ break;
+ case INVERSE:
+ *p ^= v;
+ break;
+ }
+
+}
+
+void SSD1306::_sendData(const uint8_t *blk, uint32_t len, bool isData) {
+ const uint8_t *p = blk;
+
+ //pc.printf("SendData...\r\n");
+ // now send the data
+ uint8_t control = 0x00 | (isData ? 0x40 : 0x00);
+
+
+ if (isData) {
+ i2c.start();
+ //pc.printf("%0.2x ", *p);
+ i2c.write(0x3C<<1);
+
+ //control |= 0x80;
+ i2c.write(control);
+
+ for (int32_t i=0; i<len; i++, p++) {
+ //pc.printf("%0.2x ", *p);
+ int error = i2c.write(*p);
+ //int error = 1;
+ //wait(0.1);
+ if (error != 1)
+ pc.printf("I2C error: %0.2d\r\n", error);
+ }
+ i2c.stop();
+
+ } else {
+ for (int32_t i=0; i<len; i++, p++) {
+ i2c.start();
+ //pc.printf("%0.2x ", *p);
+ i2c.write(0x3C<<1);
+ i2c.write(control);
+ int error = i2c.write(*p);
+ //int error = 1;
+ //wait(0.1);
+ i2c.stop();
+ if (error != 1)
+ pc.printf("I2C error: %0.2d\r\n", error);
+ }
+ }
+}
+
+void SSD1306::sendCommands(const uint8_t *blk, uint32_t len) {
+ _sendData(blk, len, false);
+}
+
+void SSD1306::sendData(const uint8_t *blk, uint32_t len) {
+ _sendData(blk, len, true);
+}
+
+void SSD1306::begin(bool reset) {
+ if (reset) { //pulse the reset pin -- maybe replace with RC network
+ rst = 1;
+ wait_ms(1);
+ rst = 0;
+ wait_ms(10);
+ rst = 1;
+ }
+
+ const uint8_t cmds[] = {
+ SSD1306_DISPLAYOFF,
+ SSD1306_SETDISPLAYCLOCKDIV,
+ 0x80, // the suggested ratio 0x80
+ SSD1306_SETMULTIPLEX,
+ SSD1306_LCDHEIGHT - 1,
+ SSD1306_SETDISPLAYOFFSET,
+ 0x0, // no offset
+ SSD1306_SETSTARTLINE | 0x0, // line #0
+ SSD1306_CHARGEPUMP,
+ 0x14,
+ SSD1306_MEMORYMODE,
+ 0x00, // 0x0 act like ks0108
+ SSD1306_SEGREMAP | 0x1,
+ SSD1306_COMSCANDEC,
+ SSD1306_SETCOMPINS,
+ 0x12,
+ SSD1306_SETCONTRAST,
+ 0xCF,
+ SSD1306_SETPRECHARGE,
+ 0xF1,
+ SSD1306_SETVCOMDETECT,
+ 0x40,
+ SSD1306_DISPLAYALLON_RESUME,
+ SSD1306_NORMALDISPLAY,
+ SSD1306_DEACTIVATE_SCROLL,
+ SSD1306_DISPLAYON //--turn on oled panel
+ };
+
+ sendCommands(cmds, NUM_ELEMENTS(cmds));
+
+}
+
+
+void SSD1306::display(void) {
+ const uint8_t cmds[] = {
+ SSD1306_COLUMNADDR,
+ 0, // Column start address (0 = reset)
+ SSD1306_LCDWIDTH - 1, // Column end address (127 = reset)
+ SSD1306_PAGEADDR,
+ 0, // Page start address (0 = reset)
+ 7 // Page end address
+ };
+
+ sendCommands(cmds, NUM_ELEMENTS(cmds));
+ //now send the screen image
+ sendData(buffer, NUM_ELEMENTS(buffer));
+}
+
+void SSD1306::invertDisplay(uint8_t i) {
+ const uint8_t normalCmd[] = { SSD1306_NORMALDISPLAY };
+ const uint8_t invertCmd[] = { SSD1306_INVERTDISPLAY };
+ sendCommands( i ? invertCmd : normalCmd, 1);
+}
+
+
+void SSD1306::_scroll(uint8_t mode, uint8_t start, uint8_t stop) {
+ uint8_t cmds[] = { mode, 0, start, 0, stop, 0, 0xFF, SSD1306_ACTIVATE_SCROLL };
+ sendCommands(cmds, NUM_ELEMENTS(cmds));
+}
+// startscrollright
+// Activate a right handed scroll for rows start through stop
+// Hint, the display is 16 rows tall. To scroll the whole display, run:
+// display.scrollright(0x00, 0x0F)
+void SSD1306::startscrollright(uint8_t start, uint8_t stop) {
+ _scroll(SSD1306_RIGHT_HORIZONTAL_SCROLL, start, stop);
+}
+
+// startscrollleft
+// Activate a right handed scroll for rows start through stop
+// Hint, the display is 16 rows tall. To scroll the whole display, run:
+// display.scrollright(0x00, 0x0F)
+void SSD1306::startscrollleft(uint8_t start, uint8_t stop) {
+ _scroll(SSD1306_LEFT_HORIZONTAL_SCROLL, start, stop);
+}
+
+// startscrolldiagright
+// Activate a diagonal scroll for rows start through stop
+// Hint, the display is 16 rows tall. To scroll the whole display, run:
+// display.scrollright(0x00, 0x0F)
+void SSD1306::startscrolldiagright(uint8_t start, uint8_t stop) {
+ uint8_t cmds[] = {
+ SSD1306_SET_VERTICAL_SCROLL_AREA,
+ 0X00,
+ SSD1306_LCDHEIGHT,
+ SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL,
+ 0X00,
+ start,
+ 0X00,
+ stop,
+ 0X01,
+ SSD1306_ACTIVATE_SCROLL
+ };
+
+ sendCommands(cmds, NUM_ELEMENTS(cmds));
+}
+
+// startscrolldiagleft
+// Activate a diagonal scroll for rows start through stop
+// Hint, the display is 16 rows tall. To scroll the whole display, run:
+// display.scrollright(0x00, 0x0F)
+void SSD1306::startscrolldiagleft(uint8_t start, uint8_t stop) {
+ uint8_t cmds[] = {
+ SSD1306_SET_VERTICAL_SCROLL_AREA,
+ 0X00,
+ SSD1306_LCDHEIGHT,
+ SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL,
+ 0X00,
+ start,
+ 0X00,
+ stop,
+ 0X01,
+ SSD1306_ACTIVATE_SCROLL
+ };
+
+ sendCommands(cmds, NUM_ELEMENTS(cmds));
+}
+
+
+void SSD1306::stopscroll(void) {
+ const uint8_t cmds[] = { SSD1306_DEACTIVATE_SCROLL };
+ sendCommands(cmds, NUM_ELEMENTS(cmds));
+}
+
+// Dim the display
+// dim = true: display is dimmed
+// dim = false: display is normal
+void SSD1306::dim(bool dim) {
+ // the range of contrast to too small to be really useful
+ // it is useful to dim the display
+ uint8_t cmds[] = {SSD1306_SETCONTRAST, dim ? 0 : 0xCF};
+ sendCommands(cmds, NUM_ELEMENTS(cmds));
+}
+
+// clear everything
+void SSD1306::clearDisplay(void) {
+ memset(buffer, 0, (SSD1306_LCDWIDTH * SSD1306_LCDHEIGHT / 8));
+}
+
+#if 1
+void SSD1306::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) {
+ bool bSwap = false;
+ switch (rotation) {
+ case 0:
+ // 0 degree rotation, do nothing
+ break;
+ case 1:
+ // 90 degree rotation, swap x & y for rotation, then invert x
+ bSwap = true;
+ ssd1306_swap(x, y);
+ x = WIDTH - x - 1;
+ break;
+ case 2:
+ // 180 degree rotation, invert x and y - then shift y around for height.
+ x = WIDTH - x - 1;
+ y = HEIGHT - y - 1;
+ x -= (w - 1);
+ break;
+ case 3:
+ // 270 degree rotation, swap x & y for rotation, then invert y and adjust y for w (not to become h)
+ bSwap = true;
+ ssd1306_swap(x, y);
+ y = HEIGHT - y - 1;
+ y -= (w - 1);
+ break;
+ }
+
+ if (bSwap) {
+ drawFastVLineInternal(x, y, w, color);
+ } else {
+ drawFastHLineInternal(x, y, w, color);
+ }
+}
+#endif
+
+
+void SSD1306::drawFastHLineInternal(int16_t x, int16_t y, int16_t w,
+ uint16_t color) {
+ // Do bounds/limit checks
+ if (y < 0 || y >= HEIGHT) {
+ return;
+ }
+
+ // make sure we don't try to draw below 0
+ if (x < 0) {
+ w += x;
+ x = 0;
+ }
+
+ // make sure we don't go off the edge of the display
+ if ((x + w) > WIDTH) {
+ w = (WIDTH - x);
+ }
+
+ // if our width is now negative, punt
+ if (w <= 0) {
+ return;
+ }
+
+ // set up the pointer for movement through the buffer
+ register uint8_t *pBuf = buffer;
+ // adjust the buffer pointer for the current row
+ pBuf += ((y / 8) * SSD1306_LCDWIDTH);
+ // and offset x columns in
+ pBuf += x;
+
+ register uint8_t mask = 1 << (y & 7);
+
+ switch (color) {
+ case WHITE:
+ while (w--)
+ *pBuf++ |= mask;
+ break;
+ case BLACK:
+ mask = ~mask;
+ while (w--)
+ *pBuf++ &= mask;
+ break;
+ case INVERSE:
+ while (w--)
+ *pBuf++ ^= mask;
+ break;
+ }
+}
+
+void SSD1306::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) {
+ bool bSwap = false;
+ switch (rotation) {
+ case 0:
+ break;
+ case 1:
+ // 90 degree rotation, swap x & y for rotation, then invert x and adjust x for h (now to become w)
+ bSwap = true;
+ ssd1306_swap(x, y)
+ x = WIDTH - x - 1;
+ x -= (h - 1);
+ break;
+ case 2:
+ // 180 degree rotation, invert x and y - then shift y around for height.
+ x = WIDTH - x - 1;
+ y = HEIGHT - y - 1;
+ y -= (h - 1);
+ break;
+ case 3:
+ // 270 degree rotation, swap x & y for rotation, then invert y
+ bSwap = true;
+ ssd1306_swap(x, y)
+ y = HEIGHT - y - 1;
+ break;
+ }
+
+ if (bSwap) {
+ drawFastHLineInternal(x, y, h, color);
+ } else {
+ drawFastVLineInternal(x, y, h, color);
+ }
+}
+
+void SSD1306::drawFastVLineInternal(int16_t x, int16_t __y, int16_t __h, uint16_t color) {
+
+ // do nothing if we're off the left or right side of the screen
+ if (x < 0 || x >= WIDTH) {
+ return;
+ }
+
+ // make sure we don't try to draw below 0
+ if (__y < 0) {
+ // __y is negative, this will subtract enough from __h to account for __y being 0
+ __h += __y;
+ __y = 0;
+
+ }
+
+ // make sure we don't go past the height of the display
+ if ((__y + __h) > HEIGHT) {
+ __h = (HEIGHT - __y);
+ }
+
+ // if our height is now negative, punt
+ if (__h <= 0) {
+ return;
+ }
+
+ // this display doesn't need ints for coordinates, use local byte registers for faster juggling
+ register uint8_t y = __y;
+ register uint8_t h = __h;
+
+ // set up the pointer for fast movement through the buffer
+ register uint8_t *pBuf = buffer;
+ // adjust the buffer pointer for the current row
+ pBuf += ((y / 8) * SSD1306_LCDWIDTH);
+ // and offset x columns in
+ pBuf += x;
+
+ // do the first partial byte, if necessary - this requires some masking
+ register uint8_t mod = (y & 7);
+ if (mod) {
+ // mask off the high n bits we want to set
+ mod = 8 - mod;
+
+ // note - lookup table results in a nearly 10% performance improvement in fill* functions
+ // register uint8_t mask = ~(0xFF >> (mod));
+ static uint8_t premask[8] = { 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC,
+ 0xFE };
+ register uint8_t mask = premask[mod];
+
+ // adjust the mask if we're not going to reach the end of this byte
+ if (h < mod) {
+ mask &= (0XFF >> (mod - h));
+ }
+
+ switch (color) {
+ case WHITE:
+ *pBuf |= mask;
+ break;
+ case BLACK:
+ *pBuf &= ~mask;
+ break;
+ case INVERSE:
+ *pBuf ^= mask;
+ break;
+ }
+
+ // fast exit if we're done here!
+ if (h < mod) {
+ return;
+ }
+
+ h -= mod;
+
+ pBuf += SSD1306_LCDWIDTH;
+ }
+
+ // write solid bytes while we can - effectively doing 8 rows at a time
+ if (h >= 8) {
+ if (color == INVERSE) { // separate copy of the code so we don't impact performance of the black/white write version with an extra comparison per loop
+ do {
+ *pBuf = ~(*pBuf);
+
+ // adjust the buffer forward 8 rows worth of data
+ pBuf += SSD1306_LCDWIDTH;
+
+ // adjust h & y (there's got to be a faster way for me to do this, but this should still help a fair bit for now)
+ h -= 8;
+ } while (h >= 8);
+ } else {
+ // store a local value to work with
+ register uint8_t val = (color == WHITE) ? 255 : 0;
+
+ do {
+ // write our value in
+ *pBuf = val;
+
+ // adjust the buffer forward 8 rows worth of data
+ pBuf += SSD1306_LCDWIDTH;
+
+ // adjust h & y (there's got to be a faster way for me to do this, but this should still help a fair bit for now)
+ h -= 8;
+ } while (h >= 8);
+ }
+ }
+
+ // now do the final partial byte, if necessary
+ if (h) {
+ mod = h & 7;
+ // this time we want to mask the low bits of the byte, vs the high bits we did above
+ // register uint8_t mask = (1 << mod) - 1;
+ // note - lookup table results in a nearly 10% performance improvement in fill* functions
+ static uint8_t postmask[8] = { 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F,
+ 0x7F };
+ register uint8_t mask = postmask[mod];
+ switch (color) {
+ case WHITE:
+ *pBuf |= mask;
+ break;
+ case BLACK:
+ *pBuf &= ~mask;
+ break;
+ case INVERSE:
+ *pBuf ^= mask;
+ break;
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/oled/SSD1306-Library.h Sun Jun 16 04:44:35 2019 +0000
@@ -0,0 +1,112 @@
+/*
+ * SSD1306-Libary.h
+ *
+ * Created on: Jan 1, 2017
+ * Author: johnsone
+ */
+
+#ifndef SOURCE_SSD1306_LIBARY_H_
+#define SOURCE_SSD1306_LIBARY_H_
+
+#include "Adafruit_GFX.h"
+
+#include <stdint.h>
+
+#define SSD1306_LCDWIDTH 128
+#define SSD1306_LCDHEIGHT 64
+
+#define BLACK 0
+#define WHITE 1
+#define INVERSE 2
+
+#define SSD1306_SETCONTRAST 0x81
+#define SSD1306_DISPLAYALLON_RESUME 0xA4
+#define SSD1306_DISPLAYALLON 0xA5
+#define SSD1306_NORMALDISPLAY 0xA6
+#define SSD1306_INVERTDISPLAY 0xA7
+#define SSD1306_DISPLAYOFF 0xAE
+#define SSD1306_DISPLAYON 0xAF
+
+#define SSD1306_SETDISPLAYOFFSET 0xD3
+#define SSD1306_SETCOMPINS 0xDA
+
+#define SSD1306_SETVCOMDETECT 0xDB
+
+#define SSD1306_SETDISPLAYCLOCKDIV 0xD5
+#define SSD1306_SETPRECHARGE 0xD9
+
+#define SSD1306_SETMULTIPLEX 0xA8
+
+#define SSD1306_SETLOWCOLUMN 0x00
+#define SSD1306_SETHIGHCOLUMN 0x10
+
+#define SSD1306_SETSTARTLINE 0x40
+
+#define SSD1306_MEMORYMODE 0x20
+#define SSD1306_COLUMNADDR 0x21
+#define SSD1306_PAGEADDR 0x22
+
+#define SSD1306_COMSCANINC 0xC0
+#define SSD1306_COMSCANDEC 0xC8
+
+#define SSD1306_SEGREMAP 0xA0
+
+#define SSD1306_CHARGEPUMP 0x8D
+
+// Scrolling #defines
+#define SSD1306_ACTIVATE_SCROLL 0x2F
+#define SSD1306_DEACTIVATE_SCROLL 0x2E
+#define SSD1306_SET_VERTICAL_SCROLL_AREA 0xA3
+#define SSD1306_RIGHT_HORIZONTAL_SCROLL 0x26
+#define SSD1306_LEFT_HORIZONTAL_SCROLL 0x27
+#define SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL 0x29
+#define SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL 0x2A
+
+
+class SSD1306 : public Adafruit_GFX {
+ public:
+ SSD1306(int16_t w=SSD1306_LCDWIDTH, int16_t h=SSD1306_LCDHEIGHT);
+
+ void drawPixel(int16_t x, int16_t y, uint16_t color);
+
+ void hw_setup();
+
+ void begin(bool reset=true);
+ void display(void);
+
+ void clearDisplay(void);
+ void invertDisplay(uint8_t i);
+ void startscrollleft(uint8_t start, uint8_t stop);
+ void startscrollright(uint8_t start, uint8_t stop);
+ void startscrolldiagright(uint8_t start, uint8_t stop);
+ void startscrolldiagleft(uint8_t start, uint8_t stop);
+ void stopscroll(void);
+ void dim(bool dim);
+ void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
+ void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
+
+
+ protected:
+ int16_t
+ _width, _height; // Display w/h as modified by current rotation
+
+ uint8_t
+ textsize,
+ rotation;
+
+ private:
+ void _sendData(const uint8_t *blk, uint32_t len, bool isData);
+ void sendCommands(const uint8_t *blk, uint32_t len);
+ void sendData(const uint8_t *blk, uint32_t len);
+
+ //void ssd1306_command(uint8_t c);
+
+ void drawFastHLineInternal(int16_t x, int16_t y, int16_t w, uint16_t color);
+ void drawFastVLineInternal(int16_t x, int16_t __y, int16_t __h, uint16_t color);
+
+ void _scroll(uint8_t mode, uint8_t start, uint8_t stop);
+};
+
+
+
+#endif /* SOURCE_SSD1306_LIBARY_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/oled/gfxfont.h Sun Jun 16 04:44:35 2019 +0000
@@ -0,0 +1,26 @@
+// Font structures for newer Adafruit_GFX (1.1 and later).
+// Example fonts are included in 'Fonts' directory.
+// To use a font in your Arduino sketch, #include the corresponding .h
+// file and pass address of GFXfont struct to setFont(). Pass NULL to
+// revert to 'classic' fixed-space bitmap font.
+
+#ifndef _GFXFONT_H_
+#define _GFXFONT_H_
+
+#include <stdint.h>
+
+typedef struct { // Data stored PER GLYPH
+ uint16_t bitmapOffset; // Pointer into GFXfont->bitmap
+ uint8_t width, height; // Bitmap dimensions in pixels
+ uint8_t xAdvance; // Distance to advance cursor (x axis)
+ int8_t xOffset, yOffset; // Dist from cursor pos to UL corner
+} GFXglyph;
+
+typedef struct { // Data stored for FONT AS A WHOLE:
+ uint8_t *bitmap; // Glyph bitmaps, concatenated
+ GFXglyph *glyph; // Glyph array
+ uint8_t first, last; // ASCII extents
+ uint8_t yAdvance; // Newline distance (y axis)
+} GFXfont;
+
+#endif // _GFXFONT_H_
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/oled/glcdfont.c Sun Jun 16 04:44:35 2019 +0000
@@ -0,0 +1,269 @@
+// This is the 'classic' fixed-space bitmap font for Adafruit_GFX since 1.0.
+// See gfxfont.h for newer custom bitmap font info.
+
+#ifndef FONT5X7_H
+#define FONT5X7_H
+
+#define PROGMEM
+
+// 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,
+ 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,
+ 0x55, 0x00, 0x55, 0x00, 0x55, // #176 (25% block) missing in old code
+ 0xAA, 0x55, 0xAA, 0x55, 0xAA, // 50% block
+ 0xFF, 0x55, 0xFF, 0x55, 0xFF, // 75% block
+ 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,
+ 0x00, 0x00, 0x18, 0x18, 0x00,
+ 0x00, 0x00, 0x10, 0x10, 0x00,
+ 0x30, 0x40, 0xFF, 0x01, 0x01,
+ 0x00, 0x1F, 0x01, 0x01, 0x1E,
+ 0x00, 0x19, 0x1D, 0x17, 0x12,
+ 0x00, 0x3C, 0x3C, 0x3C, 0x3C,
+ 0x00, 0x00, 0x00, 0x00, 0x00 // #255 NBSP
+};
+#endif // FONT5X7_H