aboutsummaryrefslogtreecommitdiff
path: root/drivers/avr
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/avr')
-rw-r--r--drivers/avr/analog.c53
-rw-r--r--drivers/avr/analog.h26
-rw-r--r--[-rwxr-xr-x]drivers/avr/apa102.c147
-rw-r--r--[-rwxr-xr-x]drivers/avr/apa102.h5
-rw-r--r--drivers/avr/glcdfont.c280
-rw-r--r--drivers/avr/hd44780.c510
-rw-r--r--drivers/avr/hd44780.h303
-rw-r--r--[-rwxr-xr-x]drivers/avr/i2c_master.c260
-rw-r--r--[-rwxr-xr-x]drivers/avr/i2c_master.h12
-rw-r--r--[-rwxr-xr-x]drivers/avr/i2c_slave.c18
-rw-r--r--[-rwxr-xr-x]drivers/avr/i2c_slave.h2
-rw-r--r--drivers/avr/pro_micro.h270
-rw-r--r--drivers/avr/ssd1306.c427
-rw-r--r--drivers/avr/ssd1306.h84
-rw-r--r--drivers/avr/ws2812.c384
-rw-r--r--drivers/avr/ws2812.h17
16 files changed, 1195 insertions, 1603 deletions
diff --git a/drivers/avr/analog.c b/drivers/avr/analog.c
index 1ec38df75..1a8da4261 100644
--- a/drivers/avr/analog.c
+++ b/drivers/avr/analog.c
@@ -21,49 +21,38 @@
21#include <stdint.h> 21#include <stdint.h>
22#include "analog.h" 22#include "analog.h"
23 23
24static uint8_t aref = (1 << REFS0); // default to AREF = Vcc
24 25
25static uint8_t aref = (1<<REFS0); // default to AREF = Vcc 26void analogReference(uint8_t mode) { aref = mode & 0xC0; }
26
27
28void analogReference(uint8_t mode)
29{
30 aref = mode & 0xC0;
31}
32
33 27
34// Arduino compatible pin input 28// Arduino compatible pin input
35int16_t analogRead(uint8_t pin) 29int16_t analogRead(uint8_t pin) {
36{
37#if defined(__AVR_ATmega32U4__) 30#if defined(__AVR_ATmega32U4__)
38 static const uint8_t PROGMEM pin_to_mux[] = { 31 static const uint8_t PROGMEM pin_to_mux[] = {0x00, 0x01, 0x04, 0x05, 0x06, 0x07, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20};
39 0x00, 0x01, 0x04, 0x05, 0x06, 0x07, 32 if (pin >= 12) return 0;
40 0x25, 0x24, 0x23, 0x22, 0x21, 0x20}; 33 return adc_read(pgm_read_byte(pin_to_mux + pin));
41 if (pin >= 12) return 0;
42 return adc_read(pgm_read_byte(pin_to_mux + pin));
43#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) 34#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
44 if (pin >= 8) return 0; 35 if (pin >= 8) return 0;
45 return adc_read(pin); 36 return adc_read(pin);
46#else 37#else
47 return 0; 38 return 0;
48#endif 39#endif
49} 40}
50 41
51// Mux input 42// Mux input
52int16_t adc_read(uint8_t mux) 43int16_t adc_read(uint8_t mux) {
53{
54#if defined(__AVR_AT90USB162__) 44#if defined(__AVR_AT90USB162__)
55 return 0; 45 return 0;
56#else 46#else
57 uint8_t low; 47 uint8_t low;
58 48
59 ADCSRA = (1<<ADEN) | ADC_PRESCALER; // enable ADC 49 ADCSRA = (1 << ADEN) | ADC_PRESCALER; // enable ADC
60 ADCSRB = (1<<ADHSM) | (mux & 0x20); // high speed mode 50 ADCSRB = (1 << ADHSM) | (mux & 0x20); // high speed mode
61 ADMUX = aref | (mux & 0x1F); // configure mux input 51 ADMUX = aref | (mux & 0x1F); // configure mux input
62 ADCSRA = (1<<ADEN) | ADC_PRESCALER | (1<<ADSC); // start the conversion 52 ADCSRA = (1 << ADEN) | ADC_PRESCALER | (1 << ADSC); // start the conversion
63 while (ADCSRA & (1<<ADSC)) ; // wait for result 53 while (ADCSRA & (1 << ADSC))
64 low = ADCL; // must read LSB first 54 ; // wait for result
65 return (ADCH << 8) | low; // must read MSB only once! 55 low = ADCL; // must read LSB first
56 return (ADCH << 8) | low; // must read MSB only once!
66#endif 57#endif
67} 58}
68
69
diff --git a/drivers/avr/analog.h b/drivers/avr/analog.h
index 8d93de7dc..32452a1ec 100644
--- a/drivers/avr/analog.h
+++ b/drivers/avr/analog.h
@@ -19,34 +19,34 @@
19 19
20#include <stdint.h> 20#include <stdint.h>
21 21
22void analogReference(uint8_t mode); 22void analogReference(uint8_t mode);
23int16_t analogRead(uint8_t pin); 23int16_t analogRead(uint8_t pin);
24int16_t adc_read(uint8_t mux); 24int16_t adc_read(uint8_t mux);
25 25
26#define ADC_REF_POWER (1<<REFS0) 26#define ADC_REF_POWER (1 << REFS0)
27#define ADC_REF_INTERNAL ((1<<REFS1) | (1<<REFS0)) 27#define ADC_REF_INTERNAL ((1 << REFS1) | (1 << REFS0))
28#define ADC_REF_EXTERNAL (0) 28#define ADC_REF_EXTERNAL (0)
29 29
30// These prescaler values are for high speed mode, ADHSM = 1 30// These prescaler values are for high speed mode, ADHSM = 1
31#if F_CPU == 16000000L 31#if F_CPU == 16000000L
32#define ADC_PRESCALER ((1<<ADPS2) | (1<<ADPS1)) 32# define ADC_PRESCALER ((1 << ADPS2) | (1 << ADPS1))
33#elif F_CPU == 8000000L 33#elif F_CPU == 8000000L
34#define ADC_PRESCALER ((1<<ADPS2) | (1<<ADPS0)) 34# define ADC_PRESCALER ((1 << ADPS2) | (1 << ADPS0))
35#elif F_CPU == 4000000L 35#elif F_CPU == 4000000L
36#define ADC_PRESCALER ((1<<ADPS2)) 36# define ADC_PRESCALER ((1 << ADPS2))
37#elif F_CPU == 2000000L 37#elif F_CPU == 2000000L
38#define ADC_PRESCALER ((1<<ADPS1) | (1<<ADPS0)) 38# define ADC_PRESCALER ((1 << ADPS1) | (1 << ADPS0))
39#elif F_CPU == 1000000L 39#elif F_CPU == 1000000L
40#define ADC_PRESCALER ((1<<ADPS1)) 40# define ADC_PRESCALER ((1 << ADPS1))
41#else 41#else
42#define ADC_PRESCALER ((1<<ADPS0)) 42# define ADC_PRESCALER ((1 << ADPS0))
43#endif 43#endif
44 44
45// some avr-libc versions do not properly define ADHSM 45// some avr-libc versions do not properly define ADHSM
46#if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) 46#if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
47#if !defined(ADHSM) 47# if !defined(ADHSM)
48#define ADHSM (7) 48# define ADHSM (7)
49#endif 49# endif
50#endif 50#endif
51 51
52#endif 52#endif
diff --git a/drivers/avr/apa102.c b/drivers/avr/apa102.c
index 55a0d5777..f4d97a158 100755..100644
--- a/drivers/avr/apa102.c
+++ b/drivers/avr/apa102.c
@@ -1,24 +1,24 @@
1/* 1/*
2* APA102 lib V1.0a 2 * APA102 lib V1.0a
3* 3 *
4* Controls APA102 RGB-LEDs 4 * Controls APA102 RGB-LEDs
5* Author: Mikkel (Duckle29 on github) 5 * Author: Mikkel (Duckle29 on github)
6* 6 *
7* Dec 22th, 2017 v1.0a Initial Version 7 * Dec 22th, 2017 v1.0a Initial Version
8* 8 *
9* This program is free software: you can redistribute it and/or modify 9 * This program is free software: you can redistribute it and/or modify
10* it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
11* the Free Software Foundation, either version 2 of the License, or 11 * the Free Software Foundation, either version 2 of the License, or
12* (at your option) any later version. 12 * (at your option) any later version.
13* 13 *
14* This program is distributed in the hope that it will be useful, 14 * This program is distributed in the hope that it will be useful,
15* but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17* GNU General Public License for more details. 17 * GNU General Public License for more details.
18* 18 *
19* You should have received a copy of the GNU General Public License 19 * You should have received a copy of the GNU General Public License
20* along with this program. If not, see <http://www.gnu.org/licenses/>. 20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21*/ 21 */
22 22
23#include "apa102.h" 23#include "apa102.h"
24#include <avr/interrupt.h> 24#include <avr/interrupt.h>
@@ -27,75 +27,70 @@
27#include "debug.h" 27#include "debug.h"
28 28
29// Setleds for standard RGB 29// Setleds for standard RGB
30void inline apa102_setleds(LED_TYPE *ledarray, uint16_t leds){ 30void inline apa102_setleds(LED_TYPE *ledarray, uint16_t leds) { apa102_setleds_pin(ledarray, leds, _BV(RGB_DI_PIN & 0xF), _BV(RGB_CLK_PIN & 0xF)); }
31 apa102_setleds_pin(ledarray,leds, _BV(RGB_DI_PIN & 0xF), _BV(RGB_CLK_PIN & 0xF));
32}
33 31
34void static inline apa102_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmask_DI, uint8_t pinmask_CLK){ 32void static inline apa102_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmask_DI, uint8_t pinmask_CLK) {
35 pinMode(RGB_DI_PIN, PinDirectionOutput); 33 pinMode(RGB_DI_PIN, PinDirectionOutput);
36 pinMode(RGB_CLK_PIN, PinDirectionOutput); 34 pinMode(RGB_CLK_PIN, PinDirectionOutput);
37 35
38 apa102_send_array((uint8_t*)ledarray,leds) 36 apa102_send_array((uint8_t *)ledarray, leds)
39} 37}
40 38
41void apa102_send_array(uint8_t *data, uint16_t leds){ // Data is struct of 3 bytes. RGB - leds is number of leds in data 39void apa102_send_array(uint8_t *data, uint16_t leds) { // Data is struct of 3 bytes. RGB - leds is number of leds in data
42 apa102_start_frame(); 40 apa102_start_frame();
43 while(leds--){ 41 while (leds--) {
44 apa102_send_frame(0xFF000000 | (data->b << 16) | (data->g << 8) | data->r); 42 apa102_send_frame(0xFF000000 | (data->b << 16) | (data->g << 8) | data->r);
45 data++; 43 data++;
46 } 44 }
47 apa102_end_frame(leds); 45 apa102_end_frame(leds);
48} 46}
49 47
50void apa102_send_frame(uint32_t frame){ 48void apa102_send_frame(uint32_t frame) {
51 for(uint32_t i=0xFF; i>0;){ 49 for (uint32_t i = 0xFF; i > 0;) {
52 apa102_send_byte(frame & i); 50 apa102_send_byte(frame & i);
53 i = i << 8; 51 i = i << 8;
54 } 52 }
55} 53}
56 54
57void apa102_start_frame(){ 55void apa102_start_frame() { apa102_send_frame(0); }
58 apa102_send_frame(0);
59}
60 56
61void apa102_end_frame(uint16_t leds) 57void apa102_end_frame(uint16_t leds) {
62{ 58 // This function has been taken from: https://github.com/pololu/apa102-arduino/blob/master/APA102.h
63 // This function has been taken from: https://github.com/pololu/apa102-arduino/blob/master/APA102.h 59 // and adapted. The code is MIT licensed. I think thats compatible?
64 // and adapted. The code is MIT licensed. I think thats compatible?
65 60
66 // We need to send some more bytes to ensure that all the LEDs in the 61 // We need to send some more bytes to ensure that all the LEDs in the
67 // chain see their new color and start displaying it. 62 // chain see their new color and start displaying it.
68 // 63 //
69 // The data stream seen by the last LED in the chain will be delayed by 64 // The data stream seen by the last LED in the chain will be delayed by
70 // (count - 1) clock edges, because each LED before it inverts the clock 65 // (count - 1) clock edges, because each LED before it inverts the clock
71 // line and delays the data by one clock edge. Therefore, to make sure 66 // line and delays the data by one clock edge. Therefore, to make sure
72 // the last LED actually receives the data we wrote, the number of extra 67 // the last LED actually receives the data we wrote, the number of extra
73 // edges we send at the end of the frame must be at least (count - 1). 68 // edges we send at the end of the frame must be at least (count - 1).
74 // For the APA102C, that is sufficient. 69 // For the APA102C, that is sufficient.
75 // 70 //
76 // The SK9822 only updates after it sees 32 zero bits followed by one more 71 // The SK9822 only updates after it sees 32 zero bits followed by one more
77 // rising edge. To avoid having the update time depend on the color of 72 // rising edge. To avoid having the update time depend on the color of
78 // the last LED, we send a dummy 0xFF byte. (Unfortunately, this means 73 // the last LED, we send a dummy 0xFF byte. (Unfortunately, this means
79 // that partial updates of the beginning of an LED strip are not possible; 74 // that partial updates of the beginning of an LED strip are not possible;
80 // the LED after the last one you are trying to update will be black.) 75 // the LED after the last one you are trying to update will be black.)
81 // After that, to ensure that the last LED in the chain sees 32 zero bits 76 // After that, to ensure that the last LED in the chain sees 32 zero bits
82 // and a rising edge, we need to send at least 65 + (count - 1) edges. It 77 // and a rising edge, we need to send at least 65 + (count - 1) edges. It
83 // is sufficent and simpler to just send (5 + count/16) bytes of zeros. 78 // is sufficent and simpler to just send (5 + count/16) bytes of zeros.
84 // 79 //
85 // We are ignoring the specification for the end frame in the APA102/SK9822 80 // We are ignoring the specification for the end frame in the APA102/SK9822
86 // datasheets because it does not actually ensure that all the LEDs will 81 // datasheets because it does not actually ensure that all the LEDs will
87 // start displaying their new colors right away. 82 // start displaying their new colors right away.
88 83
89 apa102_send_byte(0xFF); 84 apa102_send_byte(0xFF);
90 for (uint16_t i = 0; i < 5 + leds / 16; i++){ 85 for (uint16_t i = 0; i < 5 + leds / 16; i++) {
91 apa102_send_byte(0); 86 apa102_send_byte(0);
92 } 87 }
93} 88}
94 89
95void apa102_send_byte(uint8_t byte){ 90void apa102_send_byte(uint8_t byte) {
96 uint8_t i; 91 uint8_t i;
97 for (i = 0; i < 8; i++){ 92 for (i = 0; i < 8; i++) {
98 digitalWrite(RGB_DI_PIN, !!(byte & (1 << (7-i))); 93 digitalWrite(RGB_DI_PIN, !!(byte & (1 << (7-i)));
99 digitalWrite(RGB_CLK_PIN, PinLevelHigh); 94 digitalWrite(RGB_CLK_PIN, PinLevelHigh);
100 } 95 }
101} 96}
diff --git a/drivers/avr/apa102.h b/drivers/avr/apa102.h
index 5d852e067..d4c1e18ee 100755..100644
--- a/drivers/avr/apa102.h
+++ b/drivers/avr/apa102.h
@@ -27,7 +27,6 @@
27 27
28#include "color.h" 28#include "color.h"
29 29
30
31/* User Interface 30/* User Interface
32 * 31 *
33 * Input: 32 * Input:
@@ -41,6 +40,6 @@
41 * - Wait 50�s to reset the LEDs 40 * - Wait 50�s to reset the LEDs
42 */ 41 */
43 42
44void apa102_setleds (LED_TYPE *ledarray, uint16_t number_of_leds); 43void apa102_setleds(LED_TYPE *ledarray, uint16_t number_of_leds);
45void apa102_setleds_pin (LED_TYPE *ledarray, uint16_t number_of_leds,uint8_t pinmask); 44void apa102_setleds_pin(LED_TYPE *ledarray, uint16_t number_of_leds, uint8_t pinmask);
46void apa102_setleds_rgbw(LED_TYPE *ledarray, uint16_t number_of_leds); 45void apa102_setleds_rgbw(LED_TYPE *ledarray, uint16_t number_of_leds);
diff --git a/drivers/avr/glcdfont.c b/drivers/avr/glcdfont.c
index 6f88bd23a..2c332ea6d 100644
--- a/drivers/avr/glcdfont.c
+++ b/drivers/avr/glcdfont.c
@@ -5,272 +5,30 @@
5#define FONT5X7_H 5#define FONT5X7_H
6 6
7#ifdef __AVR__ 7#ifdef __AVR__
8 #include <avr/io.h> 8# include <avr/io.h>
9 #include <avr/pgmspace.h> 9# include <avr/pgmspace.h>
10#elif defined(ESP8266) 10#elif defined(ESP8266)
11 #include <pgmspace.h> 11# include <pgmspace.h>
12#else 12#else
13 #define PROGMEM 13# define PROGMEM
14#endif 14#endif
15 15
16// Standard ASCII 5x7 font 16// Standard ASCII 5x7 font
17 17
18static const unsigned char font[] PROGMEM = { 18static const unsigned char font[] PROGMEM = {
19 0x00, 0x00, 0x00, 0x00, 0x00, 19 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,
20 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, 20 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,
21 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, 21 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,
22 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, 22 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,
23 0x18, 0x3C, 0x7E, 0x3C, 0x18, 23 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
24 0x1C, 0x57, 0x7D, 0x57, 0x1C, 24 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
25 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, 25 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
26 0x00, 0x18, 0x3C, 0x18, 0x00, 26 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
27 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, 27 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
28 0x00, 0x18, 0x24, 0x18, 0x00, 28 0xAA, 0x55, 0xAA, 0x55, 0xAA, // 50% block
29 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, 29 0xFF, 0x55, 0xFF, 0x55, 0xFF, // 75% block
30 0x30, 0x48, 0x3A, 0x06, 0x0E, 30 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,
31 0x26, 0x29, 0x79, 0x29, 0x26, 31 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
32 0x40, 0x7F, 0x05, 0x05, 0x07, 32 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
33 0x40, 0x7F, 0x05, 0x25, 0x3F,
34 0x5A, 0x3C, 0xE7, 0x3C, 0x5A,
35 0x7F, 0x3E, 0x1C, 0x1C, 0x08,
36 0x08, 0x1C, 0x1C, 0x3E, 0x7F,
37 0x14, 0x22, 0x7F, 0x22, 0x14,
38 0x5F, 0x5F, 0x00, 0x5F, 0x5F,
39 0x06, 0x09, 0x7F, 0x01, 0x7F,
40 0x00, 0x66, 0x89, 0x95, 0x6A,
41 0x60, 0x60, 0x60, 0x60, 0x60,
42 0x94, 0xA2, 0xFF, 0xA2, 0x94,
43 0x08, 0x04, 0x7E, 0x04, 0x08,
44 0x10, 0x20, 0x7E, 0x20, 0x10,
45 0x08, 0x08, 0x2A, 0x1C, 0x08,
46 0x08, 0x1C, 0x2A, 0x08, 0x08,
47 0x1E, 0x10, 0x10, 0x10, 0x10,
48 0x0C, 0x1E, 0x0C, 0x1E, 0x0C,
49 0x30, 0x38, 0x3E, 0x38, 0x30,
50 0x06, 0x0E, 0x3E, 0x0E, 0x06,
51 0x00, 0x00, 0x00, 0x00, 0x00,
52 0x00, 0x00, 0x5F, 0x00, 0x00,
53 0x00, 0x07, 0x00, 0x07, 0x00,
54 0x14, 0x7F, 0x14, 0x7F, 0x14,
55 0x24, 0x2A, 0x7F, 0x2A, 0x12,
56 0x23, 0x13, 0x08, 0x64, 0x62,
57 0x36, 0x49, 0x56, 0x20, 0x50,
58 0x00, 0x08, 0x07, 0x03, 0x00,
59 0x00, 0x1C, 0x22, 0x41, 0x00,
60 0x00, 0x41, 0x22, 0x1C, 0x00,
61 0x2A, 0x1C, 0x7F, 0x1C, 0x2A,
62 0x08, 0x08, 0x3E, 0x08, 0x08,
63 0x00, 0x80, 0x70, 0x30, 0x00,
64 0x08, 0x08, 0x08, 0x08, 0x08,
65 0x00, 0x00, 0x60, 0x60, 0x00,
66 0x20, 0x10, 0x08, 0x04, 0x02,
67 0x3E, 0x51, 0x49, 0x45, 0x3E,
68 0x00, 0x42, 0x7F, 0x40, 0x00,
69 0x72, 0x49, 0x49, 0x49, 0x46,
70 0x21, 0x41, 0x49, 0x4D, 0x33,
71 0x18, 0x14, 0x12, 0x7F, 0x10,
72 0x27, 0x45, 0x45, 0x45, 0x39,
73 0x3C, 0x4A, 0x49, 0x49, 0x31,
74 0x41, 0x21, 0x11, 0x09, 0x07,
75 0x36, 0x49, 0x49, 0x49, 0x36,
76 0x46, 0x49, 0x49, 0x29, 0x1E,
77 0x00, 0x00, 0x14, 0x00, 0x00,
78 0x00, 0x40, 0x34, 0x00, 0x00,
79 0x00, 0x08, 0x14, 0x22, 0x41,
80 0x14, 0x14, 0x14, 0x14, 0x14,
81 0x00, 0x41, 0x22, 0x14, 0x08,
82 0x02, 0x01, 0x59, 0x09, 0x06,
83 0x3E, 0x41, 0x5D, 0x59, 0x4E,
84 0x7C, 0x12, 0x11, 0x12, 0x7C,
85 0x7F, 0x49, 0x49, 0x49, 0x36,
86 0x3E, 0x41, 0x41, 0x41, 0x22,
87 0x7F, 0x41, 0x41, 0x41, 0x3E,
88 0x7F, 0x49, 0x49, 0x49, 0x41,
89 0x7F, 0x09, 0x09, 0x09, 0x01,
90 0x3E, 0x41, 0x41, 0x51, 0x73,
91 0x7F, 0x08, 0x08, 0x08, 0x7F,
92 0x00, 0x41, 0x7F, 0x41, 0x00,
93 0x20, 0x40, 0x41, 0x3F, 0x01,
94 0x7F, 0x08, 0x14, 0x22, 0x41,
95 0x7F, 0x40, 0x40, 0x40, 0x40,
96 0x7F, 0x02, 0x1C, 0x02, 0x7F,
97 0x7F, 0x04, 0x08, 0x10, 0x7F,
98 0x3E, 0x41, 0x41, 0x41, 0x3E,
99 0x7F, 0x09, 0x09, 0x09, 0x06,
100 0x3E, 0x41, 0x51, 0x21, 0x5E,
101 0x7F, 0x09, 0x19, 0x29, 0x46,
102 0x26, 0x49, 0x49, 0x49, 0x32,
103 0x03, 0x01, 0x7F, 0x01, 0x03,
104 0x3F, 0x40, 0x40, 0x40, 0x3F,
105 0x1F, 0x20, 0x40, 0x20, 0x1F,
106 0x3F, 0x40, 0x38, 0x40, 0x3F,
107 0x63, 0x14, 0x08, 0x14, 0x63,
108 0x03, 0x04, 0x78, 0x04, 0x03,
109 0x61, 0x59, 0x49, 0x4D, 0x43,
110 0x00, 0x7F, 0x41, 0x41, 0x41,
111 0x02, 0x04, 0x08, 0x10, 0x20,
112 0x00, 0x41, 0x41, 0x41, 0x7F,
113 0x04, 0x02, 0x01, 0x02, 0x04,
114 0x40, 0x40, 0x40, 0x40, 0x40,
115 0x00, 0x03, 0x07, 0x08, 0x00,
116 0x20, 0x54, 0x54, 0x78, 0x40,
117 0x7F, 0x28, 0x44, 0x44, 0x38,
118 0x38, 0x44, 0x44, 0x44, 0x28,
119 0x38, 0x44, 0x44, 0x28, 0x7F,
120 0x38, 0x54, 0x54, 0x54, 0x18,
121 0x00, 0x08, 0x7E, 0x09, 0x02,
122 0x18, 0xA4, 0xA4, 0x9C, 0x78,
123 0x7F, 0x08, 0x04, 0x04, 0x78,
124 0x00, 0x44, 0x7D, 0x40, 0x00,
125 0x20, 0x40, 0x40, 0x3D, 0x00,
126 0x7F, 0x10, 0x28, 0x44, 0x00,
127 0x00, 0x41, 0x7F, 0x40, 0x00,
128 0x7C, 0x04, 0x78, 0x04, 0x78,
129 0x7C, 0x08, 0x04, 0x04, 0x78,
130 0x38, 0x44, 0x44, 0x44, 0x38,
131 0xFC, 0x18, 0x24, 0x24, 0x18,
132 0x18, 0x24, 0x24, 0x18, 0xFC,
133 0x7C, 0x08, 0x04, 0x04, 0x08,
134 0x48, 0x54, 0x54, 0x54, 0x24,
135 0x04, 0x04, 0x3F, 0x44, 0x24,
136 0x3C, 0x40, 0x40, 0x20, 0x7C,
137 0x1C, 0x20, 0x40, 0x20, 0x1C,
138 0x3C, 0x40, 0x30, 0x40, 0x3C,
139 0x44, 0x28, 0x10, 0x28, 0x44,
140 0x4C, 0x90, 0x90, 0x90, 0x7C,
141 0x44, 0x64, 0x54, 0x4C, 0x44,
142 0x00, 0x08, 0x36, 0x41, 0x00,
143 0x00, 0x00, 0x77, 0x00, 0x00,
144 0x00, 0x41, 0x36, 0x08, 0x00,
145 0x02, 0x01, 0x02, 0x04, 0x02,
146 0x3C, 0x26, 0x23, 0x26, 0x3C,
147 0x1E, 0xA1, 0xA1, 0x61, 0x12,
148 0x3A, 0x40, 0x40, 0x20, 0x7A,
149 0x38, 0x54, 0x54, 0x55, 0x59,
150 0x21, 0x55, 0x55, 0x79, 0x41,
151 0x22, 0x54, 0x54, 0x78, 0x42, // a-umlaut
152 0x21, 0x55, 0x54, 0x78, 0x40,
153 0x20, 0x54, 0x55, 0x79, 0x40,
154 0x0C, 0x1E, 0x52, 0x72, 0x12,
155 0x39, 0x55, 0x55, 0x55, 0x59,
156 0x39, 0x54, 0x54, 0x54, 0x59,
157 0x39, 0x55, 0x54, 0x54, 0x58,
158 0x00, 0x00, 0x45, 0x7C, 0x41,
159 0x00, 0x02, 0x45, 0x7D, 0x42,
160 0x00, 0x01, 0x45, 0x7C, 0x40,
161 0x7D, 0x12, 0x11, 0x12, 0x7D, // A-umlaut
162 0xF0, 0x28, 0x25, 0x28, 0xF0,
163 0x7C, 0x54, 0x55, 0x45, 0x00,
164 0x20, 0x54, 0x54, 0x7C, 0x54,
165 0x7C, 0x0A, 0x09, 0x7F, 0x49,
166 0x32, 0x49, 0x49, 0x49, 0x32,
167 0x3A, 0x44, 0x44, 0x44, 0x3A, // o-umlaut
168 0x32, 0x4A, 0x48, 0x48, 0x30,
169 0x3A, 0x41, 0x41, 0x21, 0x7A,
170 0x3A, 0x42, 0x40, 0x20, 0x78,
171 0x00, 0x9D, 0xA0, 0xA0, 0x7D,
172 0x3D, 0x42, 0x42, 0x42, 0x3D, // O-umlaut
173 0x3D, 0x40, 0x40, 0x40, 0x3D,
174 0x3C, 0x24, 0xFF, 0x24, 0x24,
175 0x48, 0x7E, 0x49, 0x43, 0x66,
176 0x2B, 0x2F, 0xFC, 0x2F, 0x2B,
177 0xFF, 0x09, 0x29, 0xF6, 0x20,
178 0xC0, 0x88, 0x7E, 0x09, 0x03,
179 0x20, 0x54, 0x54, 0x79, 0x41,
180 0x00, 0x00, 0x44, 0x7D, 0x41,
181 0x30, 0x48, 0x48, 0x4A, 0x32,
182 0x38, 0x40, 0x40, 0x22, 0x7A,
183 0x00, 0x7A, 0x0A, 0x0A, 0x72,
184 0x7D, 0x0D, 0x19, 0x31, 0x7D,
185 0x26, 0x29, 0x29, 0x2F, 0x28,
186 0x26, 0x29, 0x29, 0x29, 0x26,
187 0x30, 0x48, 0x4D, 0x40, 0x20,
188 0x38, 0x08, 0x08, 0x08, 0x08,
189 0x08, 0x08, 0x08, 0x08, 0x38,
190 0x2F, 0x10, 0xC8, 0xAC, 0xBA,
191 0x2F, 0x10, 0x28, 0x34, 0xFA,
192 0x00, 0x00, 0x7B, 0x00, 0x00,
193 0x08, 0x14, 0x2A, 0x14, 0x22,
194 0x22, 0x14, 0x2A, 0x14, 0x08,
195 0x55, 0x00, 0x55, 0x00, 0x55, // #176 (25% block) missing in old code
196 0xAA, 0x55, 0xAA, 0x55, 0xAA, // 50% block
197 0xFF, 0x55, 0xFF, 0x55, 0xFF, // 75% block
198 0x00, 0x00, 0x00, 0xFF, 0x00,
199 0x10, 0x10, 0x10, 0xFF, 0x00,
200 0x14, 0x14, 0x14, 0xFF, 0x00,
201 0x10, 0x10, 0xFF, 0x00, 0xFF,
202 0x10, 0x10, 0xF0, 0x10, 0xF0,
203 0x14, 0x14, 0x14, 0xFC, 0x00,
204 0x14, 0x14, 0xF7, 0x00, 0xFF,
205 0x00, 0x00, 0xFF, 0x00, 0xFF,
206 0x14, 0x14, 0xF4, 0x04, 0xFC,
207 0x14, 0x14, 0x17, 0x10, 0x1F,
208 0x10, 0x10, 0x1F, 0x10, 0x1F,
209 0x14, 0x14, 0x14, 0x1F, 0x00,
210 0x10, 0x10, 0x10, 0xF0, 0x00,
211 0x00, 0x00, 0x00, 0x1F, 0x10,
212 0x10, 0x10, 0x10, 0x1F, 0x10,
213 0x10, 0x10, 0x10, 0xF0, 0x10,
214 0x00, 0x00, 0x00, 0xFF, 0x10,
215 0x10, 0x10, 0x10, 0x10, 0x10,
216 0x10, 0x10, 0x10, 0xFF, 0x10,
217 0x00, 0x00, 0x00, 0xFF, 0x14,
218 0x00, 0x00, 0xFF, 0x00, 0xFF,
219 0x00, 0x00, 0x1F, 0x10, 0x17,
220 0x00, 0x00, 0xFC, 0x04, 0xF4,
221 0x14, 0x14, 0x17, 0x10, 0x17,
222 0x14, 0x14, 0xF4, 0x04, 0xF4,
223 0x00, 0x00, 0xFF, 0x00, 0xF7,
224 0x14, 0x14, 0x14, 0x14, 0x14,
225 0x14, 0x14, 0xF7, 0x00, 0xF7,
226 0x14, 0x14, 0x14, 0x17, 0x14,
227 0x10, 0x10, 0x1F, 0x10, 0x1F,
228 0x14, 0x14, 0x14, 0xF4, 0x14,
229 0x10, 0x10, 0xF0, 0x10, 0xF0,
230 0x00, 0x00, 0x1F, 0x10, 0x1F,
231 0x00, 0x00, 0x00, 0x1F, 0x14,
232 0x00, 0x00, 0x00, 0xFC, 0x14,
233 0x00, 0x00, 0xF0, 0x10, 0xF0,
234 0x10, 0x10, 0xFF, 0x10, 0xFF,
235 0x14, 0x14, 0x14, 0xFF, 0x14,
236 0x10, 0x10, 0x10, 0x1F, 0x00,
237 0x00, 0x00, 0x00, 0xF0, 0x10,
238 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
239 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
240 0xFF, 0xFF, 0xFF, 0x00, 0x00,
241 0x00, 0x00, 0x00, 0xFF, 0xFF,
242 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
243 0x38, 0x44, 0x44, 0x38, 0x44,
244 0xFC, 0x4A, 0x4A, 0x4A, 0x34, // sharp-s or beta
245 0x7E, 0x02, 0x02, 0x06, 0x06,
246 0x02, 0x7E, 0x02, 0x7E, 0x02,
247 0x63, 0x55, 0x49, 0x41, 0x63,
248 0x38, 0x44, 0x44, 0x3C, 0x04,
249 0x40, 0x7E, 0x20, 0x1E, 0x20,
250 0x06, 0x02, 0x7E, 0x02, 0x02,
251 0x99, 0xA5, 0xE7, 0xA5, 0x99,
252 0x1C, 0x2A, 0x49, 0x2A, 0x1C,
253 0x4C, 0x72, 0x01, 0x72, 0x4C,
254 0x30, 0x4A, 0x4D, 0x4D, 0x30,
255 0x30, 0x48, 0x78, 0x48, 0x30,
256 0xBC, 0x62, 0x5A, 0x46, 0x3D,
257 0x3E, 0x49, 0x49, 0x49, 0x00,
258 0x7E, 0x01, 0x01, 0x01, 0x7E,
259 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
260 0x44, 0x44, 0x5F, 0x44, 0x44,
261 0x40, 0x51, 0x4A, 0x44, 0x40,
262 0x40, 0x44, 0x4A, 0x51, 0x40,
263 0x00, 0x00, 0xFF, 0x01, 0x03,
264 0xE0, 0x80, 0xFF, 0x00, 0x00,
265 0x08, 0x08, 0x6B, 0x6B, 0x08,
266 0x36, 0x12, 0x36, 0x24, 0x36,
267 0x06, 0x0F, 0x09, 0x0F, 0x06,
268 0x00, 0x00, 0x18, 0x18, 0x00,
269 0x00, 0x00, 0x10, 0x10, 0x00,
270 0x30, 0x40, 0xFF, 0x01, 0x01,
271 0x00, 0x1F, 0x01, 0x01, 0x1E,
272 0x00, 0x19, 0x1D, 0x17, 0x12,
273 0x00, 0x3C, 0x3C, 0x3C, 0x3C,
274 0x00, 0x00, 0x00, 0x00, 0x00 // #255 NBSP
275}; 33};
276#endif // FONT5X7_H 34#endif // FONT5X7_H
diff --git a/drivers/avr/hd44780.c b/drivers/avr/hd44780.c
index 51414d8f9..f71069dec 100644
--- a/drivers/avr/hd44780.c
+++ b/drivers/avr/hd44780.c
@@ -3,7 +3,7 @@
3 Author: Peter Fleury <pfleury@gmx.ch> http://tinyurl.com/peterfleury 3 Author: Peter Fleury <pfleury@gmx.ch> http://tinyurl.com/peterfleury
4 License: GNU General Public License Version 3 4 License: GNU General Public License Version 3
5 File: $Id: lcd.c,v 1.15.2.2 2015/01/17 12:16:05 peter Exp $ 5 File: $Id: lcd.c,v 1.15.2.2 2015/01/17 12:16:05 peter Exp $
6 Software: AVR-GCC 3.3 6 Software: AVR-GCC 3.3
7 Target: any AVR device, memory mapped mode only for AT90S4414/8515/Mega 7 Target: any AVR device, memory mapped mode only for AT90S4414/8515/Mega
8 8
9 DESCRIPTION 9 DESCRIPTION
@@ -13,15 +13,15 @@
13 changed lcd_init(), added additional constants for lcd_command(), 13 changed lcd_init(), added additional constants for lcd_command(),
14 added 4-bit I/O mode, improved and optimized code. 14 added 4-bit I/O mode, improved and optimized code.
15 15
16 Library can be operated in memory mapped mode (LCD_IO_MODE=0) or in 16 Library can be operated in memory mapped mode (LCD_IO_MODE=0) or in
17 4-bit IO port mode (LCD_IO_MODE=1). 8-bit IO port mode not supported. 17 4-bit IO port mode (LCD_IO_MODE=1). 8-bit IO port mode not supported.
18 18
19 Memory mapped mode compatible with Kanda STK200, but supports also 19 Memory mapped mode compatible with Kanda STK200, but supports also
20 generation of R/W signal through A8 address line. 20 generation of R/W signal through A8 address line.
21 21
22 USAGE 22 USAGE
23 See the C include lcd.h file for a description of each function 23 See the C include lcd.h file for a description of each function
24 24
25*****************************************************************************/ 25*****************************************************************************/
26#include <inttypes.h> 26#include <inttypes.h>
27#include <avr/io.h> 27#include <avr/io.h>
@@ -29,55 +29,54 @@
29#include <util/delay.h> 29#include <util/delay.h>
30#include "hd44780.h" 30#include "hd44780.h"
31 31
32/* 32/*
33** constants/macros 33** constants/macros
34*/ 34*/
35#define DDR(x) (*(&x - 1)) /* address of data direction register of port x */ 35#define DDR(x) (*(&x - 1)) /* address of data direction register of port x */
36#if defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) 36#if defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__)
37 /* on ATmega64/128 PINF is on port 0x00 and not 0x60 */ 37/* on ATmega64/128 PINF is on port 0x00 and not 0x60 */
38 #define PIN(x) ( &PORTF==&(x) ? _SFR_IO8(0x00) : (*(&x - 2)) ) 38# define PIN(x) (&PORTF == &(x) ? _SFR_IO8(0x00) : (*(&x - 2)))
39#else 39#else
40 #define PIN(x) (*(&x - 2)) /* address of input register of port x */ 40# define PIN(x) (*(&x - 2)) /* address of input register of port x */
41#endif 41#endif
42 42
43
44#if LCD_IO_MODE 43#if LCD_IO_MODE
45#define lcd_e_delay() _delay_us(LCD_DELAY_ENABLE_PULSE) 44# define lcd_e_delay() _delay_us(LCD_DELAY_ENABLE_PULSE)
46#define lcd_e_high() LCD_E_PORT |= _BV(LCD_E_PIN); 45# define lcd_e_high() LCD_E_PORT |= _BV(LCD_E_PIN);
47#define lcd_e_low() LCD_E_PORT &= ~_BV(LCD_E_PIN); 46# define lcd_e_low() LCD_E_PORT &= ~_BV(LCD_E_PIN);
48#define lcd_e_toggle() toggle_e() 47# define lcd_e_toggle() toggle_e()
49#define lcd_rw_high() LCD_RW_PORT |= _BV(LCD_RW_PIN) 48# define lcd_rw_high() LCD_RW_PORT |= _BV(LCD_RW_PIN)
50#define lcd_rw_low() LCD_RW_PORT &= ~_BV(LCD_RW_PIN) 49# define lcd_rw_low() LCD_RW_PORT &= ~_BV(LCD_RW_PIN)
51#define lcd_rs_high() LCD_RS_PORT |= _BV(LCD_RS_PIN) 50# define lcd_rs_high() LCD_RS_PORT |= _BV(LCD_RS_PIN)
52#define lcd_rs_low() LCD_RS_PORT &= ~_BV(LCD_RS_PIN) 51# define lcd_rs_low() LCD_RS_PORT &= ~_BV(LCD_RS_PIN)
53#endif 52#endif
54 53
55#if LCD_IO_MODE 54#if LCD_IO_MODE
56#if LCD_LINES==1 55# if LCD_LINES == 1
57#define LCD_FUNCTION_DEFAULT LCD_FUNCTION_4BIT_1LINE 56# define LCD_FUNCTION_DEFAULT LCD_FUNCTION_4BIT_1LINE
57# else
58# define LCD_FUNCTION_DEFAULT LCD_FUNCTION_4BIT_2LINES
59# endif
58#else 60#else
59#define LCD_FUNCTION_DEFAULT LCD_FUNCTION_4BIT_2LINES 61# if LCD_LINES == 1
60#endif 62# define LCD_FUNCTION_DEFAULT LCD_FUNCTION_8BIT_1LINE
61#else 63# else
62#if LCD_LINES==1 64# define LCD_FUNCTION_DEFAULT LCD_FUNCTION_8BIT_2LINES
63#define LCD_FUNCTION_DEFAULT LCD_FUNCTION_8BIT_1LINE 65# endif
64#else
65#define LCD_FUNCTION_DEFAULT LCD_FUNCTION_8BIT_2LINES
66#endif
67#endif 66#endif
68 67
69#if LCD_CONTROLLER_KS0073 68#if LCD_CONTROLLER_KS0073
70#if LCD_LINES==4 69# if LCD_LINES == 4
71 70
72#define KS0073_EXTENDED_FUNCTION_REGISTER_ON 0x2C /* |0|010|1100 4-bit mode, extension-bit RE = 1 */ 71# define KS0073_EXTENDED_FUNCTION_REGISTER_ON 0x2C /* |0|010|1100 4-bit mode, extension-bit RE = 1 */
73#define KS0073_EXTENDED_FUNCTION_REGISTER_OFF 0x28 /* |0|010|1000 4-bit mode, extension-bit RE = 0 */ 72# define KS0073_EXTENDED_FUNCTION_REGISTER_OFF 0x28 /* |0|010|1000 4-bit mode, extension-bit RE = 0 */
74#define KS0073_4LINES_MODE 0x09 /* |0|000|1001 4 lines mode */ 73# define KS0073_4LINES_MODE 0x09 /* |0|000|1001 4 lines mode */
75 74
76#endif 75# endif
77#endif 76#endif
78 77
79/* 78/*
80** function prototypes 79** function prototypes
81*/ 80*/
82#if LCD_IO_MODE 81#if LCD_IO_MODE
83static void toggle_e(void); 82static void toggle_e(void);
@@ -87,93 +86,83 @@ static void toggle_e(void);
87** local functions 86** local functions
88*/ 87*/
89 88
90 89/*************************************************************************
91/*************************************************************************
92delay for a minimum of <us> microseconds 90delay for a minimum of <us> microseconds
93the number of loops is calculated at compile-time from MCU clock frequency 91the number of loops is calculated at compile-time from MCU clock frequency
94*************************************************************************/ 92*************************************************************************/
95#define delay(us) _delay_us(us) 93#define delay(us) _delay_us(us)
96
97 94
98#if LCD_IO_MODE 95#if LCD_IO_MODE
99/* toggle Enable Pin to initiate write */ 96/* toggle Enable Pin to initiate write */
100static void toggle_e(void) 97static void toggle_e(void) {
101{
102 lcd_e_high(); 98 lcd_e_high();
103 lcd_e_delay(); 99 lcd_e_delay();
104 lcd_e_low(); 100 lcd_e_low();
105} 101}
106#endif 102#endif
107 103
108
109/************************************************************************* 104/*************************************************************************
110Low-level function to write byte to LCD controller 105Low-level function to write byte to LCD controller
111Input: data byte to write to LCD 106Input: data byte to write to LCD
112 rs 1: write data 107 rs 1: write data
113 0: write instruction 108 0: write instruction
114Returns: none 109Returns: none
115*************************************************************************/ 110*************************************************************************/
116#if LCD_IO_MODE 111#if LCD_IO_MODE
117static void lcd_write(uint8_t data,uint8_t rs) 112static void lcd_write(uint8_t data, uint8_t rs) {
118{ 113 unsigned char dataBits;
119 unsigned char dataBits ;
120
121 114
122 if (rs) { /* write data (RS=1, RW=0) */ 115 if (rs) { /* write data (RS=1, RW=0) */
123 lcd_rs_high(); 116 lcd_rs_high();
124 } else { /* write instruction (RS=0, RW=0) */ 117 } else { /* write instruction (RS=0, RW=0) */
125 lcd_rs_low(); 118 lcd_rs_low();
126 } 119 }
127 lcd_rw_low(); /* RW=0 write mode */ 120 lcd_rw_low(); /* RW=0 write mode */
128 121
129 if ( ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT == &LCD_DATA3_PORT ) 122 if ((&LCD_DATA0_PORT == &LCD_DATA1_PORT) && (&LCD_DATA1_PORT == &LCD_DATA2_PORT) && (&LCD_DATA2_PORT == &LCD_DATA3_PORT) && (LCD_DATA0_PIN == 0) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3)) {
130 && (LCD_DATA0_PIN == 0) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) )
131 {
132 /* configure data pins as output */ 123 /* configure data pins as output */
133 DDR(LCD_DATA0_PORT) |= 0x0F; 124 DDR(LCD_DATA0_PORT) |= 0x0F;
134 125
135 /* output high nibble first */ 126 /* output high nibble first */
136 dataBits = LCD_DATA0_PORT & 0xF0; 127 dataBits = LCD_DATA0_PORT & 0xF0;
137 LCD_DATA0_PORT = dataBits |((data>>4)&0x0F); 128 LCD_DATA0_PORT = dataBits | ((data >> 4) & 0x0F);
138 lcd_e_toggle(); 129 lcd_e_toggle();
139 130
140 /* output low nibble */ 131 /* output low nibble */
141 LCD_DATA0_PORT = dataBits | (data&0x0F); 132 LCD_DATA0_PORT = dataBits | (data & 0x0F);
142 lcd_e_toggle(); 133 lcd_e_toggle();
143 134
144 /* all data pins high (inactive) */ 135 /* all data pins high (inactive) */
145 LCD_DATA0_PORT = dataBits | 0x0F; 136 LCD_DATA0_PORT = dataBits | 0x0F;
146 } 137 } else {
147 else
148 {
149 /* configure data pins as output */ 138 /* configure data pins as output */
150 DDR(LCD_DATA0_PORT) |= _BV(LCD_DATA0_PIN); 139 DDR(LCD_DATA0_PORT) |= _BV(LCD_DATA0_PIN);
151 DDR(LCD_DATA1_PORT) |= _BV(LCD_DATA1_PIN); 140 DDR(LCD_DATA1_PORT) |= _BV(LCD_DATA1_PIN);
152 DDR(LCD_DATA2_PORT) |= _BV(LCD_DATA2_PIN); 141 DDR(LCD_DATA2_PORT) |= _BV(LCD_DATA2_PIN);
153 DDR(LCD_DATA3_PORT) |= _BV(LCD_DATA3_PIN); 142 DDR(LCD_DATA3_PORT) |= _BV(LCD_DATA3_PIN);
154 143
155 /* output high nibble first */ 144 /* output high nibble first */
156 LCD_DATA3_PORT &= ~_BV(LCD_DATA3_PIN); 145 LCD_DATA3_PORT &= ~_BV(LCD_DATA3_PIN);
157 LCD_DATA2_PORT &= ~_BV(LCD_DATA2_PIN); 146 LCD_DATA2_PORT &= ~_BV(LCD_DATA2_PIN);
158 LCD_DATA1_PORT &= ~_BV(LCD_DATA1_PIN); 147 LCD_DATA1_PORT &= ~_BV(LCD_DATA1_PIN);
159 LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN); 148 LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN);
160 if(data & 0x80) LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN); 149 if (data & 0x80) LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN);
161 if(data & 0x40) LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN); 150 if (data & 0x40) LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN);
162 if(data & 0x20) LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); 151 if (data & 0x20) LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN);
163 if(data & 0x10) LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); 152 if (data & 0x10) LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN);
164 lcd_e_toggle(); 153 lcd_e_toggle();
165 154
166 /* output low nibble */ 155 /* output low nibble */
167 LCD_DATA3_PORT &= ~_BV(LCD_DATA3_PIN); 156 LCD_DATA3_PORT &= ~_BV(LCD_DATA3_PIN);
168 LCD_DATA2_PORT &= ~_BV(LCD_DATA2_PIN); 157 LCD_DATA2_PORT &= ~_BV(LCD_DATA2_PIN);
169 LCD_DATA1_PORT &= ~_BV(LCD_DATA1_PIN); 158 LCD_DATA1_PORT &= ~_BV(LCD_DATA1_PIN);
170 LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN); 159 LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN);
171 if(data & 0x08) LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN); 160 if (data & 0x08) LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN);
172 if(data & 0x04) LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN); 161 if (data & 0x04) LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN);
173 if(data & 0x02) LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); 162 if (data & 0x02) LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN);
174 if(data & 0x01) LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); 163 if (data & 0x01) LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN);
175 lcd_e_toggle(); 164 lcd_e_toggle();
176 165
177 /* all data pins high (inactive) */ 166 /* all data pins high (inactive) */
178 LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); 167 LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN);
179 LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); 168 LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN);
@@ -182,85 +171,81 @@ static void lcd_write(uint8_t data,uint8_t rs)
182 } 171 }
183} 172}
184#else 173#else
185#define lcd_write(d,rs) if (rs) *(volatile uint8_t*)(LCD_IO_DATA) = d; else *(volatile uint8_t*)(LCD_IO_FUNCTION) = d; 174# define lcd_write(d, rs) \
175 if (rs) \
176 *(volatile uint8_t *)(LCD_IO_DATA) = d; \
177 else \
178 *(volatile uint8_t *)(LCD_IO_FUNCTION) = d;
186/* rs==0 -> write instruction to LCD_IO_FUNCTION */ 179/* rs==0 -> write instruction to LCD_IO_FUNCTION */
187/* rs==1 -> write data to LCD_IO_DATA */ 180/* rs==1 -> write data to LCD_IO_DATA */
188#endif 181#endif
189 182
190
191/************************************************************************* 183/*************************************************************************
192Low-level function to read byte from LCD controller 184Low-level function to read byte from LCD controller
193Input: rs 1: read data 185Input: rs 1: read data
194 0: read busy flag / address counter 186 0: read busy flag / address counter
195Returns: byte read from LCD controller 187Returns: byte read from LCD controller
196*************************************************************************/ 188*************************************************************************/
197#if LCD_IO_MODE 189#if LCD_IO_MODE
198static uint8_t lcd_read(uint8_t rs) 190static uint8_t lcd_read(uint8_t rs) {
199{
200 uint8_t data; 191 uint8_t data;
201 192
202
203 if (rs) 193 if (rs)
204 lcd_rs_high(); /* RS=1: read data */ 194 lcd_rs_high(); /* RS=1: read data */
205 else 195 else
206 lcd_rs_low(); /* RS=0: read busy flag */ 196 lcd_rs_low(); /* RS=0: read busy flag */
207 lcd_rw_high(); /* RW=1 read mode */ 197 lcd_rw_high(); /* RW=1 read mode */
208 198
209 if ( ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT == &LCD_DATA3_PORT ) 199 if ((&LCD_DATA0_PORT == &LCD_DATA1_PORT) && (&LCD_DATA1_PORT == &LCD_DATA2_PORT) && (&LCD_DATA2_PORT == &LCD_DATA3_PORT) && (LCD_DATA0_PIN == 0) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3)) {
210 && ( LCD_DATA0_PIN == 0 )&& (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) ) 200 DDR(LCD_DATA0_PORT) &= 0xF0; /* configure data pins as input */
211 { 201
212 DDR(LCD_DATA0_PORT) &= 0xF0; /* configure data pins as input */
213
214 lcd_e_high(); 202 lcd_e_high();
215 lcd_e_delay(); 203 lcd_e_delay();
216 data = PIN(LCD_DATA0_PORT) << 4; /* read high nibble first */ 204 data = PIN(LCD_DATA0_PORT) << 4; /* read high nibble first */
217 lcd_e_low(); 205 lcd_e_low();
218 206
219 lcd_e_delay(); /* Enable 500ns low */ 207 lcd_e_delay(); /* Enable 500ns low */
220 208
221 lcd_e_high(); 209 lcd_e_high();
222 lcd_e_delay(); 210 lcd_e_delay();
223 data |= PIN(LCD_DATA0_PORT)&0x0F; /* read low nibble */ 211 data |= PIN(LCD_DATA0_PORT) & 0x0F; /* read low nibble */
224 lcd_e_low(); 212 lcd_e_low();
225 } 213 } else {
226 else
227 {
228 /* configure data pins as input */ 214 /* configure data pins as input */
229 DDR(LCD_DATA0_PORT) &= ~_BV(LCD_DATA0_PIN); 215 DDR(LCD_DATA0_PORT) &= ~_BV(LCD_DATA0_PIN);
230 DDR(LCD_DATA1_PORT) &= ~_BV(LCD_DATA1_PIN); 216 DDR(LCD_DATA1_PORT) &= ~_BV(LCD_DATA1_PIN);
231 DDR(LCD_DATA2_PORT) &= ~_BV(LCD_DATA2_PIN); 217 DDR(LCD_DATA2_PORT) &= ~_BV(LCD_DATA2_PIN);
232 DDR(LCD_DATA3_PORT) &= ~_BV(LCD_DATA3_PIN); 218 DDR(LCD_DATA3_PORT) &= ~_BV(LCD_DATA3_PIN);
233 219
234 /* read high nibble first */ 220 /* read high nibble first */
235 lcd_e_high(); 221 lcd_e_high();
236 lcd_e_delay(); 222 lcd_e_delay();
237 data = 0; 223 data = 0;
238 if ( PIN(LCD_DATA0_PORT) & _BV(LCD_DATA0_PIN) ) data |= 0x10; 224 if (PIN(LCD_DATA0_PORT) & _BV(LCD_DATA0_PIN)) data |= 0x10;
239 if ( PIN(LCD_DATA1_PORT) & _BV(LCD_DATA1_PIN) ) data |= 0x20; 225 if (PIN(LCD_DATA1_PORT) & _BV(LCD_DATA1_PIN)) data |= 0x20;
240 if ( PIN(LCD_DATA2_PORT) & _BV(LCD_DATA2_PIN) ) data |= 0x40; 226 if (PIN(LCD_DATA2_PORT) & _BV(LCD_DATA2_PIN)) data |= 0x40;
241 if ( PIN(LCD_DATA3_PORT) & _BV(LCD_DATA3_PIN) ) data |= 0x80; 227 if (PIN(LCD_DATA3_PORT) & _BV(LCD_DATA3_PIN)) data |= 0x80;
242 lcd_e_low(); 228 lcd_e_low();
243 229
244 lcd_e_delay(); /* Enable 500ns low */ 230 lcd_e_delay(); /* Enable 500ns low */
245 231
246 /* read low nibble */ 232 /* read low nibble */
247 lcd_e_high(); 233 lcd_e_high();
248 lcd_e_delay(); 234 lcd_e_delay();
249 if ( PIN(LCD_DATA0_PORT) & _BV(LCD_DATA0_PIN) ) data |= 0x01; 235 if (PIN(LCD_DATA0_PORT) & _BV(LCD_DATA0_PIN)) data |= 0x01;
250 if ( PIN(LCD_DATA1_PORT) & _BV(LCD_DATA1_PIN) ) data |= 0x02; 236 if (PIN(LCD_DATA1_PORT) & _BV(LCD_DATA1_PIN)) data |= 0x02;
251 if ( PIN(LCD_DATA2_PORT) & _BV(LCD_DATA2_PIN) ) data |= 0x04; 237 if (PIN(LCD_DATA2_PORT) & _BV(LCD_DATA2_PIN)) data |= 0x04;
252 if ( PIN(LCD_DATA3_PORT) & _BV(LCD_DATA3_PIN) ) data |= 0x08; 238 if (PIN(LCD_DATA3_PORT) & _BV(LCD_DATA3_PIN)) data |= 0x08;
253 lcd_e_low(); 239 lcd_e_low();
254 } 240 }
255 return data; 241 return data;
256} 242}
257#else 243#else
258#define lcd_read(rs) (rs) ? *(volatile uint8_t*)(LCD_IO_DATA+LCD_IO_READ) : *(volatile uint8_t*)(LCD_IO_FUNCTION+LCD_IO_READ) 244# define lcd_read(rs) (rs) ? *(volatile uint8_t *)(LCD_IO_DATA + LCD_IO_READ) : *(volatile uint8_t *)(LCD_IO_FUNCTION + LCD_IO_READ)
259/* rs==0 -> read instruction from LCD_IO_FUNCTION */ 245/* rs==0 -> read instruction from LCD_IO_FUNCTION */
260/* rs==1 -> read data from LCD_IO_DATA */ 246/* rs==1 -> read data from LCD_IO_DATA */
261#endif 247#endif
262 248
263
264/************************************************************************* 249/*************************************************************************
265loops while lcd is busy, returns address counter 250loops while lcd is busy, returns address counter
266*************************************************************************/ 251*************************************************************************/
@@ -268,65 +253,62 @@ static uint8_t lcd_waitbusy(void)
268 253
269{ 254{
270 register uint8_t c; 255 register uint8_t c;
271 256
272 /* wait until busy flag is cleared */ 257 /* wait until busy flag is cleared */
273 while ( (c=lcd_read(0)) & (1<<LCD_BUSY)) {} 258 while ((c = lcd_read(0)) & (1 << LCD_BUSY)) {
274 259 }
260
275 /* the address counter is updated 4us after the busy flag is cleared */ 261 /* the address counter is updated 4us after the busy flag is cleared */
276 delay(LCD_DELAY_BUSY_FLAG); 262 delay(LCD_DELAY_BUSY_FLAG);
277 263
278 /* now read the address counter */ 264 /* now read the address counter */
279 return (lcd_read(0)); // return address counter 265 return (lcd_read(0)); // return address counter
280
281}/* lcd_waitbusy */
282 266
267} /* lcd_waitbusy */
283 268
284/************************************************************************* 269/*************************************************************************
285Move cursor to the start of next line or to the first line if the cursor 270Move cursor to the start of next line or to the first line if the cursor
286is already on the last line. 271is already on the last line.
287*************************************************************************/ 272*************************************************************************/
288static inline void lcd_newline(uint8_t pos) 273static inline void lcd_newline(uint8_t pos) {
289{
290 register uint8_t addressCounter; 274 register uint8_t addressCounter;
291 275
292 276#if LCD_LINES == 1
293#if LCD_LINES==1
294 addressCounter = 0; 277 addressCounter = 0;
295#endif 278#endif
296#if LCD_LINES==2 279#if LCD_LINES == 2
297 if ( pos < (LCD_START_LINE2) ) 280 if (pos < (LCD_START_LINE2))
298 addressCounter = LCD_START_LINE2; 281 addressCounter = LCD_START_LINE2;
299 else 282 else
300 addressCounter = LCD_START_LINE1; 283 addressCounter = LCD_START_LINE1;
301#endif 284#endif
302#if LCD_LINES==4 285#if LCD_LINES == 4
303#if KS0073_4LINES_MODE 286# if KS0073_4LINES_MODE
304 if ( pos < LCD_START_LINE2 ) 287 if (pos < LCD_START_LINE2)
305 addressCounter = LCD_START_LINE2; 288 addressCounter = LCD_START_LINE2;
306 else if ( (pos >= LCD_START_LINE2) && (pos < LCD_START_LINE3) ) 289 else if ((pos >= LCD_START_LINE2) && (pos < LCD_START_LINE3))
307 addressCounter = LCD_START_LINE3; 290 addressCounter = LCD_START_LINE3;
308 else if ( (pos >= LCD_START_LINE3) && (pos < LCD_START_LINE4) ) 291 else if ((pos >= LCD_START_LINE3) && (pos < LCD_START_LINE4))
309 addressCounter = LCD_START_LINE4; 292 addressCounter = LCD_START_LINE4;
310 else 293 else
311 addressCounter = LCD_START_LINE1; 294 addressCounter = LCD_START_LINE1;
312#else 295# else
313 if ( pos < LCD_START_LINE3 ) 296 if (pos < LCD_START_LINE3)
314 addressCounter = LCD_START_LINE2; 297 addressCounter = LCD_START_LINE2;
315 else if ( (pos >= LCD_START_LINE2) && (pos < LCD_START_LINE4) ) 298 else if ((pos >= LCD_START_LINE2) && (pos < LCD_START_LINE4))
316 addressCounter = LCD_START_LINE3; 299 addressCounter = LCD_START_LINE3;
317 else if ( (pos >= LCD_START_LINE3) && (pos < LCD_START_LINE2) ) 300 else if ((pos >= LCD_START_LINE3) && (pos < LCD_START_LINE2))
318 addressCounter = LCD_START_LINE4; 301 addressCounter = LCD_START_LINE4;
319 else 302 else
320 addressCounter = LCD_START_LINE1; 303 addressCounter = LCD_START_LINE1;
304# endif
321#endif 305#endif
322#endif 306 lcd_command((1 << LCD_DDRAM) + addressCounter);
323 lcd_command((1<<LCD_DDRAM)+addressCounter);
324
325}/* lcd_newline */
326 307
308} /* lcd_newline */
327 309
328/* 310/*
329** PUBLIC FUNCTIONS 311** PUBLIC FUNCTIONS
330*/ 312*/
331 313
332/************************************************************************* 314/*************************************************************************
@@ -334,132 +316,107 @@ Send LCD controller instruction command
334Input: instruction to send to LCD controller, see HD44780 data sheet 316Input: instruction to send to LCD controller, see HD44780 data sheet
335Returns: none 317Returns: none
336*************************************************************************/ 318*************************************************************************/
337void lcd_command(uint8_t cmd) 319void lcd_command(uint8_t cmd) {
338{
339 lcd_waitbusy(); 320 lcd_waitbusy();
340 lcd_write(cmd,0); 321 lcd_write(cmd, 0);
341} 322}
342 323
343
344/************************************************************************* 324/*************************************************************************
345Send data byte to LCD controller 325Send data byte to LCD controller
346Input: data to send to LCD controller, see HD44780 data sheet 326Input: data to send to LCD controller, see HD44780 data sheet
347Returns: none 327Returns: none
348*************************************************************************/ 328*************************************************************************/
349void lcd_data(uint8_t data) 329void lcd_data(uint8_t data) {
350{
351 lcd_waitbusy(); 330 lcd_waitbusy();
352 lcd_write(data,1); 331 lcd_write(data, 1);
353} 332}
354 333
355
356
357/************************************************************************* 334/*************************************************************************
358Set cursor to specified position 335Set cursor to specified position
359Input: x horizontal position (0: left most position) 336Input: x horizontal position (0: left most position)
360 y vertical position (0: first line) 337 y vertical position (0: first line)
361Returns: none 338Returns: none
362*************************************************************************/ 339*************************************************************************/
363void lcd_gotoxy(uint8_t x, uint8_t y) 340void lcd_gotoxy(uint8_t x, uint8_t y) {
364{ 341#if LCD_LINES == 1
365#if LCD_LINES==1 342 lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x);
366 lcd_command((1<<LCD_DDRAM)+LCD_START_LINE1+x);
367#endif 343#endif
368#if LCD_LINES==2 344#if LCD_LINES == 2
369 if ( y==0 ) 345 if (y == 0)
370 lcd_command((1<<LCD_DDRAM)+LCD_START_LINE1+x); 346 lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x);
371 else 347 else
372 lcd_command((1<<LCD_DDRAM)+LCD_START_LINE2+x); 348 lcd_command((1 << LCD_DDRAM) + LCD_START_LINE2 + x);
373#endif 349#endif
374#if LCD_LINES==4 350#if LCD_LINES == 4
375 if ( y==0 ) 351 if (y == 0)
376 lcd_command((1<<LCD_DDRAM)+LCD_START_LINE1+x); 352 lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x);
377 else if ( y==1) 353 else if (y == 1)
378 lcd_command((1<<LCD_DDRAM)+LCD_START_LINE2+x); 354 lcd_command((1 << LCD_DDRAM) + LCD_START_LINE2 + x);
379 else if ( y==2) 355 else if (y == 2)
380 lcd_command((1<<LCD_DDRAM)+LCD_START_LINE3+x); 356 lcd_command((1 << LCD_DDRAM) + LCD_START_LINE3 + x);
381 else /* y==3 */ 357 else /* y==3 */
382 lcd_command((1<<LCD_DDRAM)+LCD_START_LINE4+x); 358 lcd_command((1 << LCD_DDRAM) + LCD_START_LINE4 + x);
383#endif 359#endif
384 360
385}/* lcd_gotoxy */ 361} /* lcd_gotoxy */
386
387 362
388/************************************************************************* 363/*************************************************************************
389*************************************************************************/ 364*************************************************************************/
390int lcd_getxy(void) 365int lcd_getxy(void) { return lcd_waitbusy(); }
391{
392 return lcd_waitbusy();
393}
394
395 366
396/************************************************************************* 367/*************************************************************************
397Clear display and set cursor to home position 368Clear display and set cursor to home position
398*************************************************************************/ 369*************************************************************************/
399void lcd_clrscr(void) 370void lcd_clrscr(void) { lcd_command(1 << LCD_CLR); }
400{
401 lcd_command(1<<LCD_CLR);
402}
403
404 371
405/************************************************************************* 372/*************************************************************************
406Set cursor to home position 373Set cursor to home position
407*************************************************************************/ 374*************************************************************************/
408void lcd_home(void) 375void lcd_home(void) { lcd_command(1 << LCD_HOME); }
409{
410 lcd_command(1<<LCD_HOME);
411}
412
413 376
414/************************************************************************* 377/*************************************************************************
415Display character at current cursor position 378Display character at current cursor position
416Input: character to be displayed 379Input: character to be displayed
417Returns: none 380Returns: none
418*************************************************************************/ 381*************************************************************************/
419void lcd_putc(char c) 382void lcd_putc(char c) {
420{
421 uint8_t pos; 383 uint8_t pos;
422 384
423 385 pos = lcd_waitbusy(); // read busy-flag and address counter
424 pos = lcd_waitbusy(); // read busy-flag and address counter 386 if (c == '\n') {
425 if (c=='\n')
426 {
427 lcd_newline(pos); 387 lcd_newline(pos);
428 } 388 } else {
429 else 389#if LCD_WRAP_LINES == 1
430 { 390# if LCD_LINES == 1
431#if LCD_WRAP_LINES==1 391 if (pos == LCD_START_LINE1 + LCD_DISP_LENGTH) {
432#if LCD_LINES==1 392 lcd_write((1 << LCD_DDRAM) + LCD_START_LINE1, 0);
433 if ( pos == LCD_START_LINE1+LCD_DISP_LENGTH ) {
434 lcd_write((1<<LCD_DDRAM)+LCD_START_LINE1,0);
435 } 393 }
436#elif LCD_LINES==2 394# elif LCD_LINES == 2
437 if ( pos == LCD_START_LINE1+LCD_DISP_LENGTH ) { 395 if (pos == LCD_START_LINE1 + LCD_DISP_LENGTH) {
438 lcd_write((1<<LCD_DDRAM)+LCD_START_LINE2,0); 396 lcd_write((1 << LCD_DDRAM) + LCD_START_LINE2, 0);
439 }else if ( pos == LCD_START_LINE2+LCD_DISP_LENGTH ){ 397 } else if (pos == LCD_START_LINE2 + LCD_DISP_LENGTH) {
440 lcd_write((1<<LCD_DDRAM)+LCD_START_LINE1,0); 398 lcd_write((1 << LCD_DDRAM) + LCD_START_LINE1, 0);
441 } 399 }
442#elif LCD_LINES==4 400# elif LCD_LINES == 4
443 if ( pos == LCD_START_LINE1+LCD_DISP_LENGTH ) { 401 if (pos == LCD_START_LINE1 + LCD_DISP_LENGTH) {
444 lcd_write((1<<LCD_DDRAM)+LCD_START_LINE2,0); 402 lcd_write((1 << LCD_DDRAM) + LCD_START_LINE2, 0);
445 }else if ( pos == LCD_START_LINE2+LCD_DISP_LENGTH ) { 403 } else if (pos == LCD_START_LINE2 + LCD_DISP_LENGTH) {
446 lcd_write((1<<LCD_DDRAM)+LCD_START_LINE3,0); 404 lcd_write((1 << LCD_DDRAM) + LCD_START_LINE3, 0);
447 }else if ( pos == LCD_START_LINE3+LCD_DISP_LENGTH ) { 405 } else if (pos == LCD_START_LINE3 + LCD_DISP_LENGTH) {
448 lcd_write((1<<LCD_DDRAM)+LCD_START_LINE4,0); 406 lcd_write((1 << LCD_DDRAM) + LCD_START_LINE4, 0);
449 }else if ( pos == LCD_START_LINE4+LCD_DISP_LENGTH ) { 407 } else if (pos == LCD_START_LINE4 + LCD_DISP_LENGTH) {
450 lcd_write((1<<LCD_DDRAM)+LCD_START_LINE1,0); 408 lcd_write((1 << LCD_DDRAM) + LCD_START_LINE1, 0);
451 } 409 }
452#endif 410# endif
453 lcd_waitbusy(); 411 lcd_waitbusy();
454#endif 412#endif
455 lcd_write(c, 1); 413 lcd_write(c, 1);
456 } 414 }
457 415
458}/* lcd_putc */ 416} /* lcd_putc */
459
460 417
461/************************************************************************* 418/*************************************************************************
462Display string without auto linefeed 419Display string without auto linefeed
463Input: string to be displayed 420Input: string to be displayed
464Returns: none 421Returns: none
465*************************************************************************/ 422*************************************************************************/
@@ -468,16 +425,15 @@ void lcd_puts(const char *s)
468{ 425{
469 register char c; 426 register char c;
470 427
471 while ( (c = *s++) ) { 428 while ((c = *s++)) {
472 lcd_putc(c); 429 lcd_putc(c);
473 } 430 }
474 431
475}/* lcd_puts */ 432} /* lcd_puts */
476
477 433
478/************************************************************************* 434/*************************************************************************
479Display string from program memory without auto linefeed 435Display string from program memory without auto linefeed
480Input: string from program memory be be displayed 436Input: string from program memory be be displayed
481Returns: none 437Returns: none
482*************************************************************************/ 438*************************************************************************/
483void lcd_puts_p(const char *progmem_s) 439void lcd_puts_p(const char *progmem_s)
@@ -485,108 +441,96 @@ void lcd_puts_p(const char *progmem_s)
485{ 441{
486 register char c; 442 register char c;
487 443
488 while ( (c = pgm_read_byte(progmem_s++)) ) { 444 while ((c = pgm_read_byte(progmem_s++))) {
489 lcd_putc(c); 445 lcd_putc(c);
490 } 446 }
491 447
492}/* lcd_puts_p */ 448} /* lcd_puts_p */
493
494 449
495/************************************************************************* 450/*************************************************************************
496Initialize display and select type of cursor 451Initialize display and select type of cursor
497Input: dispAttr LCD_DISP_OFF display off 452Input: dispAttr LCD_DISP_OFF display off
498 LCD_DISP_ON display on, cursor off 453 LCD_DISP_ON display on, cursor off
499 LCD_DISP_ON_CURSOR display on, cursor on 454 LCD_DISP_ON_CURSOR display on, cursor on
500 LCD_DISP_CURSOR_BLINK display on, cursor on flashing 455 LCD_DISP_CURSOR_BLINK display on, cursor on flashing
501Returns: none 456Returns: none
502*************************************************************************/ 457*************************************************************************/
503void lcd_init(uint8_t dispAttr) 458void lcd_init(uint8_t dispAttr) {
504{
505#if LCD_IO_MODE 459#if LCD_IO_MODE
506 /* 460 /*
507 * Initialize LCD to 4 bit I/O mode 461 * Initialize LCD to 4 bit I/O mode
508 */ 462 */
509 463
510 if ( ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT == &LCD_DATA3_PORT ) 464 if ((&LCD_DATA0_PORT == &LCD_DATA1_PORT) && (&LCD_DATA1_PORT == &LCD_DATA2_PORT) && (&LCD_DATA2_PORT == &LCD_DATA3_PORT) && (&LCD_RS_PORT == &LCD_DATA0_PORT) && (&LCD_RW_PORT == &LCD_DATA0_PORT) && (&LCD_E_PORT == &LCD_DATA0_PORT) && (LCD_DATA0_PIN == 0) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) && (LCD_RS_PIN == 4) && (LCD_RW_PIN == 5) && (LCD_E_PIN == 6)) {
511 && ( &LCD_RS_PORT == &LCD_DATA0_PORT) && ( &LCD_RW_PORT == &LCD_DATA0_PORT) && (&LCD_E_PORT == &LCD_DATA0_PORT)
512 && (LCD_DATA0_PIN == 0 ) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3)
513 && (LCD_RS_PIN == 4 ) && (LCD_RW_PIN == 5) && (LCD_E_PIN == 6 ) )
514 {
515 /* configure all port bits as output (all LCD lines on same port) */ 465 /* configure all port bits as output (all LCD lines on same port) */
516 DDR(LCD_DATA0_PORT) |= 0x7F; 466 DDR(LCD_DATA0_PORT) |= 0x7F;
517 } 467 } else if ((&LCD_DATA0_PORT == &LCD_DATA1_PORT) && (&LCD_DATA1_PORT == &LCD_DATA2_PORT) && (&LCD_DATA2_PORT == &LCD_DATA3_PORT) && (LCD_DATA0_PIN == 0) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3)) {
518 else if ( ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT == &LCD_DATA3_PORT )
519 && (LCD_DATA0_PIN == 0 ) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) )
520 {
521 /* configure all port bits as output (all LCD data lines on same port, but control lines on different ports) */ 468 /* configure all port bits as output (all LCD data lines on same port, but control lines on different ports) */
522 DDR(LCD_DATA0_PORT) |= 0x0F; 469 DDR(LCD_DATA0_PORT) |= 0x0F;
523 DDR(LCD_RS_PORT) |= _BV(LCD_RS_PIN); 470 DDR(LCD_RS_PORT) |= _BV(LCD_RS_PIN);
524 DDR(LCD_RW_PORT) |= _BV(LCD_RW_PIN); 471 DDR(LCD_RW_PORT) |= _BV(LCD_RW_PIN);
525 DDR(LCD_E_PORT) |= _BV(LCD_E_PIN); 472 DDR(LCD_E_PORT) |= _BV(LCD_E_PIN);
526 } 473 } else {
527 else
528 {
529 /* configure all port bits as output (LCD data and control lines on different ports */ 474 /* configure all port bits as output (LCD data and control lines on different ports */
530 DDR(LCD_RS_PORT) |= _BV(LCD_RS_PIN); 475 DDR(LCD_RS_PORT) |= _BV(LCD_RS_PIN);
531 DDR(LCD_RW_PORT) |= _BV(LCD_RW_PIN); 476 DDR(LCD_RW_PORT) |= _BV(LCD_RW_PIN);
532 DDR(LCD_E_PORT) |= _BV(LCD_E_PIN); 477 DDR(LCD_E_PORT) |= _BV(LCD_E_PIN);
533 DDR(LCD_DATA0_PORT) |= _BV(LCD_DATA0_PIN); 478 DDR(LCD_DATA0_PORT) |= _BV(LCD_DATA0_PIN);
534 DDR(LCD_DATA1_PORT) |= _BV(LCD_DATA1_PIN); 479 DDR(LCD_DATA1_PORT) |= _BV(LCD_DATA1_PIN);
535 DDR(LCD_DATA2_PORT) |= _BV(LCD_DATA2_PIN); 480 DDR(LCD_DATA2_PORT) |= _BV(LCD_DATA2_PIN);
536 DDR(LCD_DATA3_PORT) |= _BV(LCD_DATA3_PIN); 481 DDR(LCD_DATA3_PORT) |= _BV(LCD_DATA3_PIN);
537 } 482 }
538 delay(LCD_DELAY_BOOTUP); /* wait 16ms or more after power-on */ 483 delay(LCD_DELAY_BOOTUP); /* wait 16ms or more after power-on */
539 484
540 /* initial write to lcd is 8bit */ 485 /* initial write to lcd is 8bit */
541 LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); // LCD_FUNCTION>>4; 486 LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); // LCD_FUNCTION>>4;
542 LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); // LCD_FUNCTION_8BIT>>4; 487 LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); // LCD_FUNCTION_8BIT>>4;
488 lcd_e_toggle();
489 delay(LCD_DELAY_INIT); /* delay, busy flag can't be checked here */
490
491 /* repeat last command */
543 lcd_e_toggle(); 492 lcd_e_toggle();
544 delay(LCD_DELAY_INIT); /* delay, busy flag can't be checked here */ 493 delay(LCD_DELAY_INIT_REP); /* delay, busy flag can't be checked here */
545 494
546 /* repeat last command */
547 lcd_e_toggle();
548 delay(LCD_DELAY_INIT_REP); /* delay, busy flag can't be checked here */
549
550 /* repeat last command a third time */ 495 /* repeat last command a third time */
551 lcd_e_toggle(); 496 lcd_e_toggle();
552 delay(LCD_DELAY_INIT_REP); /* delay, busy flag can't be checked here */ 497 delay(LCD_DELAY_INIT_REP); /* delay, busy flag can't be checked here */
553 498
554 /* now configure for 4bit mode */ 499 /* now configure for 4bit mode */
555 LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN); // LCD_FUNCTION_4BIT_1LINE>>4 500 LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN); // LCD_FUNCTION_4BIT_1LINE>>4
556 lcd_e_toggle(); 501 lcd_e_toggle();
557 delay(LCD_DELAY_INIT_4BIT); /* some displays need this additional delay */ 502 delay(LCD_DELAY_INIT_4BIT); /* some displays need this additional delay */
558 503
559 /* from now the LCD only accepts 4 bit I/O, we can use lcd_command() */ 504 /* from now the LCD only accepts 4 bit I/O, we can use lcd_command() */
560#else 505#else
561 /* 506 /*
562 * Initialize LCD to 8 bit memory mapped mode 507 * Initialize LCD to 8 bit memory mapped mode
563 */ 508 */
564 509
565 /* enable external SRAM (memory mapped lcd) and one wait state */ 510 /* enable external SRAM (memory mapped lcd) and one wait state */
566 MCUCR = _BV(SRE) | _BV(SRW); 511 MCUCR = _BV(SRE) | _BV(SRW);
567 512
568 /* reset LCD */ 513 /* reset LCD */
569 delay(LCD_DELAY_BOOTUP); /* wait 16ms after power-on */ 514 delay(LCD_DELAY_BOOTUP); /* wait 16ms after power-on */
570 lcd_write(LCD_FUNCTION_8BIT_1LINE,0); /* function set: 8bit interface */ 515 lcd_write(LCD_FUNCTION_8BIT_1LINE, 0); /* function set: 8bit interface */
571 delay(LCD_DELAY_INIT); /* wait 5ms */ 516 delay(LCD_DELAY_INIT); /* wait 5ms */
572 lcd_write(LCD_FUNCTION_8BIT_1LINE,0); /* function set: 8bit interface */ 517 lcd_write(LCD_FUNCTION_8BIT_1LINE, 0); /* function set: 8bit interface */
573 delay(LCD_DELAY_INIT_REP); /* wait 64us */ 518 delay(LCD_DELAY_INIT_REP); /* wait 64us */
574 lcd_write(LCD_FUNCTION_8BIT_1LINE,0); /* function set: 8bit interface */ 519 lcd_write(LCD_FUNCTION_8BIT_1LINE, 0); /* function set: 8bit interface */
575 delay(LCD_DELAY_INIT_REP); /* wait 64us */ 520 delay(LCD_DELAY_INIT_REP); /* wait 64us */
576#endif 521#endif
577 522
578#if KS0073_4LINES_MODE 523#if KS0073_4LINES_MODE
579 /* Display with KS0073 controller requires special commands for enabling 4 line mode */ 524 /* Display with KS0073 controller requires special commands for enabling 4 line mode */
580 lcd_command(KS0073_EXTENDED_FUNCTION_REGISTER_ON); 525 lcd_command(KS0073_EXTENDED_FUNCTION_REGISTER_ON);
581 lcd_command(KS0073_4LINES_MODE); 526 lcd_command(KS0073_4LINES_MODE);
582 lcd_command(KS0073_EXTENDED_FUNCTION_REGISTER_OFF); 527 lcd_command(KS0073_EXTENDED_FUNCTION_REGISTER_OFF);
583#else 528#else
584 lcd_command(LCD_FUNCTION_DEFAULT); /* function set: display lines */ 529 lcd_command(LCD_FUNCTION_DEFAULT); /* function set: display lines */
585#endif 530#endif
586 lcd_command(LCD_DISP_OFF); /* display off */ 531 lcd_command(LCD_DISP_OFF); /* display off */
587 lcd_clrscr(); /* display clear */ 532 lcd_clrscr(); /* display clear */
588 lcd_command(LCD_MODE_DEFAULT); /* set entry mode */ 533 lcd_command(LCD_MODE_DEFAULT); /* set entry mode */
589 lcd_command(dispAttr); /* display/cursor control */ 534 lcd_command(dispAttr); /* display/cursor control */
590
591}/* lcd_init */
592 535
536} /* lcd_init */
diff --git a/drivers/avr/hd44780.h b/drivers/avr/hd44780.h
index 7421c8131..e60817e98 100644
--- a/drivers/avr/hd44780.h
+++ b/drivers/avr/hd44780.h
@@ -6,7 +6,7 @@
6 License: GNU General Public License Version 3 6 License: GNU General Public License Version 3
7 File: $Id: lcd.h,v 1.14.2.4 2015/01/20 17:16:07 peter Exp $ 7 File: $Id: lcd.h,v 1.14.2.4 2015/01/20 17:16:07 peter Exp $
8 Software: AVR-GCC 4.x 8 Software: AVR-GCC 4.x
9 Hardware: any AVR device, memory mapped mode only for AVR with 9 Hardware: any AVR device, memory mapped mode only for AVR with
10 memory mapped interface (AT90S8515/ATmega8515/ATmega128) 10 memory mapped interface (AT90S8515/ATmega8515/ATmega128)
11***************************************************************************/ 11***************************************************************************/
12 12
@@ -15,333 +15,315 @@
15 Collection of libraries for AVR-GCC 15 Collection of libraries for AVR-GCC
16 @author Peter Fleury pfleury@gmx.ch http://tinyurl.com/peterfleury 16 @author Peter Fleury pfleury@gmx.ch http://tinyurl.com/peterfleury
17 @copyright (C) 2015 Peter Fleury, GNU General Public License Version 3 17 @copyright (C) 2015 Peter Fleury, GNU General Public License Version 3
18 18
19 @file 19 @file
20 @defgroup pfleury_lcd LCD library <lcd.h> 20 @defgroup pfleury_lcd LCD library <lcd.h>
21 @code #include <lcd.h> @endcode 21 @code #include <lcd.h> @endcode
22 22
23 @brief Basic routines for interfacing a HD44780U-based character LCD display 23 @brief Basic routines for interfacing a HD44780U-based character LCD display
24 24
25 LCD character displays can be found in many devices, like espresso machines, laser printers. 25 LCD character displays can be found in many devices, like espresso machines, laser printers.
26 The Hitachi HD44780 controller and its compatible controllers like Samsung KS0066U have become an industry standard for these types of displays. 26 The Hitachi HD44780 controller and its compatible controllers like Samsung KS0066U have become an industry standard for these types of displays.
27 27
28 This library allows easy interfacing with a HD44780 compatible display and can be 28 This library allows easy interfacing with a HD44780 compatible display and can be
29 operated in memory mapped mode (LCD_IO_MODE defined as 0 in the include file lcd.h.) or in 29 operated in memory mapped mode (LCD_IO_MODE defined as 0 in the include file lcd.h.) or in
30 4-bit IO port mode (LCD_IO_MODE defined as 1). 8-bit IO port mode is not supported. 30 4-bit IO port mode (LCD_IO_MODE defined as 1). 8-bit IO port mode is not supported.
31 31
32 Memory mapped mode is compatible with old Kanda STK200 starter kit, but also supports 32 Memory mapped mode is compatible with old Kanda STK200 starter kit, but also supports
33 generation of R/W signal through A8 address line. 33 generation of R/W signal through A8 address line.
34 34
35 @see The chapter <a href=" http://homepage.hispeed.ch/peterfleury/avr-lcd44780.html" target="_blank">Interfacing a HD44780 Based LCD to an AVR</a> 35 @see The chapter <a href=" http://homepage.hispeed.ch/peterfleury/avr-lcd44780.html" target="_blank">Interfacing a HD44780 Based LCD to an AVR</a>
36 on my home page, which shows example circuits how to connect an LCD to an AVR controller. 36 on my home page, which shows example circuits how to connect an LCD to an AVR controller.
37 37
38 @author Peter Fleury pfleury@gmx.ch http://tinyurl.com/peterfleury 38 @author Peter Fleury pfleury@gmx.ch http://tinyurl.com/peterfleury
39 39
40 @version 2.0 40 @version 2.0
41 41
42 @copyright (C) 2015 Peter Fleury, GNU General Public License Version 3 42 @copyright (C) 2015 Peter Fleury, GNU General Public License Version 3
43 43
44*/ 44*/
45 45
46#include <inttypes.h> 46#include <inttypes.h>
47#include <avr/pgmspace.h> 47#include <avr/pgmspace.h>
48 48
49#if (__GNUC__ * 100 + __GNUC_MINOR__) < 405 49#if (__GNUC__ * 100 + __GNUC_MINOR__) < 405
50#error "This library requires AVR-GCC 4.5 or later, update to newer AVR-GCC compiler !" 50# error "This library requires AVR-GCC 4.5 or later, update to newer AVR-GCC compiler !"
51#endif 51#endif
52 52
53
54/**@{*/ 53/**@{*/
55 54
56/* 55/*
57 * LCD and target specific definitions below can be defined in a separate include file with name lcd_definitions.h instead modifying this file 56 * LCD and target specific definitions below can be defined in a separate include file with name lcd_definitions.h instead modifying this file
58 * by adding -D_LCD_DEFINITIONS_FILE to the CDEFS section in the Makefile 57 * by adding -D_LCD_DEFINITIONS_FILE to the CDEFS section in the Makefile
59 * All definitions added to the file lcd_definitions.h will override the default definitions from lcd.h 58 * All definitions added to the file lcd_definitions.h will override the default definitions from lcd.h
60 */ 59 */
61#ifdef _LCD_DEFINITIONS_FILE 60#ifdef _LCD_DEFINITIONS_FILE
62#include "lcd_definitions.h" 61# include "lcd_definitions.h"
63#endif 62#endif
64 63
65
66/** 64/**
67 * @name Definition for LCD controller type 65 * @name Definition for LCD controller type
68 * Use 0 for HD44780 controller, change to 1 for displays with KS0073 controller. 66 * Use 0 for HD44780 controller, change to 1 for displays with KS0073 controller.
69 */ 67 */
70#ifndef LCD_CONTROLLER_KS0073 68#ifndef LCD_CONTROLLER_KS0073
71#define LCD_CONTROLLER_KS0073 0 /**< Use 0 for HD44780 controller, 1 for KS0073 controller */ 69# define LCD_CONTROLLER_KS0073 0 /**< Use 0 for HD44780 controller, 1 for KS0073 controller */
72#endif 70#endif
73 71
74/** 72/**
75 * @name Definitions for Display Size 73 * @name Definitions for Display Size
76 * Change these definitions to adapt setting to your display 74 * Change these definitions to adapt setting to your display
77 * 75 *
78 * These definitions can be defined in a separate include file \b lcd_definitions.h instead modifying this file by 76 * These definitions can be defined in a separate include file \b lcd_definitions.h instead modifying this file by
79 * adding -D_LCD_DEFINITIONS_FILE to the CDEFS section in the Makefile. 77 * adding -D_LCD_DEFINITIONS_FILE to the CDEFS section in the Makefile.
80 * All definitions added to the file lcd_definitions.h will override the default definitions from lcd.h 78 * All definitions added to the file lcd_definitions.h will override the default definitions from lcd.h
81 * 79 *
82 */ 80 */
83#ifndef LCD_LINES 81#ifndef LCD_LINES
84#define LCD_LINES 2 /**< number of visible lines of the display */ 82# define LCD_LINES 2 /**< number of visible lines of the display */
85#endif 83#endif
86#ifndef LCD_DISP_LENGTH 84#ifndef LCD_DISP_LENGTH
87#define LCD_DISP_LENGTH 16 /**< visibles characters per line of the display */ 85# define LCD_DISP_LENGTH 16 /**< visibles characters per line of the display */
88#endif 86#endif
89#ifndef LCD_LINE_LENGTH 87#ifndef LCD_LINE_LENGTH
90#define LCD_LINE_LENGTH 0x40 /**< internal line length of the display */ 88# define LCD_LINE_LENGTH 0x40 /**< internal line length of the display */
91#endif 89#endif
92#ifndef LCD_START_LINE1 90#ifndef LCD_START_LINE1
93#define LCD_START_LINE1 0x00 /**< DDRAM address of first char of line 1 */ 91# define LCD_START_LINE1 0x00 /**< DDRAM address of first char of line 1 */
94#endif 92#endif
95#ifndef LCD_START_LINE2 93#ifndef LCD_START_LINE2
96#define LCD_START_LINE2 0x40 /**< DDRAM address of first char of line 2 */ 94# define LCD_START_LINE2 0x40 /**< DDRAM address of first char of line 2 */
97#endif 95#endif
98#ifndef LCD_START_LINE3 96#ifndef LCD_START_LINE3
99#define LCD_START_LINE3 0x14 /**< DDRAM address of first char of line 3 */ 97# define LCD_START_LINE3 0x14 /**< DDRAM address of first char of line 3 */
100#endif 98#endif
101#ifndef LCD_START_LINE4 99#ifndef LCD_START_LINE4
102#define LCD_START_LINE4 0x54 /**< DDRAM address of first char of line 4 */ 100# define LCD_START_LINE4 0x54 /**< DDRAM address of first char of line 4 */
103#endif 101#endif
104#ifndef LCD_WRAP_LINES 102#ifndef LCD_WRAP_LINES
105#define LCD_WRAP_LINES 0 /**< 0: no wrap, 1: wrap at end of visibile line */ 103# define LCD_WRAP_LINES 0 /**< 0: no wrap, 1: wrap at end of visibile line */
106#endif 104#endif
107 105
108
109/** 106/**
110 * @name Definitions for 4-bit IO mode 107 * @name Definitions for 4-bit IO mode
111 * 108 *
112 * The four LCD data lines and the three control lines RS, RW, E can be on the 109 * The four LCD data lines and the three control lines RS, RW, E can be on the
113 * same port or on different ports. 110 * same port or on different ports.
114 * Change LCD_RS_PORT, LCD_RW_PORT, LCD_E_PORT if you want the control lines on 111 * Change LCD_RS_PORT, LCD_RW_PORT, LCD_E_PORT if you want the control lines on
115 * different ports. 112 * different ports.
116 * 113 *
117 * Normally the four data lines should be mapped to bit 0..3 on one port, but it 114 * Normally the four data lines should be mapped to bit 0..3 on one port, but it
118 * is possible to connect these data lines in different order or even on different 115 * is possible to connect these data lines in different order or even on different
119 * ports by adapting the LCD_DATAx_PORT and LCD_DATAx_PIN definitions. 116 * ports by adapting the LCD_DATAx_PORT and LCD_DATAx_PIN definitions.
120 * 117 *
121 * Adjust these definitions to your target.\n 118 * Adjust these definitions to your target.\n
122 * These definitions can be defined in a separate include file \b lcd_definitions.h instead modifying this file by 119 * These definitions can be defined in a separate include file \b lcd_definitions.h instead modifying this file by
123 * adding \b -D_LCD_DEFINITIONS_FILE to the \b CDEFS section in the Makefile. 120 * adding \b -D_LCD_DEFINITIONS_FILE to the \b CDEFS section in the Makefile.
124 * All definitions added to the file lcd_definitions.h will override the default definitions from lcd.h 121 * All definitions added to the file lcd_definitions.h will override the default definitions from lcd.h
125 * 122 *
126 */ 123 */
127#define LCD_IO_MODE 1 /**< 0: memory mapped mode, 1: IO port mode */ 124#define LCD_IO_MODE 1 /**< 0: memory mapped mode, 1: IO port mode */
128 125
129#if LCD_IO_MODE 126#if LCD_IO_MODE
130 127
131#ifndef LCD_PORT 128# ifndef LCD_PORT
132#define LCD_PORT PORTA /**< port for the LCD lines */ 129# define LCD_PORT PORTA /**< port for the LCD lines */
133#endif 130# endif
134#ifndef LCD_DATA0_PORT 131# ifndef LCD_DATA0_PORT
135#define LCD_DATA0_PORT LCD_PORT /**< port for 4bit data bit 0 */ 132# define LCD_DATA0_PORT LCD_PORT /**< port for 4bit data bit 0 */
136#endif 133# endif
137#ifndef LCD_DATA1_PORT 134# ifndef LCD_DATA1_PORT
138#define LCD_DATA1_PORT LCD_PORT /**< port for 4bit data bit 1 */ 135# define LCD_DATA1_PORT LCD_PORT /**< port for 4bit data bit 1 */
139#endif 136# endif
140#ifndef LCD_DATA2_PORT 137# ifndef LCD_DATA2_PORT
141#define LCD_DATA2_PORT LCD_PORT /**< port for 4bit data bit 2 */ 138# define LCD_DATA2_PORT LCD_PORT /**< port for 4bit data bit 2 */
142#endif 139# endif
143#ifndef LCD_DATA3_PORT 140# ifndef LCD_DATA3_PORT
144#define LCD_DATA3_PORT LCD_PORT /**< port for 4bit data bit 3 */ 141# define LCD_DATA3_PORT LCD_PORT /**< port for 4bit data bit 3 */
145#endif 142# endif
146#ifndef LCD_DATA0_PIN 143# ifndef LCD_DATA0_PIN
147#define LCD_DATA0_PIN 4 /**< pin for 4bit data bit 0 */ 144# define LCD_DATA0_PIN 4 /**< pin for 4bit data bit 0 */
148#endif 145# endif
149#ifndef LCD_DATA1_PIN 146# ifndef LCD_DATA1_PIN
150#define LCD_DATA1_PIN 5 /**< pin for 4bit data bit 1 */ 147# define LCD_DATA1_PIN 5 /**< pin for 4bit data bit 1 */
151#endif 148# endif
152#ifndef LCD_DATA2_PIN 149# ifndef LCD_DATA2_PIN
153#define LCD_DATA2_PIN 6 /**< pin for 4bit data bit 2 */ 150# define LCD_DATA2_PIN 6 /**< pin for 4bit data bit 2 */
154#endif 151# endif
155#ifndef LCD_DATA3_PIN 152# ifndef LCD_DATA3_PIN
156#define LCD_DATA3_PIN 7 /**< pin for 4bit data bit 3 */ 153# define LCD_DATA3_PIN 7 /**< pin for 4bit data bit 3 */
157#endif 154# endif
158#ifndef LCD_RS_PORT 155# ifndef LCD_RS_PORT
159#define LCD_RS_PORT LCD_PORT /**< port for RS line */ 156# define LCD_RS_PORT LCD_PORT /**< port for RS line */
160#endif 157# endif
161#ifndef LCD_RS_PIN 158# ifndef LCD_RS_PIN
162#define LCD_RS_PIN 3 /**< pin for RS line */ 159# define LCD_RS_PIN 3 /**< pin for RS line */
163#endif 160# endif
164#ifndef LCD_RW_PORT 161# ifndef LCD_RW_PORT
165#define LCD_RW_PORT LCD_PORT /**< port for RW line */ 162# define LCD_RW_PORT LCD_PORT /**< port for RW line */
166#endif 163# endif
167#ifndef LCD_RW_PIN 164# ifndef LCD_RW_PIN
168#define LCD_RW_PIN 2 /**< pin for RW line */ 165# define LCD_RW_PIN 2 /**< pin for RW line */
169#endif 166# endif
170#ifndef LCD_E_PORT 167# ifndef LCD_E_PORT
171#define LCD_E_PORT LCD_PORT /**< port for Enable line */ 168# define LCD_E_PORT LCD_PORT /**< port for Enable line */
172#endif 169# endif
173#ifndef LCD_E_PIN 170# ifndef LCD_E_PIN
174#define LCD_E_PIN 1 /**< pin for Enable line */ 171# define LCD_E_PIN 1 /**< pin for Enable line */
175#endif 172# endif
176 173
177#elif defined(__AVR_AT90S4414__) || defined(__AVR_AT90S8515__) || defined(__AVR_ATmega64__) || \ 174#elif defined(__AVR_AT90S4414__) || defined(__AVR_AT90S8515__) || defined(__AVR_ATmega64__) || defined(__AVR_ATmega8515__) || defined(__AVR_ATmega103__) || defined(__AVR_ATmega128__) || defined(__AVR_ATmega161__) || defined(__AVR_ATmega162__)
178 defined(__AVR_ATmega8515__)|| defined(__AVR_ATmega103__) || defined(__AVR_ATmega128__) || \
179 defined(__AVR_ATmega161__) || defined(__AVR_ATmega162__)
180/* 175/*
181 * memory mapped mode is only supported when the device has an external data memory interface 176 * memory mapped mode is only supported when the device has an external data memory interface
182 */ 177 */
183#define LCD_IO_DATA 0xC000 /* A15=E=1, A14=RS=1 */ 178# define LCD_IO_DATA 0xC000 /* A15=E=1, A14=RS=1 */
184#define LCD_IO_FUNCTION 0x8000 /* A15=E=1, A14=RS=0 */ 179# define LCD_IO_FUNCTION 0x8000 /* A15=E=1, A14=RS=0 */
185#define LCD_IO_READ 0x0100 /* A8 =R/W=1 (R/W: 1=Read, 0=Write */ 180# define LCD_IO_READ 0x0100 /* A8 =R/W=1 (R/W: 1=Read, 0=Write */
186 181
187#else 182#else
188#error "external data memory interface not available for this device, use 4-bit IO port mode" 183# error "external data memory interface not available for this device, use 4-bit IO port mode"
189 184
190#endif 185#endif
191 186
192
193/** 187/**
194 * @name Definitions of delays 188 * @name Definitions of delays
195 * Used to calculate delay timers. 189 * Used to calculate delay timers.
196 * Adapt the F_CPU define in the Makefile to the clock frequency in Hz of your target 190 * Adapt the F_CPU define in the Makefile to the clock frequency in Hz of your target
197 * 191 *
198 * These delay times can be adjusted, if some displays require different delays.\n 192 * These delay times can be adjusted, if some displays require different delays.\n
199 * These definitions can be defined in a separate include file \b lcd_definitions.h instead modifying this file by 193 * These definitions can be defined in a separate include file \b lcd_definitions.h instead modifying this file by
200 * adding \b -D_LCD_DEFINITIONS_FILE to the \b CDEFS section in the Makefile. 194 * adding \b -D_LCD_DEFINITIONS_FILE to the \b CDEFS section in the Makefile.
201 * All definitions added to the file lcd_definitions.h will override the default definitions from lcd.h 195 * All definitions added to the file lcd_definitions.h will override the default definitions from lcd.h
202 */ 196 */
203#ifndef LCD_DELAY_BOOTUP 197#ifndef LCD_DELAY_BOOTUP
204#define LCD_DELAY_BOOTUP 16000 /**< delay in micro seconds after power-on */ 198# define LCD_DELAY_BOOTUP 16000 /**< delay in micro seconds after power-on */
205#endif 199#endif
206#ifndef LCD_DELAY_INIT 200#ifndef LCD_DELAY_INIT
207#define LCD_DELAY_INIT 5000 /**< delay in micro seconds after initialization command sent */ 201# define LCD_DELAY_INIT 5000 /**< delay in micro seconds after initialization command sent */
208#endif 202#endif
209#ifndef LCD_DELAY_INIT_REP 203#ifndef LCD_DELAY_INIT_REP
210#define LCD_DELAY_INIT_REP 64 /**< delay in micro seconds after initialization command repeated */ 204# define LCD_DELAY_INIT_REP 64 /**< delay in micro seconds after initialization command repeated */
211#endif 205#endif
212#ifndef LCD_DELAY_INIT_4BIT 206#ifndef LCD_DELAY_INIT_4BIT
213#define LCD_DELAY_INIT_4BIT 64 /**< delay in micro seconds after setting 4-bit mode */ 207# define LCD_DELAY_INIT_4BIT 64 /**< delay in micro seconds after setting 4-bit mode */
214#endif 208#endif
215#ifndef LCD_DELAY_BUSY_FLAG 209#ifndef LCD_DELAY_BUSY_FLAG
216#define LCD_DELAY_BUSY_FLAG 4 /**< time in micro seconds the address counter is updated after busy flag is cleared */ 210# define LCD_DELAY_BUSY_FLAG 4 /**< time in micro seconds the address counter is updated after busy flag is cleared */
217#endif 211#endif
218#ifndef LCD_DELAY_ENABLE_PULSE 212#ifndef LCD_DELAY_ENABLE_PULSE
219#define LCD_DELAY_ENABLE_PULSE 1 /**< enable signal pulse width in micro seconds */ 213# define LCD_DELAY_ENABLE_PULSE 1 /**< enable signal pulse width in micro seconds */
220#endif 214#endif
221 215
222
223/** 216/**
224 * @name Definitions for LCD command instructions 217 * @name Definitions for LCD command instructions
225 * The constants define the various LCD controller instructions which can be passed to the 218 * The constants define the various LCD controller instructions which can be passed to the
226 * function lcd_command(), see HD44780 data sheet for a complete description. 219 * function lcd_command(), see HD44780 data sheet for a complete description.
227 */ 220 */
228 221
229/* instruction register bit positions, see HD44780U data sheet */ 222/* instruction register bit positions, see HD44780U data sheet */
230#define LCD_CLR 0 /* DB0: clear display */ 223#define LCD_CLR 0 /* DB0: clear display */
231#define LCD_HOME 1 /* DB1: return to home position */ 224#define LCD_HOME 1 /* DB1: return to home position */
232#define LCD_ENTRY_MODE 2 /* DB2: set entry mode */ 225#define LCD_ENTRY_MODE 2 /* DB2: set entry mode */
233#define LCD_ENTRY_INC 1 /* DB1: 1=increment, 0=decrement */ 226#define LCD_ENTRY_INC 1 /* DB1: 1=increment, 0=decrement */
234#define LCD_ENTRY_SHIFT 0 /* DB2: 1=display shift on */ 227#define LCD_ENTRY_SHIFT 0 /* DB2: 1=display shift on */
235#define LCD_ON 3 /* DB3: turn lcd/cursor on */ 228#define LCD_ON 3 /* DB3: turn lcd/cursor on */
236#define LCD_ON_DISPLAY 2 /* DB2: turn display on */ 229#define LCD_ON_DISPLAY 2 /* DB2: turn display on */
237#define LCD_ON_CURSOR 1 /* DB1: turn cursor on */ 230#define LCD_ON_CURSOR 1 /* DB1: turn cursor on */
238#define LCD_ON_BLINK 0 /* DB0: blinking cursor ? */ 231#define LCD_ON_BLINK 0 /* DB0: blinking cursor ? */
239#define LCD_MOVE 4 /* DB4: move cursor/display */ 232#define LCD_MOVE 4 /* DB4: move cursor/display */
240#define LCD_MOVE_DISP 3 /* DB3: move display (0-> cursor) ? */ 233#define LCD_MOVE_DISP 3 /* DB3: move display (0-> cursor) ? */
241#define LCD_MOVE_RIGHT 2 /* DB2: move right (0-> left) ? */ 234#define LCD_MOVE_RIGHT 2 /* DB2: move right (0-> left) ? */
242#define LCD_FUNCTION 5 /* DB5: function set */ 235#define LCD_FUNCTION 5 /* DB5: function set */
243#define LCD_FUNCTION_8BIT 4 /* DB4: set 8BIT mode (0->4BIT mode) */ 236#define LCD_FUNCTION_8BIT 4 /* DB4: set 8BIT mode (0->4BIT mode) */
244#define LCD_FUNCTION_2LINES 3 /* DB3: two lines (0->one line) */ 237#define LCD_FUNCTION_2LINES 3 /* DB3: two lines (0->one line) */
245#define LCD_FUNCTION_10DOTS 2 /* DB2: 5x10 font (0->5x7 font) */ 238#define LCD_FUNCTION_10DOTS 2 /* DB2: 5x10 font (0->5x7 font) */
246#define LCD_CGRAM 6 /* DB6: set CG RAM address */ 239#define LCD_CGRAM 6 /* DB6: set CG RAM address */
247#define LCD_DDRAM 7 /* DB7: set DD RAM address */ 240#define LCD_DDRAM 7 /* DB7: set DD RAM address */
248#define LCD_BUSY 7 /* DB7: LCD is busy */ 241#define LCD_BUSY 7 /* DB7: LCD is busy */
249 242
250/* set entry mode: display shift on/off, dec/inc cursor move direction */ 243/* set entry mode: display shift on/off, dec/inc cursor move direction */
251#define LCD_ENTRY_DEC 0x04 /* display shift off, dec cursor move dir */ 244#define LCD_ENTRY_DEC 0x04 /* display shift off, dec cursor move dir */
252#define LCD_ENTRY_DEC_SHIFT 0x05 /* display shift on, dec cursor move dir */ 245#define LCD_ENTRY_DEC_SHIFT 0x05 /* display shift on, dec cursor move dir */
253#define LCD_ENTRY_INC_ 0x06 /* display shift off, inc cursor move dir */ 246#define LCD_ENTRY_INC_ 0x06 /* display shift off, inc cursor move dir */
254#define LCD_ENTRY_INC_SHIFT 0x07 /* display shift on, inc cursor move dir */ 247#define LCD_ENTRY_INC_SHIFT 0x07 /* display shift on, inc cursor move dir */
255 248
256/* display on/off, cursor on/off, blinking char at cursor position */ 249/* display on/off, cursor on/off, blinking char at cursor position */
257#define LCD_DISP_OFF 0x08 /* display off */ 250#define LCD_DISP_OFF 0x08 /* display off */
258#define LCD_DISP_ON 0x0C /* display on, cursor off */ 251#define LCD_DISP_ON 0x0C /* display on, cursor off */
259#define LCD_DISP_ON_BLINK 0x0D /* display on, cursor off, blink char */ 252#define LCD_DISP_ON_BLINK 0x0D /* display on, cursor off, blink char */
260#define LCD_DISP_ON_CURSOR 0x0E /* display on, cursor on */ 253#define LCD_DISP_ON_CURSOR 0x0E /* display on, cursor on */
261#define LCD_DISP_ON_CURSOR_BLINK 0x0F /* display on, cursor on, blink char */ 254#define LCD_DISP_ON_CURSOR_BLINK 0x0F /* display on, cursor on, blink char */
262 255
263/* move cursor/shift display */ 256/* move cursor/shift display */
264#define LCD_MOVE_CURSOR_LEFT 0x10 /* move cursor left (decrement) */ 257#define LCD_MOVE_CURSOR_LEFT 0x10 /* move cursor left (decrement) */
265#define LCD_MOVE_CURSOR_RIGHT 0x14 /* move cursor right (increment) */ 258#define LCD_MOVE_CURSOR_RIGHT 0x14 /* move cursor right (increment) */
266#define LCD_MOVE_DISP_LEFT 0x18 /* shift display left */ 259#define LCD_MOVE_DISP_LEFT 0x18 /* shift display left */
267#define LCD_MOVE_DISP_RIGHT 0x1C /* shift display right */ 260#define LCD_MOVE_DISP_RIGHT 0x1C /* shift display right */
268 261
269/* function set: set interface data length and number of display lines */ 262/* function set: set interface data length and number of display lines */
270#define LCD_FUNCTION_4BIT_1LINE 0x20 /* 4-bit interface, single line, 5x7 dots */ 263#define LCD_FUNCTION_4BIT_1LINE 0x20 /* 4-bit interface, single line, 5x7 dots */
271#define LCD_FUNCTION_4BIT_2LINES 0x28 /* 4-bit interface, dual line, 5x7 dots */ 264#define LCD_FUNCTION_4BIT_2LINES 0x28 /* 4-bit interface, dual line, 5x7 dots */
272#define LCD_FUNCTION_8BIT_1LINE 0x30 /* 8-bit interface, single line, 5x7 dots */ 265#define LCD_FUNCTION_8BIT_1LINE 0x30 /* 8-bit interface, single line, 5x7 dots */
273#define LCD_FUNCTION_8BIT_2LINES 0x38 /* 8-bit interface, dual line, 5x7 dots */ 266#define LCD_FUNCTION_8BIT_2LINES 0x38 /* 8-bit interface, dual line, 5x7 dots */
274 267
268#define LCD_MODE_DEFAULT ((1 << LCD_ENTRY_MODE) | (1 << LCD_ENTRY_INC))
275 269
276#define LCD_MODE_DEFAULT ((1<<LCD_ENTRY_MODE) | (1<<LCD_ENTRY_INC) ) 270/**
277
278
279
280/**
281 * @name Functions 271 * @name Functions
282 */ 272 */
283 273
284
285/** 274/**
286 @brief Initialize display and select type of cursor 275 @brief Initialize display and select type of cursor
287 @param dispAttr \b LCD_DISP_OFF display off\n 276 @param dispAttr \b LCD_DISP_OFF display off\n
288 \b LCD_DISP_ON display on, cursor off\n 277 \b LCD_DISP_ON display on, cursor off\n
289 \b LCD_DISP_ON_CURSOR display on, cursor on\n 278 \b LCD_DISP_ON_CURSOR display on, cursor on\n
290 \b LCD_DISP_ON_CURSOR_BLINK display on, cursor on flashing 279 \b LCD_DISP_ON_CURSOR_BLINK display on, cursor on flashing
291 @return none 280 @return none
292*/ 281*/
293extern void lcd_init(uint8_t dispAttr); 282extern void lcd_init(uint8_t dispAttr);
294 283
295
296/** 284/**
297 @brief Clear display and set cursor to home position 285 @brief Clear display and set cursor to home position
298 @return none 286 @return none
299*/ 287*/
300extern void lcd_clrscr(void); 288extern void lcd_clrscr(void);
301 289
302
303/** 290/**
304 @brief Set cursor to home position 291 @brief Set cursor to home position
305 @return none 292 @return none
306*/ 293*/
307extern void lcd_home(void); 294extern void lcd_home(void);
308 295
309
310/** 296/**
311 @brief Set cursor to specified position 297 @brief Set cursor to specified position
312 298
313 @param x horizontal position\n (0: left most position) 299 @param x horizontal position\n (0: left most position)
314 @param y vertical position\n (0: first line) 300 @param y vertical position\n (0: first line)
315 @return none 301 @return none
316*/ 302*/
317extern void lcd_gotoxy(uint8_t x, uint8_t y); 303extern void lcd_gotoxy(uint8_t x, uint8_t y);
318 304
319
320/** 305/**
321 @brief Display character at current cursor position 306 @brief Display character at current cursor position
322 @param c character to be displayed 307 @param c character to be displayed
323 @return none 308 @return none
324*/ 309*/
325extern void lcd_putc(char c); 310extern void lcd_putc(char c);
326 311
327
328/** 312/**
329 @brief Display string without auto linefeed 313 @brief Display string without auto linefeed
330 @param s string to be displayed 314 @param s string to be displayed
331 @return none 315 @return none
332*/ 316*/
333extern void lcd_puts(const char *s); 317extern void lcd_puts(const char *s);
334 318
335
336/** 319/**
337 @brief Display string from program memory without auto linefeed 320 @brief Display string from program memory without auto linefeed
338 @param progmem_s string from program memory be be displayed 321 @param progmem_s string from program memory be be displayed
339 @return none 322 @return none
340 @see lcd_puts_P 323 @see lcd_puts_P
341*/ 324*/
342extern void lcd_puts_p(const char *progmem_s); 325extern void lcd_puts_p(const char *progmem_s);
343 326
344
345/** 327/**
346 @brief Send LCD controller instruction command 328 @brief Send LCD controller instruction command
347 @param cmd instruction to send to LCD controller, see HD44780 data sheet 329 @param cmd instruction to send to LCD controller, see HD44780 data sheet
@@ -349,23 +331,20 @@ extern void lcd_puts_p(const char *progmem_s);
349*/ 331*/
350extern void lcd_command(uint8_t cmd); 332extern void lcd_command(uint8_t cmd);
351 333
352
353/** 334/**
354 @brief Send data byte to LCD controller 335 @brief Send data byte to LCD controller
355 336
356 Similar to lcd_putc(), but without interpreting LF 337 Similar to lcd_putc(), but without interpreting LF
357 @param data byte to send to LCD controller, see HD44780 data sheet 338 @param data byte to send to LCD controller, see HD44780 data sheet
358 @return none 339 @return none
359*/ 340*/
360extern void lcd_data(uint8_t data); 341extern void lcd_data(uint8_t data);
361 342
362
363/** 343/**
364 @brief macros for automatically storing string constant in program memory 344 @brief macros for automatically storing string constant in program memory
365*/ 345*/
366#define lcd_puts_P(__s) lcd_puts_p(PSTR(__s)) 346#define lcd_puts_P(__s) lcd_puts_p(PSTR(__s))
367 347
368/**@}*/ 348/**@}*/
369 349
370#endif //LCD_H 350#endif // LCD_H
371
diff --git a/drivers/avr/i2c_master.c b/drivers/avr/i2c_master.c
index 0acc24642..52924437e 100755..100644
--- a/drivers/avr/i2c_master.c
+++ b/drivers/avr/i2c_master.c
@@ -25,200 +25,200 @@
25#include "wait.h" 25#include "wait.h"
26 26
27#ifndef F_SCL 27#ifndef F_SCL
28# define F_SCL 400000UL // SCL frequency 28# define F_SCL 400000UL // SCL frequency
29#endif 29#endif
30#define Prescaler 1 30#define Prescaler 1
31#define TWBR_val ((((F_CPU / F_SCL) / Prescaler) - 16) / 2) 31#define TWBR_val ((((F_CPU / F_SCL) / Prescaler) - 16) / 2)
32 32
33void i2c_init(void) { 33void i2c_init(void) {
34 TWSR = 0; /* no prescaler */ 34 TWSR = 0; /* no prescaler */
35 TWBR = (uint8_t)TWBR_val; 35 TWBR = (uint8_t)TWBR_val;
36 36
37 #ifdef __AVR_ATmega32A__ 37#ifdef __AVR_ATmega32A__
38 // set pull-up resistors on I2C bus pins 38 // set pull-up resistors on I2C bus pins
39 PORTC |= 0b11; 39 PORTC |= 0b11;
40 40
41 // enable TWI (two-wire interface) 41 // enable TWI (two-wire interface)
42 TWCR |= (1 << TWEN); 42 TWCR |= (1 << TWEN);
43 43
44 // enable TWI interrupt and slave address ACK 44 // enable TWI interrupt and slave address ACK
45 TWCR |= (1 << TWIE); 45 TWCR |= (1 << TWIE);
46 TWCR |= (1 << TWEA); 46 TWCR |= (1 << TWEA);
47 #endif 47#endif
48} 48}
49 49
50i2c_status_t i2c_start(uint8_t address, uint16_t timeout) { 50i2c_status_t i2c_start(uint8_t address, uint16_t timeout) {
51 // reset TWI control register 51 // reset TWI control register
52 TWCR = 0; 52 TWCR = 0;
53 // transmit START condition 53 // transmit START condition
54 TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); 54 TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
55 55
56 uint16_t timeout_timer = timer_read(); 56 uint16_t timeout_timer = timer_read();
57 while (!(TWCR & (1 << TWINT))) { 57 while (!(TWCR & (1 << TWINT))) {
58 if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { 58 if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) {
59 return I2C_STATUS_TIMEOUT; 59 return I2C_STATUS_TIMEOUT;
60 } 60 }
61 } 61 }
62 62
63 // check if the start condition was successfully transmitted 63 // check if the start condition was successfully transmitted
64 if (((TW_STATUS & 0xF8) != TW_START) && ((TW_STATUS & 0xF8) != TW_REP_START)) { 64 if (((TW_STATUS & 0xF8) != TW_START) && ((TW_STATUS & 0xF8) != TW_REP_START)) {
65 return I2C_STATUS_ERROR; 65 return I2C_STATUS_ERROR;
66 } 66 }
67 67
68 // load slave address into data register 68 // load slave address into data register
69 TWDR = address; 69 TWDR = address;
70 // start transmission of address 70 // start transmission of address
71 TWCR = (1 << TWINT) | (1 << TWEN); 71 TWCR = (1 << TWINT) | (1 << TWEN);
72 72
73 timeout_timer = timer_read(); 73 timeout_timer = timer_read();
74 while (!(TWCR & (1 << TWINT))) { 74 while (!(TWCR & (1 << TWINT))) {
75 if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { 75 if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) {
76 return I2C_STATUS_TIMEOUT; 76 return I2C_STATUS_TIMEOUT;
77 } 77 }
78 } 78 }
79 79
80 // check if the device has acknowledged the READ / WRITE mode 80 // check if the device has acknowledged the READ / WRITE mode
81 uint8_t twst = TW_STATUS & 0xF8; 81 uint8_t twst = TW_STATUS & 0xF8;
82 if ((twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK)) { 82 if ((twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK)) {
83 return I2C_STATUS_ERROR; 83 return I2C_STATUS_ERROR;
84 } 84 }
85 85
86 return I2C_STATUS_SUCCESS; 86 return I2C_STATUS_SUCCESS;
87} 87}
88 88
89i2c_status_t i2c_write(uint8_t data, uint16_t timeout) { 89i2c_status_t i2c_write(uint8_t data, uint16_t timeout) {
90 // load data into data register 90 // load data into data register
91 TWDR = data; 91 TWDR = data;
92 // start transmission of data 92 // start transmission of data
93 TWCR = (1 << TWINT) | (1 << TWEN); 93 TWCR = (1 << TWINT) | (1 << TWEN);
94 94
95 uint16_t timeout_timer = timer_read(); 95 uint16_t timeout_timer = timer_read();
96 while (!(TWCR & (1 << TWINT))) { 96 while (!(TWCR & (1 << TWINT))) {
97 if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { 97 if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) {
98 return I2C_STATUS_TIMEOUT; 98 return I2C_STATUS_TIMEOUT;
99 }
99 } 100 }
100 }
101 101
102 if ((TW_STATUS & 0xF8) != TW_MT_DATA_ACK) { 102 if ((TW_STATUS & 0xF8) != TW_MT_DATA_ACK) {
103 return I2C_STATUS_ERROR; 103 return I2C_STATUS_ERROR;
104 } 104 }
105 105
106 return I2C_STATUS_SUCCESS; 106 return I2C_STATUS_SUCCESS;
107} 107}
108 108
109int16_t i2c_read_ack(uint16_t timeout) { 109int16_t i2c_read_ack(uint16_t timeout) {
110 // start TWI module and acknowledge data after reception 110 // start TWI module and acknowledge data after reception
111 TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA); 111 TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA);
112 112
113 uint16_t timeout_timer = timer_read(); 113 uint16_t timeout_timer = timer_read();
114 while (!(TWCR & (1 << TWINT))) { 114 while (!(TWCR & (1 << TWINT))) {
115 if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { 115 if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) {
116 return I2C_STATUS_TIMEOUT; 116 return I2C_STATUS_TIMEOUT;
117 }
117 } 118 }
118 }
119 119
120 // return received data from TWDR 120 // return received data from TWDR
121 return TWDR; 121 return TWDR;
122} 122}
123 123
124int16_t i2c_read_nack(uint16_t timeout) { 124int16_t i2c_read_nack(uint16_t timeout) {
125 // start receiving without acknowledging reception 125 // start receiving without acknowledging reception
126 TWCR = (1 << TWINT) | (1 << TWEN); 126 TWCR = (1 << TWINT) | (1 << TWEN);
127 127
128 uint16_t timeout_timer = timer_read(); 128 uint16_t timeout_timer = timer_read();
129 while (!(TWCR & (1 << TWINT))) { 129 while (!(TWCR & (1 << TWINT))) {
130 if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { 130 if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) {
131 return I2C_STATUS_TIMEOUT; 131 return I2C_STATUS_TIMEOUT;
132 }
132 } 133 }
133 }
134 134
135 // return received data from TWDR 135 // return received data from TWDR
136 return TWDR; 136 return TWDR;
137} 137}
138 138
139i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout) { 139i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout) {
140 i2c_status_t status = i2c_start(address | I2C_WRITE, timeout); 140 i2c_status_t status = i2c_start(address | I2C_WRITE, timeout);
141 141
142 for (uint16_t i = 0; i < length && status >= 0; i++) { 142 for (uint16_t i = 0; i < length && status >= 0; i++) {
143 status = i2c_write(data[i], timeout); 143 status = i2c_write(data[i], timeout);
144 } 144 }
145 145
146 i2c_stop(); 146 i2c_stop();
147 147
148 return status; 148 return status;
149} 149}
150 150
151i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) { 151i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) {
152 i2c_status_t status = i2c_start(address | I2C_READ, timeout); 152 i2c_status_t status = i2c_start(address | I2C_READ, timeout);
153 153
154 for (uint16_t i = 0; i < (length - 1) && status >= 0; i++) { 154 for (uint16_t i = 0; i < (length - 1) && status >= 0; i++) {
155 status = i2c_read_ack(timeout); 155 status = i2c_read_ack(timeout);
156 if (status >= 0) { 156 if (status >= 0) {
157 data[i] = status; 157 data[i] = status;
158 }
158 } 159 }
159 }
160 160
161 if (status >= 0) {
162 status = i2c_read_nack(timeout);
163 if (status >= 0) { 161 if (status >= 0) {
164 data[(length - 1)] = status; 162 status = i2c_read_nack(timeout);
163 if (status >= 0) {
164 data[(length - 1)] = status;
165 }
165 } 166 }
166 }
167 167
168 i2c_stop(); 168 i2c_stop();
169 169
170 return (status < 0) ? status : I2C_STATUS_SUCCESS; 170 return (status < 0) ? status : I2C_STATUS_SUCCESS;
171} 171}
172 172
173i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) { 173i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) {
174 i2c_status_t status = i2c_start(devaddr | 0x00, timeout); 174 i2c_status_t status = i2c_start(devaddr | 0x00, timeout);
175 if (status >= 0) { 175 if (status >= 0) {
176 status = i2c_write(regaddr, timeout); 176 status = i2c_write(regaddr, timeout);
177 177
178 for (uint16_t i = 0; i < length && status >= 0; i++) { 178 for (uint16_t i = 0; i < length && status >= 0; i++) {
179 status = i2c_write(data[i], timeout); 179 status = i2c_write(data[i], timeout);
180 }
180 } 181 }
181 }
182 182
183 i2c_stop(); 183 i2c_stop();
184 184
185 return status; 185 return status;
186} 186}
187 187
188i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) { 188i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) {
189 i2c_status_t status = i2c_start(devaddr, timeout); 189 i2c_status_t status = i2c_start(devaddr, timeout);
190 if (status < 0) { 190 if (status < 0) {
191 goto error; 191 goto error;
192 } 192 }
193 193
194 status = i2c_write(regaddr, timeout); 194 status = i2c_write(regaddr, timeout);
195 if (status < 0) { 195 if (status < 0) {
196 goto error; 196 goto error;
197 } 197 }
198 198
199 status = i2c_start(devaddr | 0x01, timeout); 199 status = i2c_start(devaddr | 0x01, timeout);
200 200
201 for (uint16_t i = 0; i < (length - 1) && status >= 0; i++) { 201 for (uint16_t i = 0; i < (length - 1) && status >= 0; i++) {
202 status = i2c_read_ack(timeout); 202 status = i2c_read_ack(timeout);
203 if (status >= 0) { 203 if (status >= 0) {
204 data[i] = status; 204 data[i] = status;
205 }
205 } 206 }
206 }
207 207
208 if (status >= 0) {
209 status = i2c_read_nack(timeout);
210 if (status >= 0) { 208 if (status >= 0) {
211 data[(length - 1)] = status; 209 status = i2c_read_nack(timeout);
210 if (status >= 0) {
211 data[(length - 1)] = status;
212 }
212 } 213 }
213 }
214 214
215error: 215error:
216 i2c_stop(); 216 i2c_stop();
217 217
218 return (status < 0) ? status : I2C_STATUS_SUCCESS; 218 return (status < 0) ? status : I2C_STATUS_SUCCESS;
219} 219}
220 220
221void i2c_stop(void) { 221void i2c_stop(void) {
222 // transmit STOP condition 222 // transmit STOP condition
223 TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); 223 TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
224} 224}
diff --git a/drivers/avr/i2c_master.h b/drivers/avr/i2c_master.h
index d68142430..0a3b6c508 100755..100644
--- a/drivers/avr/i2c_master.h
+++ b/drivers/avr/i2c_master.h
@@ -26,21 +26,21 @@
26typedef int16_t i2c_status_t; 26typedef int16_t i2c_status_t;
27 27
28#define I2C_STATUS_SUCCESS (0) 28#define I2C_STATUS_SUCCESS (0)
29#define I2C_STATUS_ERROR (-1) 29#define I2C_STATUS_ERROR (-1)
30#define I2C_STATUS_TIMEOUT (-2) 30#define I2C_STATUS_TIMEOUT (-2)
31 31
32#define I2C_TIMEOUT_IMMEDIATE (0) 32#define I2C_TIMEOUT_IMMEDIATE (0)
33#define I2C_TIMEOUT_INFINITE (0xFFFF) 33#define I2C_TIMEOUT_INFINITE (0xFFFF)
34 34
35void i2c_init(void); 35void i2c_init(void);
36i2c_status_t i2c_start(uint8_t address, uint16_t timeout); 36i2c_status_t i2c_start(uint8_t address, uint16_t timeout);
37i2c_status_t i2c_write(uint8_t data, uint16_t timeout); 37i2c_status_t i2c_write(uint8_t data, uint16_t timeout);
38int16_t i2c_read_ack(uint16_t timeout); 38int16_t i2c_read_ack(uint16_t timeout);
39int16_t i2c_read_nack(uint16_t timeout); 39int16_t i2c_read_nack(uint16_t timeout);
40i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout); 40i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout);
41i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout); 41i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);
42i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); 42i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
43i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); 43i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
44void i2c_stop(void); 44void i2c_stop(void);
45 45
46#endif // I2C_MASTER_H 46#endif // I2C_MASTER_H
diff --git a/drivers/avr/i2c_slave.c b/drivers/avr/i2c_slave.c
index 4958a0f8e..3fb684f70 100755..100644
--- a/drivers/avr/i2c_slave.c
+++ b/drivers/avr/i2c_slave.c
@@ -27,24 +27,24 @@
27volatile uint8_t i2c_slave_reg[I2C_SLAVE_REG_COUNT]; 27volatile uint8_t i2c_slave_reg[I2C_SLAVE_REG_COUNT];
28 28
29static volatile uint8_t buffer_address; 29static volatile uint8_t buffer_address;
30static volatile bool slave_has_register_set = false; 30static volatile bool slave_has_register_set = false;
31 31
32void i2c_slave_init(uint8_t address){ 32void i2c_slave_init(uint8_t address) {
33 // load address into TWI address register 33 // load address into TWI address register
34 TWAR = address; 34 TWAR = address;
35 // set the TWCR to enable address matching and enable TWI, clear TWINT, enable TWI interrupt 35 // set the TWCR to enable address matching and enable TWI, clear TWINT, enable TWI interrupt
36 TWCR = (1 << TWIE) | (1 << TWEA) | (1 << TWINT) | (1 << TWEN); 36 TWCR = (1 << TWIE) | (1 << TWEA) | (1 << TWINT) | (1 << TWEN);
37} 37}
38 38
39void i2c_slave_stop(void){ 39void i2c_slave_stop(void) {
40 // clear acknowledge and enable bits 40 // clear acknowledge and enable bits
41 TWCR &= ~((1 << TWEA) | (1 << TWEN)); 41 TWCR &= ~((1 << TWEA) | (1 << TWEN));
42} 42}
43 43
44ISR(TWI_vect){ 44ISR(TWI_vect) {
45 uint8_t ack = 1; 45 uint8_t ack = 1;
46 46
47 switch(TW_STATUS){ 47 switch (TW_STATUS) {
48 case TW_SR_SLA_ACK: 48 case TW_SR_SLA_ACK:
49 // The device is now a slave receiver 49 // The device is now a slave receiver
50 slave_has_register_set = false; 50 slave_has_register_set = false;
@@ -53,14 +53,14 @@ ISR(TWI_vect){
53 case TW_SR_DATA_ACK: 53 case TW_SR_DATA_ACK:
54 // This device is a slave receiver and has received data 54 // This device is a slave receiver and has received data
55 // First byte is the location then the bytes will be writen in buffer with auto-incriment 55 // First byte is the location then the bytes will be writen in buffer with auto-incriment
56 if(!slave_has_register_set){ 56 if (!slave_has_register_set) {
57 buffer_address = TWDR; 57 buffer_address = TWDR;
58 58
59 if (buffer_address >= I2C_SLAVE_REG_COUNT) { // address out of bounds dont ack 59 if (buffer_address >= I2C_SLAVE_REG_COUNT) { // address out of bounds dont ack
60 ack = 0; 60 ack = 0;
61 buffer_address = 0; 61 buffer_address = 0;
62 } 62 }
63 slave_has_register_set = true; // address has been receaved now fill in buffer 63 slave_has_register_set = true; // address has been receaved now fill in buffer
64 } else { 64 } else {
65 i2c_slave_reg[buffer_address] = TWDR; 65 i2c_slave_reg[buffer_address] = TWDR;
66 buffer_address++; 66 buffer_address++;
diff --git a/drivers/avr/i2c_slave.h b/drivers/avr/i2c_slave.h
index 2f4589e9c..5ed0b11a8 100755..100644
--- a/drivers/avr/i2c_slave.h
+++ b/drivers/avr/i2c_slave.h
@@ -30,4 +30,4 @@ extern volatile uint8_t i2c_slave_reg[I2C_SLAVE_REG_COUNT];
30void i2c_slave_init(uint8_t address); 30void i2c_slave_init(uint8_t address);
31void i2c_slave_stop(void); 31void i2c_slave_stop(void);
32 32
33#endif // I2C_SLAVE_H 33#endif // I2C_SLAVE_H
diff --git a/drivers/avr/pro_micro.h b/drivers/avr/pro_micro.h
index f9e7ed75d..762a99a05 100644
--- a/drivers/avr/pro_micro.h
+++ b/drivers/avr/pro_micro.h
@@ -90,14 +90,14 @@
90#undef OCR2_6 90#undef OCR2_6
91#undef OCR2_7 91#undef OCR2_7
92 92
93#define NUM_DIGITAL_PINS 30 93#define NUM_DIGITAL_PINS 30
94#define NUM_ANALOG_INPUTS 12 94#define NUM_ANALOG_INPUTS 12
95 95
96#define TX_RX_LED_INIT DDRD |= (1<<5), DDRB |= (1<<0) 96#define TX_RX_LED_INIT DDRD |= (1 << 5), DDRB |= (1 << 0)
97#define TXLED0 PORTD |= (1<<5) 97#define TXLED0 PORTD |= (1 << 5)
98#define TXLED1 PORTD &= ~(1<<5) 98#define TXLED1 PORTD &= ~(1 << 5)
99#define RXLED0 PORTB |= (1<<0) 99#define RXLED0 PORTB |= (1 << 0)
100#define RXLED1 PORTB &= ~(1<<0) 100#define RXLED1 PORTB &= ~(1 << 0)
101 101
102static const uint8_t SDA = 2; 102static const uint8_t SDA = 2;
103static const uint8_t SCL = 3; 103static const uint8_t SCL = 3;
@@ -111,27 +111,27 @@ static const uint8_t SCK = 15;
111 111
112// Mapping of analog pins as digital I/O 112// Mapping of analog pins as digital I/O
113// A6-A11 share with digital pins 113// A6-A11 share with digital pins
114static const uint8_t ADC0 = 18; 114static const uint8_t ADC0 = 18;
115static const uint8_t ADC1 = 19; 115static const uint8_t ADC1 = 19;
116static const uint8_t ADC2 = 20; 116static const uint8_t ADC2 = 20;
117static const uint8_t ADC3 = 21; 117static const uint8_t ADC3 = 21;
118static const uint8_t ADC4 = 22; 118static const uint8_t ADC4 = 22;
119static const uint8_t ADC5 = 23; 119static const uint8_t ADC5 = 23;
120static const uint8_t ADC6 = 24; // D4 120static const uint8_t ADC6 = 24; // D4
121static const uint8_t ADC7 = 25; // D6 121static const uint8_t ADC7 = 25; // D6
122static const uint8_t ADC8 = 26; // D8 122static const uint8_t ADC8 = 26; // D8
123static const uint8_t ADC9 = 27; // D9 123static const uint8_t ADC9 = 27; // D9
124static const uint8_t ADC10 = 28; // D10 124static const uint8_t ADC10 = 28; // D10
125static const uint8_t ADC11 = 29; // D12 125static const uint8_t ADC11 = 29; // D12
126 126
127#define digitalPinToPCICR(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCICR) : ((uint8_t *)0)) 127#define digitalPinToPCICR(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCICR) : ((uint8_t *)0))
128#define digitalPinToPCICRbit(p) 0 128#define digitalPinToPCICRbit(p) 0
129#define digitalPinToPCMSK(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCMSK0) : ((uint8_t *)0)) 129#define digitalPinToPCMSK(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCMSK0) : ((uint8_t *)0))
130#define digitalPinToPCMSKbit(p) ( ((p) >= 8 && (p) <= 11) ? (p) - 4 : ((p) == 14 ? 3 : ((p) == 15 ? 1 : ((p) == 16 ? 2 : ((p) == 17 ? 0 : (p - A8 + 4)))))) 130#define digitalPinToPCMSKbit(p) (((p) >= 8 && (p) <= 11) ? (p)-4 : ((p) == 14 ? 3 : ((p) == 15 ? 1 : ((p) == 16 ? 2 : ((p) == 17 ? 0 : (p - A8 + 4))))))
131 131
132// __AVR_ATmega32U4__ has an unusual mapping of pins to channels 132// __AVR_ATmega32U4__ has an unusual mapping of pins to channels
133extern const uint8_t PROGMEM analog_pin_to_channel_PGM[]; 133extern const uint8_t PROGMEM analog_pin_to_channel_PGM[];
134#define analogPinToChannel(P) ( pgm_read_byte( analog_pin_to_channel_PGM + (P) ) ) 134#define analogPinToChannel(P) (pgm_read_byte(analog_pin_to_channel_PGM + (P)))
135 135
136#define digitalPinToInterrupt(p) ((p) == 0 ? 2 : ((p) == 1 ? 3 : ((p) == 2 ? 1 : ((p) == 3 ? 0 : ((p) == 7 ? 4 : NOT_AN_INTERRUPT))))) 136#define digitalPinToInterrupt(p) ((p) == 0 ? 2 : ((p) == 1 ? 3 : ((p) == 2 ? 1 : ((p) == 3 ? 0 : ((p) == 7 ? 4 : NOT_AN_INTERRUPT)))))
137 137
@@ -182,159 +182,121 @@ extern const uint8_t PROGMEM analog_pin_to_channel_PGM[];
182// appropriate addresses for various functions (e.g. reading 182// appropriate addresses for various functions (e.g. reading
183// and writing) 183// and writing)
184const uint16_t PROGMEM port_to_mode_PGM[] = { 184const uint16_t PROGMEM port_to_mode_PGM[] = {
185 NOT_A_PORT, 185 NOT_A_PORT, NOT_A_PORT, (uint16_t)&DDRB, (uint16_t)&DDRC, (uint16_t)&DDRD, (uint16_t)&DDRE, (uint16_t)&DDRF,
186 NOT_A_PORT,
187 (uint16_t) &DDRB,
188 (uint16_t) &DDRC,
189 (uint16_t) &DDRD,
190 (uint16_t) &DDRE,
191 (uint16_t) &DDRF,
192}; 186};
193 187
194const uint16_t PROGMEM port_to_output_PGM[] = { 188const uint16_t PROGMEM port_to_output_PGM[] = {
195 NOT_A_PORT, 189 NOT_A_PORT, NOT_A_PORT, (uint16_t)&PORTB, (uint16_t)&PORTC, (uint16_t)&PORTD, (uint16_t)&PORTE, (uint16_t)&PORTF,
196 NOT_A_PORT,
197 (uint16_t) &PORTB,
198 (uint16_t) &PORTC,
199 (uint16_t) &PORTD,
200 (uint16_t) &PORTE,
201 (uint16_t) &PORTF,
202}; 190};
203 191
204const uint16_t PROGMEM port_to_input_PGM[] = { 192const uint16_t PROGMEM port_to_input_PGM[] = {
205 NOT_A_PORT, 193 NOT_A_PORT, NOT_A_PORT, (uint16_t)&PINB, (uint16_t)&PINC, (uint16_t)&PIND, (uint16_t)&PINE, (uint16_t)&PINF,
206 NOT_A_PORT,
207 (uint16_t) &PINB,
208 (uint16_t) &PINC,
209 (uint16_t) &PIND,
210 (uint16_t) &PINE,
211 (uint16_t) &PINF,
212}; 194};
213 195
214const uint8_t PROGMEM digital_pin_to_port_PGM[] = { 196const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
215 PD, // D0 - PD2 197 PD, // D0 - PD2
216 PD, // D1 - PD3 198 PD, // D1 - PD3
217 PD, // D2 - PD1 199 PD, // D2 - PD1
218 PD, // D3 - PD0 200 PD, // D3 - PD0
219 PD, // D4 - PD4 201 PD, // D4 - PD4
220 PC, // D5 - PC6 202 PC, // D5 - PC6
221 PD, // D6 - PD7 203 PD, // D6 - PD7
222 PE, // D7 - PE6 204 PE, // D7 - PE6
223 205
224 PB, // D8 - PB4 206 PB, // D8 - PB4
225 PB, // D9 - PB5 207 PB, // D9 - PB5
226 PB, // D10 - PB6 208 PB, // D10 - PB6
227 PB, // D11 - PB7 209 PB, // D11 - PB7
228 PD, // D12 - PD6 210 PD, // D12 - PD6
229 PC, // D13 - PC7 211 PC, // D13 - PC7
230 212
231 PB, // D14 - MISO - PB3 213 PB, // D14 - MISO - PB3
232 PB, // D15 - SCK - PB1 214 PB, // D15 - SCK - PB1
233 PB, // D16 - MOSI - PB2 215 PB, // D16 - MOSI - PB2
234 PB, // D17 - SS - PB0 216 PB, // D17 - SS - PB0
235 217
236 PF, // D18 - A0 - PF7 218 PF, // D18 - A0 - PF7
237 PF, // D19 - A1 - PF6 219 PF, // D19 - A1 - PF6
238 PF, // D20 - A2 - PF5 220 PF, // D20 - A2 - PF5
239 PF, // D21 - A3 - PF4 221 PF, // D21 - A3 - PF4
240 PF, // D22 - A4 - PF1 222 PF, // D22 - A4 - PF1
241 PF, // D23 - A5 - PF0 223 PF, // D23 - A5 - PF0
242 224
243 PD, // D24 - PD5 225 PD, // D24 - PD5
244 PD, // D25 / D6 - A7 - PD7 226 PD, // D25 / D6 - A7 - PD7
245 PB, // D26 / D8 - A8 - PB4 227 PB, // D26 / D8 - A8 - PB4
246 PB, // D27 / D9 - A9 - PB5 228 PB, // D27 / D9 - A9 - PB5
247 PB, // D28 / D10 - A10 - PB6 229 PB, // D28 / D10 - A10 - PB6
248 PD, // D29 / D12 - A11 - PD6 230 PD, // D29 / D12 - A11 - PD6
249}; 231};
250 232
251const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = { 233const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = {
252 _BV(2), // D0 - PD2 234 _BV(2), // D0 - PD2
253 _BV(3), // D1 - PD3 235 _BV(3), // D1 - PD3
254 _BV(1), // D2 - PD1 236 _BV(1), // D2 - PD1
255 _BV(0), // D3 - PD0 237 _BV(0), // D3 - PD0
256 _BV(4), // D4 - PD4 238 _BV(4), // D4 - PD4
257 _BV(6), // D5 - PC6 239 _BV(6), // D5 - PC6
258 _BV(7), // D6 - PD7 240 _BV(7), // D6 - PD7
259 _BV(6), // D7 - PE6 241 _BV(6), // D7 - PE6
260 242
261 _BV(4), // D8 - PB4 243 _BV(4), // D8 - PB4
262 _BV(5), // D9 - PB5 244 _BV(5), // D9 - PB5
263 _BV(6), // D10 - PB6 245 _BV(6), // D10 - PB6
264 _BV(7), // D11 - PB7 246 _BV(7), // D11 - PB7
265 _BV(6), // D12 - PD6 247 _BV(6), // D12 - PD6
266 _BV(7), // D13 - PC7 248 _BV(7), // D13 - PC7
267 249
268 _BV(3), // D14 - MISO - PB3 250 _BV(3), // D14 - MISO - PB3
269 _BV(1), // D15 - SCK - PB1 251 _BV(1), // D15 - SCK - PB1
270 _BV(2), // D16 - MOSI - PB2 252 _BV(2), // D16 - MOSI - PB2
271 _BV(0), // D17 - SS - PB0 253 _BV(0), // D17 - SS - PB0
272 254
273 _BV(7), // D18 - A0 - PF7 255 _BV(7), // D18 - A0 - PF7
274 _BV(6), // D19 - A1 - PF6 256 _BV(6), // D19 - A1 - PF6
275 _BV(5), // D20 - A2 - PF5 257 _BV(5), // D20 - A2 - PF5
276 _BV(4), // D21 - A3 - PF4 258 _BV(4), // D21 - A3 - PF4
277 _BV(1), // D22 - A4 - PF1 259 _BV(1), // D22 - A4 - PF1
278 _BV(0), // D23 - A5 - PF0 260 _BV(0), // D23 - A5 - PF0
279 261
280 _BV(5), // D24 - PD5 262 _BV(5), // D24 - PD5
281 _BV(7), // D25 / D6 - A7 - PD7 263 _BV(7), // D25 / D6 - A7 - PD7
282 _BV(4), // D26 / D8 - A8 - PB4 264 _BV(4), // D26 / D8 - A8 - PB4
283 _BV(5), // D27 / D9 - A9 - PB5 265 _BV(5), // D27 / D9 - A9 - PB5
284 _BV(6), // D28 / D10 - A10 - PB6 266 _BV(6), // D28 / D10 - A10 - PB6
285 _BV(6), // D29 / D12 - A11 - PD6 267 _BV(6), // D29 / D12 - A11 - PD6
286}; 268};
287 269
288const uint8_t PROGMEM digital_pin_to_timer_PGM[] = { 270const uint8_t PROGMEM digital_pin_to_timer_PGM[] = {
289 NOT_ON_TIMER, 271 NOT_ON_TIMER, NOT_ON_TIMER, NOT_ON_TIMER, TIMER0B, /* 3 */
290 NOT_ON_TIMER, 272 NOT_ON_TIMER, TIMER3A, /* 5 */
291 NOT_ON_TIMER, 273 TIMER4D, /* 6 */
292 TIMER0B, /* 3 */
293 NOT_ON_TIMER,
294 TIMER3A, /* 5 */
295 TIMER4D, /* 6 */
296 NOT_ON_TIMER, 274 NOT_ON_TIMER,
297 275
298 NOT_ON_TIMER, 276 NOT_ON_TIMER, TIMER1A, /* 9 */
299 TIMER1A, /* 9 */ 277 TIMER1B, /* 10 */
300 TIMER1B, /* 10 */ 278 TIMER0A, /* 11 */
301 TIMER0A, /* 11 */
302 279
303 NOT_ON_TIMER, 280 NOT_ON_TIMER, TIMER4A, /* 13 */
304 TIMER4A, /* 13 */
305 281
306 NOT_ON_TIMER, 282 NOT_ON_TIMER, NOT_ON_TIMER, NOT_ON_TIMER, NOT_ON_TIMER, NOT_ON_TIMER, NOT_ON_TIMER,
307 NOT_ON_TIMER,
308 NOT_ON_TIMER,
309 NOT_ON_TIMER,
310 NOT_ON_TIMER,
311 NOT_ON_TIMER,
312 283
313 NOT_ON_TIMER, 284 NOT_ON_TIMER, NOT_ON_TIMER, NOT_ON_TIMER, NOT_ON_TIMER, NOT_ON_TIMER, NOT_ON_TIMER, NOT_ON_TIMER, NOT_ON_TIMER, NOT_ON_TIMER, NOT_ON_TIMER,
314 NOT_ON_TIMER,
315 NOT_ON_TIMER,
316 NOT_ON_TIMER,
317 NOT_ON_TIMER,
318 NOT_ON_TIMER,
319 NOT_ON_TIMER,
320 NOT_ON_TIMER,
321 NOT_ON_TIMER,
322 NOT_ON_TIMER,
323}; 285};
324 286
325const uint8_t PROGMEM analog_pin_to_channel_PGM[] = { 287const uint8_t PROGMEM analog_pin_to_channel_PGM[] = {
326 7, // A0 PF7 ADC7 288 7, // A0 PF7 ADC7
327 6, // A1 PF6 ADC6 289 6, // A1 PF6 ADC6
328 5, // A2 PF5 ADC5 290 5, // A2 PF5 ADC5
329 4, // A3 PF4 ADC4 291 4, // A3 PF4 ADC4
330 1, // A4 PF1 ADC1 292 1, // A4 PF1 ADC1
331 0, // A5 PF0 ADC0 293 0, // A5 PF0 ADC0
332 8, // A6 D4 PD4 ADC8 294 8, // A6 D4 PD4 ADC8
333 10, // A7 D6 PD7 ADC10 295 10, // A7 D6 PD7 ADC10
334 11, // A8 D8 PB4 ADC11 296 11, // A8 D8 PB4 ADC11
335 12, // A9 D9 PB5 ADC12 297 12, // A9 D9 PB5 ADC12
336 13, // A10 D10 PB6 ADC13 298 13, // A10 D10 PB6 ADC13
337 9 // A11 D12 PD6 ADC9 299 9 // A11 D12 PD6 ADC9
338}; 300};
339 301
340#endif /* ARDUINO_MAIN */ 302#endif /* ARDUINO_MAIN */
@@ -354,9 +316,9 @@ const uint8_t PROGMEM analog_pin_to_channel_PGM[] = {
354// 316//
355// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX 317// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX
356// pins are NOT connected to anything by default. 318// pins are NOT connected to anything by default.
357#define SERIAL_PORT_MONITOR Serial 319#define SERIAL_PORT_MONITOR Serial
358#define SERIAL_PORT_USBVIRTUAL Serial 320#define SERIAL_PORT_USBVIRTUAL Serial
359#define SERIAL_PORT_HARDWARE Serial1 321#define SERIAL_PORT_HARDWARE Serial1
360#define SERIAL_PORT_HARDWARE_OPEN Serial1 322#define SERIAL_PORT_HARDWARE_OPEN Serial1
361 323
362#endif /* Pins_Arduino_h */ 324#endif /* Pins_Arduino_h */
diff --git a/drivers/avr/ssd1306.c b/drivers/avr/ssd1306.c
index bb8938bba..61d7a9953 100644
--- a/drivers/avr/ssd1306.c
+++ b/drivers/avr/ssd1306.c
@@ -1,325 +1,320 @@
1#ifdef SSD1306OLED 1#ifdef SSD1306OLED
2 2
3#include "ssd1306.h" 3# include "ssd1306.h"
4#include "i2c.h" 4# include "i2c.h"
5#include <string.h> 5# include <string.h>
6#include "print.h" 6# include "print.h"
7#include "glcdfont.c" 7# include "glcdfont.c"
8#ifdef ADAFRUIT_BLE_ENABLE 8# ifdef ADAFRUIT_BLE_ENABLE
9#include "adafruit_ble.h" 9# include "adafruit_ble.h"
10#endif 10# endif
11#ifdef PROTOCOL_LUFA 11# ifdef PROTOCOL_LUFA
12#include "lufa.h" 12# include "lufa.h"
13#endif 13# endif
14#include "sendchar.h" 14# include "sendchar.h"
15#include "timer.h" 15# include "timer.h"
16 16
17// Set this to 1 to help diagnose early startup problems 17// Set this to 1 to help diagnose early startup problems
18// when testing power-on with ble. Turn it off otherwise, 18// when testing power-on with ble. Turn it off otherwise,
19// as the latency of printing most of the debug info messes 19// as the latency of printing most of the debug info messes
20// with the matrix scan, causing keys to drop. 20// with the matrix scan, causing keys to drop.
21#define DEBUG_TO_SCREEN 0 21# define DEBUG_TO_SCREEN 0
22 22
23//static uint16_t last_battery_update; 23// static uint16_t last_battery_update;
24//static uint32_t vbat; 24// static uint32_t vbat;
25//#define BatteryUpdateInterval 10000 /* milliseconds */ 25//#define BatteryUpdateInterval 10000 /* milliseconds */
26#define ScreenOffInterval 300000 /* milliseconds */ 26# define ScreenOffInterval 300000 /* milliseconds */
27#if DEBUG_TO_SCREEN 27# if DEBUG_TO_SCREEN
28static uint8_t displaying; 28static uint8_t displaying;
29#endif 29# endif
30static uint16_t last_flush; 30static uint16_t last_flush;
31 31
32// Write command sequence. 32// Write command sequence.
33// Returns true on success. 33// Returns true on success.
34static inline bool _send_cmd1(uint8_t cmd) { 34static inline bool _send_cmd1(uint8_t cmd) {
35 bool res = false; 35 bool res = false;
36 36
37 if (i2c_start_write(SSD1306_ADDRESS)) { 37 if (i2c_start_write(SSD1306_ADDRESS)) {
38 xprintf("failed to start write to %d\n", SSD1306_ADDRESS); 38 xprintf("failed to start write to %d\n", SSD1306_ADDRESS);
39 goto done; 39 goto done;
40 } 40 }
41 41
42 if (i2c_master_write(0x0 /* command byte follows */)) { 42 if (i2c_master_write(0x0 /* command byte follows */)) {
43 print("failed to write control byte\n"); 43 print("failed to write control byte\n");
44 44
45 goto done; 45 goto done;
46 } 46 }
47 47
48 if (i2c_master_write(cmd)) { 48 if (i2c_master_write(cmd)) {
49 xprintf("failed to write command %d\n", cmd); 49 xprintf("failed to write command %d\n", cmd);
50 goto done; 50 goto done;
51 } 51 }
52 res = true; 52 res = true;
53done: 53done:
54 i2c_master_stop(); 54 i2c_master_stop();
55 return res; 55 return res;
56} 56}
57 57
58// Write 2-byte command sequence. 58// Write 2-byte command sequence.
59// Returns true on success 59// Returns true on success
60static inline bool _send_cmd2(uint8_t cmd, uint8_t opr) { 60static inline bool _send_cmd2(uint8_t cmd, uint8_t opr) {
61 if (!_send_cmd1(cmd)) { 61 if (!_send_cmd1(cmd)) {
62 return false; 62 return false;
63 } 63 }
64 return _send_cmd1(opr); 64 return _send_cmd1(opr);
65} 65}
66 66
67// Write 3-byte command sequence. 67// Write 3-byte command sequence.
68// Returns true on success 68// Returns true on success
69static inline bool _send_cmd3(uint8_t cmd, uint8_t opr1, uint8_t opr2) { 69static inline bool _send_cmd3(uint8_t cmd, uint8_t opr1, uint8_t opr2) {
70 if (!_send_cmd1(cmd)) { 70 if (!_send_cmd1(cmd)) {
71 return false; 71 return false;
72 } 72 }
73 if (!_send_cmd1(opr1)) { 73 if (!_send_cmd1(opr1)) {
74 return false; 74 return false;
75 } 75 }
76 return _send_cmd1(opr2); 76 return _send_cmd1(opr2);
77} 77}
78 78
79#define send_cmd1(c) if (!_send_cmd1(c)) {goto done;} 79# define send_cmd1(c) \
80#define send_cmd2(c,o) if (!_send_cmd2(c,o)) {goto done;} 80 if (!_send_cmd1(c)) { \
81#define send_cmd3(c,o1,o2) if (!_send_cmd3(c,o1,o2)) {goto done;} 81 goto done; \
82 }
83# define send_cmd2(c, o) \
84 if (!_send_cmd2(c, o)) { \
85 goto done; \
86 }
87# define send_cmd3(c, o1, o2) \
88 if (!_send_cmd3(c, o1, o2)) { \
89 goto done; \
90 }
82 91
83static void clear_display(void) { 92static void clear_display(void) {
84 matrix_clear(&display); 93 matrix_clear(&display);
85 94
86 // Clear all of the display bits (there can be random noise 95 // Clear all of the display bits (there can be random noise
87 // in the RAM on startup) 96 // in the RAM on startup)
88 send_cmd3(PageAddr, 0, (DisplayHeight / 8) - 1); 97 send_cmd3(PageAddr, 0, (DisplayHeight / 8) - 1);
89 send_cmd3(ColumnAddr, 0, DisplayWidth - 1); 98 send_cmd3(ColumnAddr, 0, DisplayWidth - 1);
90 99
91 if (i2c_start_write(SSD1306_ADDRESS)) { 100 if (i2c_start_write(SSD1306_ADDRESS)) {
92 goto done; 101 goto done;
93 } 102 }
94 if (i2c_master_write(0x40)) { 103 if (i2c_master_write(0x40)) {
95 // Data mode 104 // Data mode
96 goto done; 105 goto done;
97 } 106 }
98 for (uint8_t row = 0; row < MatrixRows; ++row) { 107 for (uint8_t row = 0; row < MatrixRows; ++row) {
99 for (uint8_t col = 0; col < DisplayWidth; ++col) { 108 for (uint8_t col = 0; col < DisplayWidth; ++col) {
100 i2c_master_write(0); 109 i2c_master_write(0);
110 }
101 } 111 }
102 }
103 112
104 display.dirty = false; 113 display.dirty = false;
105 114
106done: 115done:
107 i2c_master_stop(); 116 i2c_master_stop();
108} 117}
109 118
110#if DEBUG_TO_SCREEN 119# if DEBUG_TO_SCREEN
111#undef sendchar 120# undef sendchar
112static int8_t capture_sendchar(uint8_t c) { 121static int8_t capture_sendchar(uint8_t c) {
113 sendchar(c); 122 sendchar(c);
114 iota_gfx_write_char(c); 123 iota_gfx_write_char(c);
115 124
116 if (!displaying) { 125 if (!displaying) {
117 iota_gfx_flush(); 126 iota_gfx_flush();
118 } 127 }
119 return 0; 128 return 0;
120} 129}
121#endif 130# endif
122 131
123bool iota_gfx_init(void) { 132bool iota_gfx_init(void) {
124 bool success = false; 133 bool success = false;
125 134
126 send_cmd1(DisplayOff); 135 send_cmd1(DisplayOff);
127 send_cmd2(SetDisplayClockDiv, 0x80); 136 send_cmd2(SetDisplayClockDiv, 0x80);
128 send_cmd2(SetMultiPlex, DisplayHeight - 1); 137 send_cmd2(SetMultiPlex, DisplayHeight - 1);
129 138
130 send_cmd2(SetDisplayOffset, 0); 139 send_cmd2(SetDisplayOffset, 0);
131 140
141 send_cmd1(SetStartLine | 0x0);
142 send_cmd2(SetChargePump, 0x14 /* Enable */);
143 send_cmd2(SetMemoryMode, 0 /* horizontal addressing */);
132 144
133 send_cmd1(SetStartLine | 0x0); 145# ifdef OLED_ROTATE180
134 send_cmd2(SetChargePump, 0x14 /* Enable */); 146 // the following Flip the display orientation 180 degrees
135 send_cmd2(SetMemoryMode, 0 /* horizontal addressing */); 147 send_cmd1(SegRemap);
148 send_cmd1(ComScanInc);
149# endif
150# ifndef OLED_ROTATE180
151 // Flips the display orientation 0 degrees
152 send_cmd1(SegRemap | 0x1);
153 send_cmd1(ComScanDec);
154# endif
136 155
137#ifdef OLED_ROTATE180 156 send_cmd2(SetComPins, 0x2);
138// the following Flip the display orientation 180 degrees 157 send_cmd2(SetContrast, 0x8f);
139 send_cmd1(SegRemap); 158 send_cmd2(SetPreCharge, 0xf1);
140 send_cmd1(ComScanInc); 159 send_cmd2(SetVComDetect, 0x40);
141#endif 160 send_cmd1(DisplayAllOnResume);
142#ifndef OLED_ROTATE180 161 send_cmd1(NormalDisplay);
143// Flips the display orientation 0 degrees 162 send_cmd1(DeActivateScroll);
144 send_cmd1(SegRemap | 0x1); 163 send_cmd1(DisplayOn);
145 send_cmd1(ComScanDec);
146#endif
147
148 send_cmd2(SetComPins, 0x2);
149 send_cmd2(SetContrast, 0x8f);
150 send_cmd2(SetPreCharge, 0xf1);
151 send_cmd2(SetVComDetect, 0x40);
152 send_cmd1(DisplayAllOnResume);
153 send_cmd1(NormalDisplay);
154 send_cmd1(DeActivateScroll);
155 send_cmd1(DisplayOn);
156 164
157 send_cmd2(SetContrast, 0); // Dim 165 send_cmd2(SetContrast, 0); // Dim
158 166
159 clear_display(); 167 clear_display();
160 168
161 success = true; 169 success = true;
162 170
163 iota_gfx_flush(); 171 iota_gfx_flush();
164 172
165#if DEBUG_TO_SCREEN 173# if DEBUG_TO_SCREEN
166 print_set_sendchar(capture_sendchar); 174 print_set_sendchar(capture_sendchar);
167#endif 175# endif
168 176
169done: 177done:
170 return success; 178 return success;
171} 179}
172 180
173bool iota_gfx_off(void) { 181bool iota_gfx_off(void) {
174 bool success = false; 182 bool success = false;
175 183
176 send_cmd1(DisplayOff); 184 send_cmd1(DisplayOff);
177 success = true; 185 success = true;
178 186
179done: 187done:
180 return success; 188 return success;
181} 189}
182 190
183bool iota_gfx_on(void) { 191bool iota_gfx_on(void) {
184 bool success = false; 192 bool success = false;
185 193
186 send_cmd1(DisplayOn); 194 send_cmd1(DisplayOn);
187 success = true; 195 success = true;
188 196
189done: 197done:
190 return success; 198 return success;
191} 199}
192 200
193void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c) { 201void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c) {
194 *matrix->cursor = c; 202 *matrix->cursor = c;
195 ++matrix->cursor; 203 ++matrix->cursor;
196 204
197 if (matrix->cursor - &matrix->display[0][0] == sizeof(matrix->display)) { 205 if (matrix->cursor - &matrix->display[0][0] == sizeof(matrix->display)) {
198 // We went off the end; scroll the display upwards by one line 206 // We went off the end; scroll the display upwards by one line
199 memmove(&matrix->display[0], &matrix->display[1], 207 memmove(&matrix->display[0], &matrix->display[1], MatrixCols * (MatrixRows - 1));
200 MatrixCols * (MatrixRows - 1)); 208 matrix->cursor = &matrix->display[MatrixRows - 1][0];
201 matrix->cursor = &matrix->display[MatrixRows - 1][0]; 209 memset(matrix->cursor, ' ', MatrixCols);
202 memset(matrix->cursor, ' ', MatrixCols); 210 }
203 }
204} 211}
205 212
206void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c) { 213void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c) {
207 matrix->dirty = true; 214 matrix->dirty = true;
208 215
209 if (c == '\n') { 216 if (c == '\n') {
210 // Clear to end of line from the cursor and then move to the 217 // Clear to end of line from the cursor and then move to the
211 // start of the next line 218 // start of the next line
212 uint8_t cursor_col = (matrix->cursor - &matrix->display[0][0]) % MatrixCols; 219 uint8_t cursor_col = (matrix->cursor - &matrix->display[0][0]) % MatrixCols;
213 220
214 while (cursor_col++ < MatrixCols) { 221 while (cursor_col++ < MatrixCols) {
215 matrix_write_char_inner(matrix, ' '); 222 matrix_write_char_inner(matrix, ' ');
223 }
224 return;
216 } 225 }
217 return;
218 }
219 226
220 matrix_write_char_inner(matrix, c); 227 matrix_write_char_inner(matrix, c);
221} 228}
222 229
223void iota_gfx_write_char(uint8_t c) { 230void iota_gfx_write_char(uint8_t c) { matrix_write_char(&display, c); }
224 matrix_write_char(&display, c);
225}
226 231
227void matrix_write(struct CharacterMatrix *matrix, const char *data) { 232void matrix_write(struct CharacterMatrix *matrix, const char *data) {
228 const char *end = data + strlen(data); 233 const char *end = data + strlen(data);
229 while (data < end) { 234 while (data < end) {
230 matrix_write_char(matrix, *data); 235 matrix_write_char(matrix, *data);
231 ++data; 236 ++data;
232 } 237 }
233} 238}
234 239
235void iota_gfx_write(const char *data) { 240void iota_gfx_write(const char *data) { matrix_write(&display, data); }
236 matrix_write(&display, data);
237}
238 241
239void matrix_write_P(struct CharacterMatrix *matrix, const char *data) { 242void matrix_write_P(struct CharacterMatrix *matrix, const char *data) {
240 while (true) { 243 while (true) {
241 uint8_t c = pgm_read_byte(data); 244 uint8_t c = pgm_read_byte(data);
242 if (c == 0) { 245 if (c == 0) {
243 return; 246 return;
247 }
248 matrix_write_char(matrix, c);
249 ++data;
244 } 250 }
245 matrix_write_char(matrix, c);
246 ++data;
247 }
248} 251}
249 252
250void iota_gfx_write_P(const char *data) { 253void iota_gfx_write_P(const char *data) { matrix_write_P(&display, data); }
251 matrix_write_P(&display, data);
252}
253 254
254void matrix_clear(struct CharacterMatrix *matrix) { 255void matrix_clear(struct CharacterMatrix *matrix) {
255 memset(matrix->display, ' ', sizeof(matrix->display)); 256 memset(matrix->display, ' ', sizeof(matrix->display));
256 matrix->cursor = &matrix->display[0][0]; 257 matrix->cursor = &matrix->display[0][0];
257 matrix->dirty = true; 258 matrix->dirty = true;
258} 259}
259 260
260void iota_gfx_clear_screen(void) { 261void iota_gfx_clear_screen(void) { matrix_clear(&display); }
261 matrix_clear(&display);
262}
263 262
264void matrix_render(struct CharacterMatrix *matrix) { 263void matrix_render(struct CharacterMatrix *matrix) {
265 last_flush = timer_read(); 264 last_flush = timer_read();
266 iota_gfx_on(); 265 iota_gfx_on();
267#if DEBUG_TO_SCREEN 266# if DEBUG_TO_SCREEN
268 ++displaying; 267 ++displaying;
269#endif 268# endif
269
270 // Move to the home position
271 send_cmd3(PageAddr, 0, MatrixRows - 1);
272 send_cmd3(ColumnAddr, 0, (MatrixCols * FontWidth) - 1);
273
274 if (i2c_start_write(SSD1306_ADDRESS)) {
275 goto done;
276 }
277 if (i2c_master_write(0x40)) {
278 // Data mode
279 goto done;
280 }
281
282 for (uint8_t row = 0; row < MatrixRows; ++row) {
283 for (uint8_t col = 0; col < MatrixCols; ++col) {
284 const uint8_t *glyph = font + (matrix->display[row][col] * (FontWidth - 1));
285
286 for (uint8_t glyphCol = 0; glyphCol < FontWidth - 1; ++glyphCol) {
287 uint8_t colBits = pgm_read_byte(glyph + glyphCol);
288 i2c_master_write(colBits);
289 }
270 290
271 // Move to the home position 291 // 1 column of space between chars (it's not included in the glyph)
272 send_cmd3(PageAddr, 0, MatrixRows - 1); 292 i2c_master_write(0);
273 send_cmd3(ColumnAddr, 0, (MatrixCols * FontWidth) - 1); 293 }
274
275 if (i2c_start_write(SSD1306_ADDRESS)) {
276 goto done;
277 }
278 if (i2c_master_write(0x40)) {
279 // Data mode
280 goto done;
281 }
282
283 for (uint8_t row = 0; row < MatrixRows; ++row) {
284 for (uint8_t col = 0; col < MatrixCols; ++col) {
285 const uint8_t *glyph = font + (matrix->display[row][col] * (FontWidth - 1));
286
287 for (uint8_t glyphCol = 0; glyphCol < FontWidth - 1; ++glyphCol) {
288 uint8_t colBits = pgm_read_byte(glyph + glyphCol);
289 i2c_master_write(colBits);
290 }
291
292 // 1 column of space between chars (it's not included in the glyph)
293 i2c_master_write(0);
294 } 294 }
295 }
296 295
297 matrix->dirty = false; 296 matrix->dirty = false;
298 297
299done: 298done:
300 i2c_master_stop(); 299 i2c_master_stop();
301#if DEBUG_TO_SCREEN 300# if DEBUG_TO_SCREEN
302 --displaying; 301 --displaying;
303#endif 302# endif
304} 303}
305 304
306void iota_gfx_flush(void) { 305void iota_gfx_flush(void) { matrix_render(&display); }
307 matrix_render(&display);
308}
309 306
310__attribute__ ((weak)) 307__attribute__((weak)) void iota_gfx_task_user(void) {}
311void iota_gfx_task_user(void) {
312}
313 308
314void iota_gfx_task(void) { 309void iota_gfx_task(void) {
315 iota_gfx_task_user(); 310 iota_gfx_task_user();
316 311
317 if (display.dirty) { 312 if (display.dirty) {
318 iota_gfx_flush(); 313 iota_gfx_flush();
319 } 314 }
320 315
321 if (timer_elapsed(last_flush) > ScreenOffInterval) { 316 if (timer_elapsed(last_flush) > ScreenOffInterval) {
322 iota_gfx_off(); 317 iota_gfx_off();
323 } 318 }
324} 319}
325#endif 320#endif
diff --git a/drivers/avr/ssd1306.h b/drivers/avr/ssd1306.h
index df6a75359..825b0d7d5 100644
--- a/drivers/avr/ssd1306.h
+++ b/drivers/avr/ssd1306.h
@@ -7,49 +7,49 @@
7#include "config.h" 7#include "config.h"
8 8
9enum ssd1306_cmds { 9enum ssd1306_cmds {
10 DisplayOff = 0xAE, 10 DisplayOff = 0xAE,
11 DisplayOn = 0xAF, 11 DisplayOn = 0xAF,
12 12
13 SetContrast = 0x81, 13 SetContrast = 0x81,
14 DisplayAllOnResume = 0xA4, 14 DisplayAllOnResume = 0xA4,
15 15
16 DisplayAllOn = 0xA5, 16 DisplayAllOn = 0xA5,
17 NormalDisplay = 0xA6, 17 NormalDisplay = 0xA6,
18 InvertDisplay = 0xA7, 18 InvertDisplay = 0xA7,
19 SetDisplayOffset = 0xD3, 19 SetDisplayOffset = 0xD3,
20 SetComPins = 0xda, 20 SetComPins = 0xda,
21 SetVComDetect = 0xdb, 21 SetVComDetect = 0xdb,
22 SetDisplayClockDiv = 0xD5, 22 SetDisplayClockDiv = 0xD5,
23 SetPreCharge = 0xd9, 23 SetPreCharge = 0xd9,
24 SetMultiPlex = 0xa8, 24 SetMultiPlex = 0xa8,
25 SetLowColumn = 0x00, 25 SetLowColumn = 0x00,
26 SetHighColumn = 0x10, 26 SetHighColumn = 0x10,
27 SetStartLine = 0x40, 27 SetStartLine = 0x40,
28 28
29 SetMemoryMode = 0x20, 29 SetMemoryMode = 0x20,
30 ColumnAddr = 0x21, 30 ColumnAddr = 0x21,
31 PageAddr = 0x22, 31 PageAddr = 0x22,
32 32
33 ComScanInc = 0xc0, 33 ComScanInc = 0xc0,
34 ComScanDec = 0xc8, 34 ComScanDec = 0xc8,
35 SegRemap = 0xa0, 35 SegRemap = 0xa0,
36 SetChargePump = 0x8d, 36 SetChargePump = 0x8d,
37 ExternalVcc = 0x01, 37 ExternalVcc = 0x01,
38 SwitchCapVcc = 0x02, 38 SwitchCapVcc = 0x02,
39 39
40 ActivateScroll = 0x2f, 40 ActivateScroll = 0x2f,
41 DeActivateScroll = 0x2e, 41 DeActivateScroll = 0x2e,
42 SetVerticalScrollArea = 0xa3, 42 SetVerticalScrollArea = 0xa3,
43 RightHorizontalScroll = 0x26, 43 RightHorizontalScroll = 0x26,
44 LeftHorizontalScroll = 0x27, 44 LeftHorizontalScroll = 0x27,
45 VerticalAndRightHorizontalScroll = 0x29, 45 VerticalAndRightHorizontalScroll = 0x29,
46 VerticalAndLeftHorizontalScroll = 0x2a, 46 VerticalAndLeftHorizontalScroll = 0x2a,
47}; 47};
48 48
49// Controls the SSD1306 128x32 OLED display via i2c 49// Controls the SSD1306 128x32 OLED display via i2c
50 50
51#ifndef SSD1306_ADDRESS 51#ifndef SSD1306_ADDRESS
52#define SSD1306_ADDRESS 0x3C 52# define SSD1306_ADDRESS 0x3C
53#endif 53#endif
54 54
55#define DisplayHeight 32 55#define DisplayHeight 32
@@ -62,9 +62,9 @@ enum ssd1306_cmds {
62#define MatrixCols (DisplayWidth / FontWidth) 62#define MatrixCols (DisplayWidth / FontWidth)
63 63
64struct CharacterMatrix { 64struct CharacterMatrix {
65 uint8_t display[MatrixRows][MatrixCols]; 65 uint8_t display[MatrixRows][MatrixCols];
66 uint8_t *cursor; 66 uint8_t *cursor;
67 bool dirty; 67 bool dirty;
68}; 68};
69 69
70struct CharacterMatrix display; 70struct CharacterMatrix display;
@@ -88,6 +88,4 @@ void matrix_write(struct CharacterMatrix *matrix, const char *data);
88void matrix_write_P(struct CharacterMatrix *matrix, const char *data); 88void matrix_write_P(struct CharacterMatrix *matrix, const char *data);
89void matrix_render(struct CharacterMatrix *matrix); 89void matrix_render(struct CharacterMatrix *matrix);
90 90
91
92
93#endif 91#endif
diff --git a/drivers/avr/ws2812.c b/drivers/avr/ws2812.c
index 7c3cb5174..0a02c6f7f 100644
--- a/drivers/avr/ws2812.c
+++ b/drivers/avr/ws2812.c
@@ -1,25 +1,25 @@
1/* 1/*
2* light weight WS2812 lib V2.0b 2 * light weight WS2812 lib V2.0b
3* 3 *
4* Controls WS2811/WS2812/WS2812B RGB-LEDs 4 * Controls WS2811/WS2812/WS2812B RGB-LEDs
5* Author: Tim (cpldcpu@gmail.com) 5 * Author: Tim (cpldcpu@gmail.com)
6* 6 *
7* Jan 18th, 2014 v2.0b Initial Version 7 * Jan 18th, 2014 v2.0b Initial Version
8* Nov 29th, 2015 v2.3 Added SK6812RGBW support 8 * Nov 29th, 2015 v2.3 Added SK6812RGBW support
9* 9 *
10* This program is free software: you can redistribute it and/or modify 10 * This program is free software: you can redistribute it and/or modify
11* it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
12* the Free Software Foundation, either version 2 of the License, or 12 * the Free Software Foundation, either version 2 of the License, or
13* (at your option) any later version. 13 * (at your option) any later version.
14* 14 *
15* This program is distributed in the hope that it will be useful, 15 * This program is distributed in the hope that it will be useful,
16* but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18* GNU General Public License for more details. 18 * GNU General Public License for more details.
19* 19 *
20* You should have received a copy of the GNU General Public License 20 * You should have received a copy of the GNU General Public License
21* along with this program. If not, see <http://www.gnu.org/licenses/>. 21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22*/ 22 */
23 23
24#include "ws2812.h" 24#include "ws2812.h"
25#include <avr/interrupt.h> 25#include <avr/interrupt.h>
@@ -30,44 +30,40 @@
30#if !defined(LED_ARRAY) && defined(RGB_MATRIX_ENABLE) 30#if !defined(LED_ARRAY) && defined(RGB_MATRIX_ENABLE)
31// LED color buffer 31// LED color buffer
32LED_TYPE led[DRIVER_LED_TOTAL]; 32LED_TYPE led[DRIVER_LED_TOTAL];
33 #define LED_ARRAY led 33# define LED_ARRAY led
34#endif 34#endif
35 35
36#ifdef RGBW_BB_TWI 36#ifdef RGBW_BB_TWI
37 37
38// Port for the I2C 38// Port for the I2C
39#define I2C_DDR DDRD 39# define I2C_DDR DDRD
40#define I2C_PIN PIND 40# define I2C_PIN PIND
41#define I2C_PORT PORTD 41# define I2C_PORT PORTD
42 42
43// Pins to be used in the bit banging 43// Pins to be used in the bit banging
44#define I2C_CLK 0 44# define I2C_CLK 0
45#define I2C_DAT 1 45# define I2C_DAT 1
46 46
47#define I2C_DATA_HI()\ 47# define I2C_DATA_HI() \
48I2C_DDR &= ~ (1 << I2C_DAT);\ 48 I2C_DDR &= ~(1 << I2C_DAT); \
49I2C_PORT |= (1 << I2C_DAT); 49 I2C_PORT |= (1 << I2C_DAT);
50#define I2C_DATA_LO()\ 50# define I2C_DATA_LO() \
51I2C_DDR |= (1 << I2C_DAT);\ 51 I2C_DDR |= (1 << I2C_DAT); \
52I2C_PORT &= ~ (1 << I2C_DAT); 52 I2C_PORT &= ~(1 << I2C_DAT);
53 53
54#define I2C_CLOCK_HI()\ 54# define I2C_CLOCK_HI() \
55I2C_DDR &= ~ (1 << I2C_CLK);\ 55 I2C_DDR &= ~(1 << I2C_CLK); \
56I2C_PORT |= (1 << I2C_CLK); 56 I2C_PORT |= (1 << I2C_CLK);
57#define I2C_CLOCK_LO()\ 57# define I2C_CLOCK_LO() \
58I2C_DDR |= (1 << I2C_CLK);\ 58 I2C_DDR |= (1 << I2C_CLK); \
59I2C_PORT &= ~ (1 << I2C_CLK); 59 I2C_PORT &= ~(1 << I2C_CLK);
60 60
61#define I2C_DELAY 1 61# define I2C_DELAY 1
62 62
63void I2C_WriteBit(unsigned char c) 63void I2C_WriteBit(unsigned char c) {
64{ 64 if (c > 0) {
65 if (c > 0)
66 {
67 I2C_DATA_HI(); 65 I2C_DATA_HI();
68 } 66 } else {
69 else
70 {
71 I2C_DATA_LO(); 67 I2C_DATA_LO();
72 } 68 }
73 69
@@ -77,8 +73,7 @@ void I2C_WriteBit(unsigned char c)
77 I2C_CLOCK_LO(); 73 I2C_CLOCK_LO();
78 _delay_us(I2C_DELAY); 74 _delay_us(I2C_DELAY);
79 75
80 if (c > 0) 76 if (c > 0) {
81 {
82 I2C_DATA_LO(); 77 I2C_DATA_LO();
83 } 78 }
84 79
@@ -87,9 +82,8 @@ void I2C_WriteBit(unsigned char c)
87 82
88// Inits bitbanging port, must be called before using the functions below 83// Inits bitbanging port, must be called before using the functions below
89// 84//
90void I2C_Init(void) 85void I2C_Init(void) {
91{ 86 I2C_PORT &= ~((1 << I2C_DAT) | (1 << I2C_CLK));
92 I2C_PORT &= ~ ((1 << I2C_DAT) | (1 << I2C_CLK));
93 87
94 I2C_CLOCK_HI(); 88 I2C_CLOCK_HI();
95 I2C_DATA_HI(); 89 I2C_DATA_HI();
@@ -99,10 +93,9 @@ void I2C_Init(void)
99 93
100// Send a START Condition 94// Send a START Condition
101// 95//
102void I2C_Start(void) 96void I2C_Start(void) {
103{
104 // set both to high at the same time 97 // set both to high at the same time
105 I2C_DDR &= ~ ((1 << I2C_DAT) | (1 << I2C_CLK)); 98 I2C_DDR &= ~((1 << I2C_DAT) | (1 << I2C_CLK));
106 _delay_us(I2C_DELAY); 99 _delay_us(I2C_DELAY);
107 100
108 I2C_DATA_LO(); 101 I2C_DATA_LO();
@@ -114,8 +107,7 @@ void I2C_Start(void)
114 107
115// Send a STOP Condition 108// Send a STOP Condition
116// 109//
117void I2C_Stop(void) 110void I2C_Stop(void) {
118{
119 I2C_CLOCK_HI(); 111 I2C_CLOCK_HI();
120 _delay_us(I2C_DELAY); 112 _delay_us(I2C_DELAY);
121 113
@@ -125,106 +117,91 @@ void I2C_Stop(void)
125 117
126// write a byte to the I2C slave device 118// write a byte to the I2C slave device
127// 119//
128unsigned char I2C_Write(unsigned char c) 120unsigned char I2C_Write(unsigned char c) {
129{ 121 for (char i = 0; i < 8; i++) {
130 for (char i = 0; i < 8; i++)
131 {
132 I2C_WriteBit(c & 128); 122 I2C_WriteBit(c & 128);
133 123
134 c <<= 1; 124 c <<= 1;
135 } 125 }
136 126
137
138 I2C_WriteBit(0); 127 I2C_WriteBit(0);
139 _delay_us(I2C_DELAY); 128 _delay_us(I2C_DELAY);
140 _delay_us(I2C_DELAY); 129 _delay_us(I2C_DELAY);
141 130
142 // _delay_us(I2C_DELAY); 131 // _delay_us(I2C_DELAY);
143 //return I2C_ReadBit(); 132 // return I2C_ReadBit();
144 return 0; 133 return 0;
145} 134}
146 135
147
148#endif 136#endif
149 137
150#ifdef RGB_MATRIX_ENABLE 138#ifdef RGB_MATRIX_ENABLE
151// Set an led in the buffer to a color 139// Set an led in the buffer to a color
152void inline ws2812_setled(int i, uint8_t r, uint8_t g, uint8_t b) 140void inline ws2812_setled(int i, uint8_t r, uint8_t g, uint8_t b) {
153{
154 led[i].r = r; 141 led[i].r = r;
155 led[i].g = g; 142 led[i].g = g;
156 led[i].b = b; 143 led[i].b = b;
157} 144}
158 145
159void ws2812_setled_all (uint8_t r, uint8_t g, uint8_t b) 146void ws2812_setled_all(uint8_t r, uint8_t g, uint8_t b) {
160{ 147 for (int i = 0; i < sizeof(led) / sizeof(led[0]); i++) {
161 for (int i = 0; i < sizeof(led)/sizeof(led[0]); i++) { 148 led[i].r = r;
162 led[i].r = r; 149 led[i].g = g;
163 led[i].g = g; 150 led[i].b = b;
164 led[i].b = b; 151 }
165 }
166} 152}
167#endif 153#endif
168 154
169// Setleds for standard RGB 155// Setleds for standard RGB
170void inline ws2812_setleds(LED_TYPE *ledarray, uint16_t leds) 156void inline ws2812_setleds(LED_TYPE *ledarray, uint16_t leds) {
171{ 157 // ws2812_setleds_pin(ledarray,leds, _BV(ws2812_pin));
172 // ws2812_setleds_pin(ledarray,leds, _BV(ws2812_pin)); 158 ws2812_setleds_pin(ledarray, leds, _BV(RGB_DI_PIN & 0xF));
173 ws2812_setleds_pin(ledarray,leds, _BV(RGB_DI_PIN & 0xF));
174} 159}
175 160
176void inline ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmask) 161void inline ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmask) {
177{ 162 // ws2812_DDRREG |= pinmask; // Enable DDR
178 // ws2812_DDRREG |= pinmask; // Enable DDR 163 // new universal format (DDR)
179 // new universal format (DDR) 164 _SFR_IO8((RGB_DI_PIN >> 4) + 1) |= pinmask;
180 _SFR_IO8((RGB_DI_PIN >> 4) + 1) |= pinmask;
181 165
182 ws2812_sendarray_mask((uint8_t*)ledarray,leds+leds+leds,pinmask); 166 ws2812_sendarray_mask((uint8_t *)ledarray, leds + leds + leds, pinmask);
183 _delay_us(50); 167 _delay_us(50);
184} 168}
185 169
186// Setleds for SK6812RGBW 170// Setleds for SK6812RGBW
187void inline ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t leds) 171void inline ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t leds) {
188{ 172#ifdef RGBW_BB_TWI
189
190 #ifdef RGBW_BB_TWI
191 uint8_t sreg_prev, twcr_prev; 173 uint8_t sreg_prev, twcr_prev;
192 sreg_prev=SREG; 174 sreg_prev = SREG;
193 twcr_prev=TWCR; 175 twcr_prev = TWCR;
194 cli(); 176 cli();
195 TWCR &= ~(1<<TWEN); 177 TWCR &= ~(1 << TWEN);
196 I2C_Init(); 178 I2C_Init();
197 I2C_Start(); 179 I2C_Start();
198 I2C_Write(0x84); 180 I2C_Write(0x84);
199 uint16_t datlen = leds<<2; 181 uint16_t datlen = leds << 2;
200 uint8_t curbyte; 182 uint8_t curbyte;
201 uint8_t * data = (uint8_t*)ledarray; 183 uint8_t *data = (uint8_t *)ledarray;
202 while (datlen--) { 184 while (datlen--) {
203 curbyte=*data++; 185 curbyte = *data++;
204 I2C_Write(curbyte); 186 I2C_Write(curbyte);
205 } 187 }
206 I2C_Stop(); 188 I2C_Stop();
207 SREG=sreg_prev; 189 SREG = sreg_prev;
208 TWCR=twcr_prev; 190 TWCR = twcr_prev;
209 #endif 191#endif
210
211
212 // ws2812_DDRREG |= _BV(ws2812_pin); // Enable DDR
213 // new universal format (DDR)
214 _SFR_IO8((RGB_DI_PIN >> 4) + 1) |= _BV(RGB_DI_PIN & 0xF);
215 192
216 ws2812_sendarray_mask((uint8_t*)ledarray,leds<<2,_BV(RGB_DI_PIN & 0xF)); 193 // ws2812_DDRREG |= _BV(ws2812_pin); // Enable DDR
194 // new universal format (DDR)
195 _SFR_IO8((RGB_DI_PIN >> 4) + 1) |= _BV(RGB_DI_PIN & 0xF);
217 196
197 ws2812_sendarray_mask((uint8_t *)ledarray, leds << 2, _BV(RGB_DI_PIN & 0xF));
218 198
219 #ifndef RGBW_BB_TWI 199#ifndef RGBW_BB_TWI
220 _delay_us(80); 200 _delay_us(80);
221 #endif 201#endif
222} 202}
223 203
224void ws2812_sendarray(uint8_t *data,uint16_t datlen) 204void ws2812_sendarray(uint8_t *data, uint16_t datlen) { ws2812_sendarray_mask(data, datlen, _BV(RGB_DI_PIN & 0xF)); }
225{
226 ws2812_sendarray_mask(data,datlen,_BV(RGB_DI_PIN & 0xF));
227}
228 205
229/* 206/*
230 This routine writes an array of bytes with RGB values to the Dataout pin 207 This routine writes an array of bytes with RGB values to the Dataout pin
@@ -232,136 +209,133 @@ void ws2812_sendarray(uint8_t *data,uint16_t datlen)
232*/ 209*/
233 210
234// Timing in ns 211// Timing in ns
235#define w_zeropulse 350 212#define w_zeropulse 350
236#define w_onepulse 900 213#define w_onepulse 900
237#define w_totalperiod 1250 214#define w_totalperiod 1250
238 215
239// Fixed cycles used by the inner loop 216// Fixed cycles used by the inner loop
240#define w_fixedlow 2 217#define w_fixedlow 2
241#define w_fixedhigh 4 218#define w_fixedhigh 4
242#define w_fixedtotal 8 219#define w_fixedtotal 8
243 220
244// Insert NOPs to match the timing, if possible 221// Insert NOPs to match the timing, if possible
245#define w_zerocycles (((F_CPU/1000)*w_zeropulse )/1000000) 222#define w_zerocycles (((F_CPU / 1000) * w_zeropulse) / 1000000)
246#define w_onecycles (((F_CPU/1000)*w_onepulse +500000)/1000000) 223#define w_onecycles (((F_CPU / 1000) * w_onepulse + 500000) / 1000000)
247#define w_totalcycles (((F_CPU/1000)*w_totalperiod +500000)/1000000) 224#define w_totalcycles (((F_CPU / 1000) * w_totalperiod + 500000) / 1000000)
248 225
249// w1 - nops between rising edge and falling edge - low 226// w1 - nops between rising edge and falling edge - low
250#define w1 (w_zerocycles-w_fixedlow) 227#define w1 (w_zerocycles - w_fixedlow)
251// w2 nops between fe low and fe high 228// w2 nops between fe low and fe high
252#define w2 (w_onecycles-w_fixedhigh-w1) 229#define w2 (w_onecycles - w_fixedhigh - w1)
253// w3 nops to complete loop 230// w3 nops to complete loop
254#define w3 (w_totalcycles-w_fixedtotal-w1-w2) 231#define w3 (w_totalcycles - w_fixedtotal - w1 - w2)
255 232
256#if w1>0 233#if w1 > 0
257 #define w1_nops w1 234# define w1_nops w1
258#else 235#else
259 #define w1_nops 0 236# define w1_nops 0
260#endif 237#endif
261 238
262// The only critical timing parameter is the minimum pulse length of the "0" 239// The only critical timing parameter is the minimum pulse length of the "0"
263// Warn or throw error if this timing can not be met with current F_CPU settings. 240// Warn or throw error if this timing can not be met with current F_CPU settings.
264#define w_lowtime ((w1_nops+w_fixedlow)*1000000)/(F_CPU/1000) 241#define w_lowtime ((w1_nops + w_fixedlow) * 1000000) / (F_CPU / 1000)
265#if w_lowtime>550 242#if w_lowtime > 550
266 #error "Light_ws2812: Sorry, the clock speed is too low. Did you set F_CPU correctly?" 243# error "Light_ws2812: Sorry, the clock speed is too low. Did you set F_CPU correctly?"
267#elif w_lowtime>450 244#elif w_lowtime > 450
268 #warning "Light_ws2812: The timing is critical and may only work on WS2812B, not on WS2812(S)." 245# warning "Light_ws2812: The timing is critical and may only work on WS2812B, not on WS2812(S)."
269 #warning "Please consider a higher clockspeed, if possible" 246# warning "Please consider a higher clockspeed, if possible"
270#endif 247#endif
271 248
272#if w2>0 249#if w2 > 0
273#define w2_nops w2 250# define w2_nops w2
274#else 251#else
275#define w2_nops 0 252# define w2_nops 0
276#endif 253#endif
277 254
278#if w3>0 255#if w3 > 0
279#define w3_nops w3 256# define w3_nops w3
280#else 257#else
281#define w3_nops 0 258# define w3_nops 0
282#endif 259#endif
283 260
284#define w_nop1 "nop \n\t" 261#define w_nop1 "nop \n\t"
285#define w_nop2 "rjmp .+0 \n\t" 262#define w_nop2 "rjmp .+0 \n\t"
286#define w_nop4 w_nop2 w_nop2 263#define w_nop4 w_nop2 w_nop2
287#define w_nop8 w_nop4 w_nop4 264#define w_nop8 w_nop4 w_nop4
288#define w_nop16 w_nop8 w_nop8 265#define w_nop16 w_nop8 w_nop8
289 266
290void inline ws2812_sendarray_mask(uint8_t *data,uint16_t datlen,uint8_t maskhi) 267void inline ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t maskhi) {
291{ 268 uint8_t curbyte, ctr, masklo;
292 uint8_t curbyte,ctr,masklo; 269 uint8_t sreg_prev;
293 uint8_t sreg_prev; 270
294 271 // masklo =~maskhi&ws2812_PORTREG;
295 // masklo =~maskhi&ws2812_PORTREG; 272 // maskhi |= ws2812_PORTREG;
296 // maskhi |= ws2812_PORTREG; 273 masklo = ~maskhi & _SFR_IO8((RGB_DI_PIN >> 4) + 2);
297 masklo =~maskhi&_SFR_IO8((RGB_DI_PIN >> 4) + 2); 274 maskhi |= _SFR_IO8((RGB_DI_PIN >> 4) + 2);
298 maskhi |= _SFR_IO8((RGB_DI_PIN >> 4) + 2); 275 sreg_prev = SREG;
299 sreg_prev=SREG; 276 cli();
300 cli(); 277
301 278 while (datlen--) {
302 while (datlen--) { 279 curbyte = (*data++);
303 curbyte=(*data++); 280
304 281 asm volatile(" ldi %0,8 \n\t"
305 asm volatile( 282 "loop%=: \n\t"
306 " ldi %0,8 \n\t" 283 " out %2,%3 \n\t" // '1' [01] '0' [01] - re
307 "loop%=: \n\t" 284#if (w1_nops & 1)
308 " out %2,%3 \n\t" // '1' [01] '0' [01] - re 285 w_nop1
309#if (w1_nops&1)
310w_nop1
311#endif 286#endif
312#if (w1_nops&2) 287#if (w1_nops & 2)
313w_nop2 288 w_nop2
314#endif 289#endif
315#if (w1_nops&4) 290#if (w1_nops & 4)
316w_nop4 291 w_nop4
317#endif 292#endif
318#if (w1_nops&8) 293#if (w1_nops & 8)
319w_nop8 294 w_nop8
320#endif 295#endif
321#if (w1_nops&16) 296#if (w1_nops & 16)
322w_nop16 297 w_nop16
323#endif 298#endif
324 " sbrs %1,7 \n\t" // '1' [03] '0' [02] 299 " sbrs %1,7 \n\t" // '1' [03] '0' [02]
325 " out %2,%4 \n\t" // '1' [--] '0' [03] - fe-low 300 " out %2,%4 \n\t" // '1' [--] '0' [03] - fe-low
326 " lsl %1 \n\t" // '1' [04] '0' [04] 301 " lsl %1 \n\t" // '1' [04] '0' [04]
327#if (w2_nops&1) 302#if (w2_nops & 1)
328 w_nop1 303 w_nop1
329#endif 304#endif
330#if (w2_nops&2) 305#if (w2_nops & 2)
331 w_nop2 306 w_nop2
332#endif 307#endif
333#if (w2_nops&4) 308#if (w2_nops & 4)
334 w_nop4 309 w_nop4
335#endif 310#endif
336#if (w2_nops&8) 311#if (w2_nops & 8)
337 w_nop8 312 w_nop8
338#endif 313#endif
339#if (w2_nops&16) 314#if (w2_nops & 16)
340 w_nop16 315 w_nop16
341#endif 316#endif
342 " out %2,%4 \n\t" // '1' [+1] '0' [+1] - fe-high 317 " out %2,%4 \n\t" // '1' [+1] '0' [+1] - fe-high
343#if (w3_nops&1) 318#if (w3_nops & 1)
344w_nop1 319 w_nop1
345#endif 320#endif
346#if (w3_nops&2) 321#if (w3_nops & 2)
347w_nop2 322 w_nop2
348#endif 323#endif
349#if (w3_nops&4) 324#if (w3_nops & 4)
350w_nop4 325 w_nop4
351#endif 326#endif
352#if (w3_nops&8) 327#if (w3_nops & 8)
353w_nop8 328 w_nop8
354#endif 329#endif
355#if (w3_nops&16) 330#if (w3_nops & 16)
356w_nop16 331 w_nop16
357#endif 332#endif
358 333
359 " dec %0 \n\t" // '1' [+2] '0' [+2] 334 " dec %0 \n\t" // '1' [+2] '0' [+2]
360 " brne loop%=\n\t" // '1' [+3] '0' [+4] 335 " brne loop%=\n\t" // '1' [+3] '0' [+4]
361 : "=&d" (ctr) 336 : "=&d"(ctr)
362 : "r" (curbyte), "I" (_SFR_IO_ADDR(_SFR_IO8((RGB_DI_PIN >> 4) + 2))), "r" (maskhi), "r" (masklo) 337 : "r"(curbyte), "I"(_SFR_IO_ADDR(_SFR_IO8((RGB_DI_PIN >> 4) + 2))), "r"(maskhi), "r"(masklo));
363 ); 338 }
364 }
365 339
366 SREG=sreg_prev; 340 SREG = sreg_prev;
367} 341}
diff --git a/drivers/avr/ws2812.h b/drivers/avr/ws2812.h
index 95f540b18..a9dd89718 100644
--- a/drivers/avr/ws2812.h
+++ b/drivers/avr/ws2812.h
@@ -43,12 +43,12 @@
43 * - Wait 50�s to reset the LEDs 43 * - Wait 50�s to reset the LEDs
44 */ 44 */
45#ifdef RGB_MATRIX_ENABLE 45#ifdef RGB_MATRIX_ENABLE
46void ws2812_setled (int index, uint8_t r, uint8_t g, uint8_t b); 46void ws2812_setled(int index, uint8_t r, uint8_t g, uint8_t b);
47void ws2812_setled_all (uint8_t r, uint8_t g, uint8_t b); 47void ws2812_setled_all(uint8_t r, uint8_t g, uint8_t b);
48#endif 48#endif
49 49
50void ws2812_setleds (LED_TYPE *ledarray, uint16_t number_of_leds); 50void ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds);
51void ws2812_setleds_pin (LED_TYPE *ledarray, uint16_t number_of_leds,uint8_t pinmask); 51void ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t number_of_leds, uint8_t pinmask);
52void ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t number_of_leds); 52void ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t number_of_leds);
53 53
54/* 54/*
@@ -58,18 +58,17 @@ void ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t number_of_leds);
58 * The length is the number of bytes to send - three per LED. 58 * The length is the number of bytes to send - three per LED.
59 */ 59 */
60 60
61void ws2812_sendarray (uint8_t *array,uint16_t length); 61void ws2812_sendarray(uint8_t *array, uint16_t length);
62void ws2812_sendarray_mask(uint8_t *array,uint16_t length, uint8_t pinmask); 62void ws2812_sendarray_mask(uint8_t *array, uint16_t length, uint8_t pinmask);
63
64 63
65/* 64/*
66 * Internal defines 65 * Internal defines
67 */ 66 */
68#ifndef CONCAT 67#ifndef CONCAT
69#define CONCAT(a, b) a ## b 68# define CONCAT(a, b) a##b
70#endif 69#endif
71#ifndef CONCAT_EXP 70#ifndef CONCAT_EXP
72#define CONCAT_EXP(a, b) CONCAT(a, b) 71# define CONCAT_EXP(a, b) CONCAT(a, b)
73#endif 72#endif
74 73
75#endif /* LIGHT_WS2812_H_ */ 74#endif /* LIGHT_WS2812_H_ */