diff options
| author | skullY <skullydazed@gmail.com> | 2019-08-30 11:19:03 -0700 |
|---|---|---|
| committer | skullydazed <skullydazed@users.noreply.github.com> | 2019-08-30 15:01:52 -0700 |
| commit | b624f32f944acdc59dcb130674c09090c5c404cb (patch) | |
| tree | bc13adbba137d122d9a2c2fb2fafcbb08ac10e25 /drivers/avr | |
| parent | 61af76a10d00aba185b8338604171de490a13e3b (diff) | |
| download | qmk_firmware-b624f32f944acdc59dcb130674c09090c5c404cb.tar.gz qmk_firmware-b624f32f944acdc59dcb130674c09090c5c404cb.zip | |
clang-format changes
Diffstat (limited to 'drivers/avr')
| -rw-r--r-- | drivers/avr/analog.c | 53 | ||||
| -rw-r--r-- | drivers/avr/analog.h | 26 | ||||
| -rw-r--r--[-rwxr-xr-x] | drivers/avr/apa102.c | 147 | ||||
| -rw-r--r--[-rwxr-xr-x] | drivers/avr/apa102.h | 5 | ||||
| -rw-r--r-- | drivers/avr/glcdfont.c | 280 | ||||
| -rw-r--r-- | drivers/avr/hd44780.c | 510 | ||||
| -rw-r--r-- | drivers/avr/hd44780.h | 303 | ||||
| -rw-r--r--[-rwxr-xr-x] | drivers/avr/i2c_master.c | 260 | ||||
| -rw-r--r--[-rwxr-xr-x] | drivers/avr/i2c_master.h | 12 | ||||
| -rw-r--r--[-rwxr-xr-x] | drivers/avr/i2c_slave.c | 18 | ||||
| -rw-r--r--[-rwxr-xr-x] | drivers/avr/i2c_slave.h | 2 | ||||
| -rw-r--r-- | drivers/avr/pro_micro.h | 270 | ||||
| -rw-r--r-- | drivers/avr/ssd1306.c | 427 | ||||
| -rw-r--r-- | drivers/avr/ssd1306.h | 84 | ||||
| -rw-r--r-- | drivers/avr/ws2812.c | 384 | ||||
| -rw-r--r-- | drivers/avr/ws2812.h | 17 |
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 | ||
| 24 | static uint8_t aref = (1 << REFS0); // default to AREF = Vcc | ||
| 24 | 25 | ||
| 25 | static uint8_t aref = (1<<REFS0); // default to AREF = Vcc | 26 | void analogReference(uint8_t mode) { aref = mode & 0xC0; } |
| 26 | |||
| 27 | |||
| 28 | void analogReference(uint8_t mode) | ||
| 29 | { | ||
| 30 | aref = mode & 0xC0; | ||
| 31 | } | ||
| 32 | |||
| 33 | 27 | ||
| 34 | // Arduino compatible pin input | 28 | // Arduino compatible pin input |
| 35 | int16_t analogRead(uint8_t pin) | 29 | int16_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 |
| 52 | int16_t adc_read(uint8_t mux) | 43 | int16_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 | ||
| 22 | void analogReference(uint8_t mode); | 22 | void analogReference(uint8_t mode); |
| 23 | int16_t analogRead(uint8_t pin); | 23 | int16_t analogRead(uint8_t pin); |
| 24 | int16_t adc_read(uint8_t mux); | 24 | int16_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 |
| 30 | void inline apa102_setleds(LED_TYPE *ledarray, uint16_t leds){ | 30 | void 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 | ||
| 34 | void static inline apa102_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmask_DI, uint8_t pinmask_CLK){ | 32 | void 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 | ||
| 41 | void apa102_send_array(uint8_t *data, uint16_t leds){ // Data is struct of 3 bytes. RGB - leds is number of leds in data | 39 | void 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 | ||
| 50 | void apa102_send_frame(uint32_t frame){ | 48 | void 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 | ||
| 57 | void apa102_start_frame(){ | 55 | void apa102_start_frame() { apa102_send_frame(0); } |
| 58 | apa102_send_frame(0); | ||
| 59 | } | ||
| 60 | 56 | ||
| 61 | void apa102_end_frame(uint16_t leds) | 57 | void 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 | ||
| 95 | void apa102_send_byte(uint8_t byte){ | 90 | void 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 | ||
| 44 | void apa102_setleds (LED_TYPE *ledarray, uint16_t number_of_leds); | 43 | void apa102_setleds(LED_TYPE *ledarray, uint16_t number_of_leds); |
| 45 | void apa102_setleds_pin (LED_TYPE *ledarray, uint16_t number_of_leds,uint8_t pinmask); | 44 | void apa102_setleds_pin(LED_TYPE *ledarray, uint16_t number_of_leds, uint8_t pinmask); |
| 46 | void apa102_setleds_rgbw(LED_TYPE *ledarray, uint16_t number_of_leds); | 45 | void 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 | ||
| 18 | static const unsigned char font[] PROGMEM = { | 18 | static 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 |
| 83 | static void toggle_e(void); | 82 | static 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 | /************************************************************************* | ||
| 92 | delay for a minimum of <us> microseconds | 90 | delay for a minimum of <us> microseconds |
| 93 | the number of loops is calculated at compile-time from MCU clock frequency | 91 | the 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 */ |
| 100 | static void toggle_e(void) | 97 | static 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 | /************************************************************************* |
| 110 | Low-level function to write byte to LCD controller | 105 | Low-level function to write byte to LCD controller |
| 111 | Input: data byte to write to LCD | 106 | Input: data byte to write to LCD |
| 112 | rs 1: write data | 107 | rs 1: write data |
| 113 | 0: write instruction | 108 | 0: write instruction |
| 114 | Returns: none | 109 | Returns: none |
| 115 | *************************************************************************/ | 110 | *************************************************************************/ |
| 116 | #if LCD_IO_MODE | 111 | #if LCD_IO_MODE |
| 117 | static void lcd_write(uint8_t data,uint8_t rs) | 112 | static 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 | /************************************************************************* |
| 192 | Low-level function to read byte from LCD controller | 184 | Low-level function to read byte from LCD controller |
| 193 | Input: rs 1: read data | 185 | Input: rs 1: read data |
| 194 | 0: read busy flag / address counter | 186 | 0: read busy flag / address counter |
| 195 | Returns: byte read from LCD controller | 187 | Returns: byte read from LCD controller |
| 196 | *************************************************************************/ | 188 | *************************************************************************/ |
| 197 | #if LCD_IO_MODE | 189 | #if LCD_IO_MODE |
| 198 | static uint8_t lcd_read(uint8_t rs) | 190 | static 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 | /************************************************************************* |
| 265 | loops while lcd is busy, returns address counter | 250 | loops 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 | /************************************************************************* |
| 285 | Move cursor to the start of next line or to the first line if the cursor | 270 | Move cursor to the start of next line or to the first line if the cursor |
| 286 | is already on the last line. | 271 | is already on the last line. |
| 287 | *************************************************************************/ | 272 | *************************************************************************/ |
| 288 | static inline void lcd_newline(uint8_t pos) | 273 | static 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 | |||
| 334 | Input: instruction to send to LCD controller, see HD44780 data sheet | 316 | Input: instruction to send to LCD controller, see HD44780 data sheet |
| 335 | Returns: none | 317 | Returns: none |
| 336 | *************************************************************************/ | 318 | *************************************************************************/ |
| 337 | void lcd_command(uint8_t cmd) | 319 | void 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 | /************************************************************************* |
| 345 | Send data byte to LCD controller | 325 | Send data byte to LCD controller |
| 346 | Input: data to send to LCD controller, see HD44780 data sheet | 326 | Input: data to send to LCD controller, see HD44780 data sheet |
| 347 | Returns: none | 327 | Returns: none |
| 348 | *************************************************************************/ | 328 | *************************************************************************/ |
| 349 | void lcd_data(uint8_t data) | 329 | void 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 | /************************************************************************* |
| 358 | Set cursor to specified position | 335 | Set cursor to specified position |
| 359 | Input: x horizontal position (0: left most position) | 336 | Input: x horizontal position (0: left most position) |
| 360 | y vertical position (0: first line) | 337 | y vertical position (0: first line) |
| 361 | Returns: none | 338 | Returns: none |
| 362 | *************************************************************************/ | 339 | *************************************************************************/ |
| 363 | void lcd_gotoxy(uint8_t x, uint8_t y) | 340 | void 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 | *************************************************************************/ |
| 390 | int lcd_getxy(void) | 365 | int lcd_getxy(void) { return lcd_waitbusy(); } |
| 391 | { | ||
| 392 | return lcd_waitbusy(); | ||
| 393 | } | ||
| 394 | |||
| 395 | 366 | ||
| 396 | /************************************************************************* | 367 | /************************************************************************* |
| 397 | Clear display and set cursor to home position | 368 | Clear display and set cursor to home position |
| 398 | *************************************************************************/ | 369 | *************************************************************************/ |
| 399 | void lcd_clrscr(void) | 370 | void lcd_clrscr(void) { lcd_command(1 << LCD_CLR); } |
| 400 | { | ||
| 401 | lcd_command(1<<LCD_CLR); | ||
| 402 | } | ||
| 403 | |||
| 404 | 371 | ||
| 405 | /************************************************************************* | 372 | /************************************************************************* |
| 406 | Set cursor to home position | 373 | Set cursor to home position |
| 407 | *************************************************************************/ | 374 | *************************************************************************/ |
| 408 | void lcd_home(void) | 375 | void lcd_home(void) { lcd_command(1 << LCD_HOME); } |
| 409 | { | ||
| 410 | lcd_command(1<<LCD_HOME); | ||
| 411 | } | ||
| 412 | |||
| 413 | 376 | ||
| 414 | /************************************************************************* | 377 | /************************************************************************* |
| 415 | Display character at current cursor position | 378 | Display character at current cursor position |
| 416 | Input: character to be displayed | 379 | Input: character to be displayed |
| 417 | Returns: none | 380 | Returns: none |
| 418 | *************************************************************************/ | 381 | *************************************************************************/ |
| 419 | void lcd_putc(char c) | 382 | void 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 | /************************************************************************* |
| 462 | Display string without auto linefeed | 419 | Display string without auto linefeed |
| 463 | Input: string to be displayed | 420 | Input: string to be displayed |
| 464 | Returns: none | 421 | Returns: 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 | /************************************************************************* |
| 479 | Display string from program memory without auto linefeed | 435 | Display string from program memory without auto linefeed |
| 480 | Input: string from program memory be be displayed | 436 | Input: string from program memory be be displayed |
| 481 | Returns: none | 437 | Returns: none |
| 482 | *************************************************************************/ | 438 | *************************************************************************/ |
| 483 | void lcd_puts_p(const char *progmem_s) | 439 | void 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 | /************************************************************************* |
| 496 | Initialize display and select type of cursor | 451 | Initialize display and select type of cursor |
| 497 | Input: dispAttr LCD_DISP_OFF display off | 452 | Input: 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 |
| 501 | Returns: none | 456 | Returns: none |
| 502 | *************************************************************************/ | 457 | *************************************************************************/ |
| 503 | void lcd_init(uint8_t dispAttr) | 458 | void 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 | */ |
| 293 | extern void lcd_init(uint8_t dispAttr); | 282 | extern 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 | */ |
| 300 | extern void lcd_clrscr(void); | 288 | extern 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 | */ |
| 307 | extern void lcd_home(void); | 294 | extern 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 | */ |
| 317 | extern void lcd_gotoxy(uint8_t x, uint8_t y); | 303 | extern 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 | */ |
| 325 | extern void lcd_putc(char c); | 310 | extern 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 | */ |
| 333 | extern void lcd_puts(const char *s); | 317 | extern 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 | */ |
| 342 | extern void lcd_puts_p(const char *progmem_s); | 325 | extern 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 | */ |
| 350 | extern void lcd_command(uint8_t cmd); | 332 | extern 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 | */ |
| 360 | extern void lcd_data(uint8_t data); | 341 | extern 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 | ||
| 33 | void i2c_init(void) { | 33 | void 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 | ||
| 50 | i2c_status_t i2c_start(uint8_t address, uint16_t timeout) { | 50 | i2c_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 | ||
| 89 | i2c_status_t i2c_write(uint8_t data, uint16_t timeout) { | 89 | i2c_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 | ||
| 109 | int16_t i2c_read_ack(uint16_t timeout) { | 109 | int16_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 | ||
| 124 | int16_t i2c_read_nack(uint16_t timeout) { | 124 | int16_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 | ||
| 139 | i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout) { | 139 | i2c_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 | ||
| 151 | i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) { | 151 | i2c_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 | ||
| 173 | i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) { | 173 | i2c_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 | ||
| 188 | i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) { | 188 | i2c_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 | ||
| 215 | error: | 215 | error: |
| 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 | ||
| 221 | void i2c_stop(void) { | 221 | void 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 @@ | |||
| 26 | typedef int16_t i2c_status_t; | 26 | typedef 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 | ||
| 35 | void i2c_init(void); | 35 | void i2c_init(void); |
| 36 | i2c_status_t i2c_start(uint8_t address, uint16_t timeout); | 36 | i2c_status_t i2c_start(uint8_t address, uint16_t timeout); |
| 37 | i2c_status_t i2c_write(uint8_t data, uint16_t timeout); | 37 | i2c_status_t i2c_write(uint8_t data, uint16_t timeout); |
| 38 | int16_t i2c_read_ack(uint16_t timeout); | 38 | int16_t i2c_read_ack(uint16_t timeout); |
| 39 | int16_t i2c_read_nack(uint16_t timeout); | 39 | int16_t i2c_read_nack(uint16_t timeout); |
| 40 | i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout); | 40 | i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout); |
| 41 | i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout); | 41 | i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout); |
| 42 | i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); | 42 | i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); |
| 43 | i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); | 43 | i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); |
| 44 | void i2c_stop(void); | 44 | void 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 @@ | |||
| 27 | volatile uint8_t i2c_slave_reg[I2C_SLAVE_REG_COUNT]; | 27 | volatile uint8_t i2c_slave_reg[I2C_SLAVE_REG_COUNT]; |
| 28 | 28 | ||
| 29 | static volatile uint8_t buffer_address; | 29 | static volatile uint8_t buffer_address; |
| 30 | static volatile bool slave_has_register_set = false; | 30 | static volatile bool slave_has_register_set = false; |
| 31 | 31 | ||
| 32 | void i2c_slave_init(uint8_t address){ | 32 | void 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 | ||
| 39 | void i2c_slave_stop(void){ | 39 | void 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 | ||
| 44 | ISR(TWI_vect){ | 44 | ISR(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]; | |||
| 30 | void i2c_slave_init(uint8_t address); | 30 | void i2c_slave_init(uint8_t address); |
| 31 | void i2c_slave_stop(void); | 31 | void 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 | ||
| 102 | static const uint8_t SDA = 2; | 102 | static const uint8_t SDA = 2; |
| 103 | static const uint8_t SCL = 3; | 103 | static 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 |
| 114 | static const uint8_t ADC0 = 18; | 114 | static const uint8_t ADC0 = 18; |
| 115 | static const uint8_t ADC1 = 19; | 115 | static const uint8_t ADC1 = 19; |
| 116 | static const uint8_t ADC2 = 20; | 116 | static const uint8_t ADC2 = 20; |
| 117 | static const uint8_t ADC3 = 21; | 117 | static const uint8_t ADC3 = 21; |
| 118 | static const uint8_t ADC4 = 22; | 118 | static const uint8_t ADC4 = 22; |
| 119 | static const uint8_t ADC5 = 23; | 119 | static const uint8_t ADC5 = 23; |
| 120 | static const uint8_t ADC6 = 24; // D4 | 120 | static const uint8_t ADC6 = 24; // D4 |
| 121 | static const uint8_t ADC7 = 25; // D6 | 121 | static const uint8_t ADC7 = 25; // D6 |
| 122 | static const uint8_t ADC8 = 26; // D8 | 122 | static const uint8_t ADC8 = 26; // D8 |
| 123 | static const uint8_t ADC9 = 27; // D9 | 123 | static const uint8_t ADC9 = 27; // D9 |
| 124 | static const uint8_t ADC10 = 28; // D10 | 124 | static const uint8_t ADC10 = 28; // D10 |
| 125 | static const uint8_t ADC11 = 29; // D12 | 125 | static 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 |
| 133 | extern const uint8_t PROGMEM analog_pin_to_channel_PGM[]; | 133 | extern 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) |
| 184 | const uint16_t PROGMEM port_to_mode_PGM[] = { | 184 | const 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 | ||
| 194 | const uint16_t PROGMEM port_to_output_PGM[] = { | 188 | const 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 | ||
| 204 | const uint16_t PROGMEM port_to_input_PGM[] = { | 192 | const 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 | ||
| 214 | const uint8_t PROGMEM digital_pin_to_port_PGM[] = { | 196 | const 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 | ||
| 251 | const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = { | 233 | const 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 | ||
| 288 | const uint8_t PROGMEM digital_pin_to_timer_PGM[] = { | 270 | const 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 | ||
| 325 | const uint8_t PROGMEM analog_pin_to_channel_PGM[] = { | 287 | const 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 |
| 28 | static uint8_t displaying; | 28 | static uint8_t displaying; |
| 29 | #endif | 29 | # endif |
| 30 | static uint16_t last_flush; | 30 | static uint16_t last_flush; |
| 31 | 31 | ||
| 32 | // Write command sequence. | 32 | // Write command sequence. |
| 33 | // Returns true on success. | 33 | // Returns true on success. |
| 34 | static inline bool _send_cmd1(uint8_t cmd) { | 34 | static 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; |
| 53 | done: | 53 | done: |
| 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 |
| 60 | static inline bool _send_cmd2(uint8_t cmd, uint8_t opr) { | 60 | static 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 |
| 69 | static inline bool _send_cmd3(uint8_t cmd, uint8_t opr1, uint8_t opr2) { | 69 | static 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 | ||
| 83 | static void clear_display(void) { | 92 | static 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 | ||
| 106 | done: | 115 | done: |
| 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 |
| 112 | static int8_t capture_sendchar(uint8_t c) { | 121 | static 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 | ||
| 123 | bool iota_gfx_init(void) { | 132 | bool 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 | ||
| 169 | done: | 177 | done: |
| 170 | return success; | 178 | return success; |
| 171 | } | 179 | } |
| 172 | 180 | ||
| 173 | bool iota_gfx_off(void) { | 181 | bool 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 | ||
| 179 | done: | 187 | done: |
| 180 | return success; | 188 | return success; |
| 181 | } | 189 | } |
| 182 | 190 | ||
| 183 | bool iota_gfx_on(void) { | 191 | bool 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 | ||
| 189 | done: | 197 | done: |
| 190 | return success; | 198 | return success; |
| 191 | } | 199 | } |
| 192 | 200 | ||
| 193 | void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c) { | 201 | void 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 | ||
| 206 | void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c) { | 213 | void 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 | ||
| 223 | void iota_gfx_write_char(uint8_t c) { | 230 | void iota_gfx_write_char(uint8_t c) { matrix_write_char(&display, c); } |
| 224 | matrix_write_char(&display, c); | ||
| 225 | } | ||
| 226 | 231 | ||
| 227 | void matrix_write(struct CharacterMatrix *matrix, const char *data) { | 232 | void 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 | ||
| 235 | void iota_gfx_write(const char *data) { | 240 | void iota_gfx_write(const char *data) { matrix_write(&display, data); } |
| 236 | matrix_write(&display, data); | ||
| 237 | } | ||
| 238 | 241 | ||
| 239 | void matrix_write_P(struct CharacterMatrix *matrix, const char *data) { | 242 | void 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 | ||
| 250 | void iota_gfx_write_P(const char *data) { | 253 | void iota_gfx_write_P(const char *data) { matrix_write_P(&display, data); } |
| 251 | matrix_write_P(&display, data); | ||
| 252 | } | ||
| 253 | 254 | ||
| 254 | void matrix_clear(struct CharacterMatrix *matrix) { | 255 | void 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 | ||
| 260 | void iota_gfx_clear_screen(void) { | 261 | void iota_gfx_clear_screen(void) { matrix_clear(&display); } |
| 261 | matrix_clear(&display); | ||
| 262 | } | ||
| 263 | 262 | ||
| 264 | void matrix_render(struct CharacterMatrix *matrix) { | 263 | void 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 | ||
| 299 | done: | 298 | done: |
| 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 | ||
| 306 | void iota_gfx_flush(void) { | 305 | void 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) {} |
| 311 | void iota_gfx_task_user(void) { | ||
| 312 | } | ||
| 313 | 308 | ||
| 314 | void iota_gfx_task(void) { | 309 | void 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 | ||
| 9 | enum ssd1306_cmds { | 9 | enum 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 | ||
| 64 | struct CharacterMatrix { | 64 | struct 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 | ||
| 70 | struct CharacterMatrix display; | 70 | struct CharacterMatrix display; |
| @@ -88,6 +88,4 @@ void matrix_write(struct CharacterMatrix *matrix, const char *data); | |||
| 88 | void matrix_write_P(struct CharacterMatrix *matrix, const char *data); | 88 | void matrix_write_P(struct CharacterMatrix *matrix, const char *data); |
| 89 | void matrix_render(struct CharacterMatrix *matrix); | 89 | void 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 |
| 32 | LED_TYPE led[DRIVER_LED_TOTAL]; | 32 | LED_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() \ |
| 48 | I2C_DDR &= ~ (1 << I2C_DAT);\ | 48 | I2C_DDR &= ~(1 << I2C_DAT); \ |
| 49 | I2C_PORT |= (1 << I2C_DAT); | 49 | I2C_PORT |= (1 << I2C_DAT); |
| 50 | #define I2C_DATA_LO()\ | 50 | # define I2C_DATA_LO() \ |
| 51 | I2C_DDR |= (1 << I2C_DAT);\ | 51 | I2C_DDR |= (1 << I2C_DAT); \ |
| 52 | I2C_PORT &= ~ (1 << I2C_DAT); | 52 | I2C_PORT &= ~(1 << I2C_DAT); |
| 53 | 53 | ||
| 54 | #define I2C_CLOCK_HI()\ | 54 | # define I2C_CLOCK_HI() \ |
| 55 | I2C_DDR &= ~ (1 << I2C_CLK);\ | 55 | I2C_DDR &= ~(1 << I2C_CLK); \ |
| 56 | I2C_PORT |= (1 << I2C_CLK); | 56 | I2C_PORT |= (1 << I2C_CLK); |
| 57 | #define I2C_CLOCK_LO()\ | 57 | # define I2C_CLOCK_LO() \ |
| 58 | I2C_DDR |= (1 << I2C_CLK);\ | 58 | I2C_DDR |= (1 << I2C_CLK); \ |
| 59 | I2C_PORT &= ~ (1 << I2C_CLK); | 59 | I2C_PORT &= ~(1 << I2C_CLK); |
| 60 | 60 | ||
| 61 | #define I2C_DELAY 1 | 61 | # define I2C_DELAY 1 |
| 62 | 62 | ||
| 63 | void I2C_WriteBit(unsigned char c) | 63 | void 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 | // |
| 90 | void I2C_Init(void) | 85 | void 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 | // |
| 102 | void I2C_Start(void) | 96 | void 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 | // |
| 117 | void I2C_Stop(void) | 110 | void 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 | // |
| 128 | unsigned char I2C_Write(unsigned char c) | 120 | unsigned 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 |
| 152 | void inline ws2812_setled(int i, uint8_t r, uint8_t g, uint8_t b) | 140 | void 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 | ||
| 159 | void ws2812_setled_all (uint8_t r, uint8_t g, uint8_t b) | 146 | void 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 |
| 170 | void inline ws2812_setleds(LED_TYPE *ledarray, uint16_t leds) | 156 | void 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 | ||
| 176 | void inline ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmask) | 161 | void 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 |
| 187 | void inline ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t leds) | 171 | void 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 | ||
| 224 | void ws2812_sendarray(uint8_t *data,uint16_t datlen) | 204 | void 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 | ||
| 290 | void inline ws2812_sendarray_mask(uint8_t *data,uint16_t datlen,uint8_t maskhi) | 267 | void 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) | ||
| 310 | w_nop1 | ||
| 311 | #endif | 286 | #endif |
| 312 | #if (w1_nops&2) | 287 | #if (w1_nops & 2) |
| 313 | w_nop2 | 288 | w_nop2 |
| 314 | #endif | 289 | #endif |
| 315 | #if (w1_nops&4) | 290 | #if (w1_nops & 4) |
| 316 | w_nop4 | 291 | w_nop4 |
| 317 | #endif | 292 | #endif |
| 318 | #if (w1_nops&8) | 293 | #if (w1_nops & 8) |
| 319 | w_nop8 | 294 | w_nop8 |
| 320 | #endif | 295 | #endif |
| 321 | #if (w1_nops&16) | 296 | #if (w1_nops & 16) |
| 322 | w_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) |
| 344 | w_nop1 | 319 | w_nop1 |
| 345 | #endif | 320 | #endif |
| 346 | #if (w3_nops&2) | 321 | #if (w3_nops & 2) |
| 347 | w_nop2 | 322 | w_nop2 |
| 348 | #endif | 323 | #endif |
| 349 | #if (w3_nops&4) | 324 | #if (w3_nops & 4) |
| 350 | w_nop4 | 325 | w_nop4 |
| 351 | #endif | 326 | #endif |
| 352 | #if (w3_nops&8) | 327 | #if (w3_nops & 8) |
| 353 | w_nop8 | 328 | w_nop8 |
| 354 | #endif | 329 | #endif |
| 355 | #if (w3_nops&16) | 330 | #if (w3_nops & 16) |
| 356 | w_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 |
| 46 | void ws2812_setled (int index, uint8_t r, uint8_t g, uint8_t b); | 46 | void ws2812_setled(int index, uint8_t r, uint8_t g, uint8_t b); |
| 47 | void ws2812_setled_all (uint8_t r, uint8_t g, uint8_t b); | 47 | void ws2812_setled_all(uint8_t r, uint8_t g, uint8_t b); |
| 48 | #endif | 48 | #endif |
| 49 | 49 | ||
| 50 | void ws2812_setleds (LED_TYPE *ledarray, uint16_t number_of_leds); | 50 | void ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds); |
| 51 | void ws2812_setleds_pin (LED_TYPE *ledarray, uint16_t number_of_leds,uint8_t pinmask); | 51 | void ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t number_of_leds, uint8_t pinmask); |
| 52 | void ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t number_of_leds); | 52 | void 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 | ||
| 61 | void ws2812_sendarray (uint8_t *array,uint16_t length); | 61 | void ws2812_sendarray(uint8_t *array, uint16_t length); |
| 62 | void ws2812_sendarray_mask(uint8_t *array,uint16_t length, uint8_t pinmask); | 62 | void 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_ */ |
