clang-format changes
This commit is contained in:
		
							parent
							
								
									61af76a10d
								
							
						
					
					
						commit
						b624f32f94
					
				
					 502 changed files with 32259 additions and 39062 deletions
				
			
		|  | @ -21,49 +21,38 @@ | |||
| #include <stdint.h> | ||||
| #include "analog.h" | ||||
| 
 | ||||
| static uint8_t aref = (1 << REFS0);  // default to AREF = Vcc
 | ||||
| 
 | ||||
| static uint8_t aref = (1<<REFS0); // default to AREF = Vcc
 | ||||
| 
 | ||||
| 
 | ||||
| void analogReference(uint8_t mode) | ||||
| { | ||||
| 	aref = mode & 0xC0; | ||||
| } | ||||
| 
 | ||||
| void analogReference(uint8_t mode) { aref = mode & 0xC0; } | ||||
| 
 | ||||
| // Arduino compatible pin input
 | ||||
| int16_t analogRead(uint8_t pin) | ||||
| { | ||||
| int16_t analogRead(uint8_t pin) { | ||||
| #if defined(__AVR_ATmega32U4__) | ||||
| 	static const uint8_t PROGMEM pin_to_mux[] = { | ||||
| 		0x00, 0x01, 0x04, 0x05, 0x06, 0x07, | ||||
| 		0x25, 0x24, 0x23, 0x22, 0x21, 0x20}; | ||||
| 	if (pin >= 12) return 0; | ||||
| 	return adc_read(pgm_read_byte(pin_to_mux + pin)); | ||||
|     static const uint8_t PROGMEM pin_to_mux[] = {0x00, 0x01, 0x04, 0x05, 0x06, 0x07, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20}; | ||||
|     if (pin >= 12) return 0; | ||||
|     return adc_read(pgm_read_byte(pin_to_mux + pin)); | ||||
| #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) | ||||
| 	if (pin >= 8) return 0; | ||||
| 	return adc_read(pin); | ||||
|     if (pin >= 8) return 0; | ||||
|     return adc_read(pin); | ||||
| #else | ||||
| 	return 0; | ||||
|     return 0; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| // Mux input
 | ||||
| int16_t adc_read(uint8_t mux) | ||||
| { | ||||
| int16_t adc_read(uint8_t mux) { | ||||
| #if defined(__AVR_AT90USB162__) | ||||
| 	return 0; | ||||
|     return 0; | ||||
| #else | ||||
| 	uint8_t low; | ||||
|     uint8_t low; | ||||
| 
 | ||||
| 	ADCSRA = (1<<ADEN) | ADC_PRESCALER;		// enable ADC
 | ||||
| 	ADCSRB = (1<<ADHSM) | (mux & 0x20);		// high speed mode
 | ||||
| 	ADMUX = aref | (mux & 0x1F);			// configure mux input
 | ||||
| 	ADCSRA = (1<<ADEN) | ADC_PRESCALER | (1<<ADSC);	// start the conversion
 | ||||
| 	while (ADCSRA & (1<<ADSC)) ;			// wait for result
 | ||||
| 	low = ADCL;					// must read LSB first
 | ||||
| 	return (ADCH << 8) | low;			// must read MSB only once!
 | ||||
|     ADCSRA = (1 << ADEN) | ADC_PRESCALER;                // enable ADC
 | ||||
|     ADCSRB = (1 << ADHSM) | (mux & 0x20);                // high speed mode
 | ||||
|     ADMUX  = aref | (mux & 0x1F);                        // configure mux input
 | ||||
|     ADCSRA = (1 << ADEN) | ADC_PRESCALER | (1 << ADSC);  // start the conversion
 | ||||
|     while (ADCSRA & (1 << ADSC)) | ||||
|         ;                      // wait for result
 | ||||
|     low = ADCL;                // must read LSB first
 | ||||
|     return (ADCH << 8) | low;  // must read MSB only once!
 | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -19,34 +19,34 @@ | |||
| 
 | ||||
| #include <stdint.h> | ||||
| 
 | ||||
| void analogReference(uint8_t mode); | ||||
| void    analogReference(uint8_t mode); | ||||
| int16_t analogRead(uint8_t pin); | ||||
| int16_t adc_read(uint8_t mux); | ||||
| 
 | ||||
| #define ADC_REF_POWER     (1<<REFS0) | ||||
| #define ADC_REF_INTERNAL  ((1<<REFS1) | (1<<REFS0)) | ||||
| #define ADC_REF_EXTERNAL  (0) | ||||
| #define ADC_REF_POWER (1 << REFS0) | ||||
| #define ADC_REF_INTERNAL ((1 << REFS1) | (1 << REFS0)) | ||||
| #define ADC_REF_EXTERNAL (0) | ||||
| 
 | ||||
| // These prescaler values are for high speed mode, ADHSM = 1
 | ||||
| #if F_CPU == 16000000L | ||||
| #define ADC_PRESCALER ((1<<ADPS2) | (1<<ADPS1)) | ||||
| #    define ADC_PRESCALER ((1 << ADPS2) | (1 << ADPS1)) | ||||
| #elif F_CPU == 8000000L | ||||
| #define ADC_PRESCALER ((1<<ADPS2) | (1<<ADPS0)) | ||||
| #    define ADC_PRESCALER ((1 << ADPS2) | (1 << ADPS0)) | ||||
| #elif F_CPU == 4000000L | ||||
| #define ADC_PRESCALER ((1<<ADPS2)) | ||||
| #    define ADC_PRESCALER ((1 << ADPS2)) | ||||
| #elif F_CPU == 2000000L | ||||
| #define ADC_PRESCALER ((1<<ADPS1) | (1<<ADPS0)) | ||||
| #    define ADC_PRESCALER ((1 << ADPS1) | (1 << ADPS0)) | ||||
| #elif F_CPU == 1000000L | ||||
| #define ADC_PRESCALER ((1<<ADPS1)) | ||||
| #    define ADC_PRESCALER ((1 << ADPS1)) | ||||
| #else | ||||
| #define ADC_PRESCALER ((1<<ADPS0)) | ||||
| #    define ADC_PRESCALER ((1 << ADPS0)) | ||||
| #endif | ||||
| 
 | ||||
| // some avr-libc versions do not properly define ADHSM
 | ||||
| #if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) | ||||
| #if !defined(ADHSM) | ||||
| #define ADHSM (7) | ||||
| #endif | ||||
| #    if !defined(ADHSM) | ||||
| #        define ADHSM (7) | ||||
| #    endif | ||||
| #endif | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
							
								
								
									
										157
									
								
								drivers/avr/apa102.c
									
										
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										157
									
								
								drivers/avr/apa102.c
									
										
									
									
									
										
										
										Executable file → Normal file
									
								
							|  | @ -1,24 +1,24 @@ | |||
| /*
 | ||||
| * APA102 lib V1.0a | ||||
| * | ||||
| * Controls APA102 RGB-LEDs | ||||
| * Author: Mikkel (Duckle29 on github) | ||||
| * | ||||
| * Dec 22th, 2017  v1.0a Initial Version | ||||
| * | ||||
| * This program is free software: you can redistribute it and/or modify | ||||
| * it under the terms of the GNU General Public License as published by | ||||
| * the Free Software Foundation, either version 2 of the License, or | ||||
| * (at your option) any later version. | ||||
| * | ||||
| * This program is distributed in the hope that it will be useful, | ||||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| * GNU General Public License for more details. | ||||
| * | ||||
| * You should have received a copy of the GNU General Public License | ||||
| * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
| */ | ||||
|  * APA102 lib V1.0a | ||||
|  * | ||||
|  * Controls APA102 RGB-LEDs | ||||
|  * Author: Mikkel (Duckle29 on github) | ||||
|  * | ||||
|  * Dec 22th, 2017  v1.0a Initial Version | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 2 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| 
 | ||||
| #include "apa102.h" | ||||
| #include <avr/interrupt.h> | ||||
|  | @ -27,75 +27,70 @@ | |||
| #include "debug.h" | ||||
| 
 | ||||
| // Setleds for standard RGB
 | ||||
| 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)); | ||||
| 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)); } | ||||
| 
 | ||||
| void static inline apa102_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmask_DI, uint8_t pinmask_CLK) { | ||||
|     pinMode(RGB_DI_PIN, PinDirectionOutput); | ||||
|     pinMode(RGB_CLK_PIN, PinDirectionOutput); | ||||
| 
 | ||||
|     apa102_send_array((uint8_t *)ledarray, leds) | ||||
| } | ||||
| 
 | ||||
| void static inline apa102_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmask_DI, uint8_t pinmask_CLK){ | ||||
|   pinMode(RGB_DI_PIN, PinDirectionOutput); | ||||
|   pinMode(RGB_CLK_PIN, PinDirectionOutput); | ||||
| 
 | ||||
|   apa102_send_array((uint8_t*)ledarray,leds) | ||||
| void apa102_send_array(uint8_t *data, uint16_t leds) {  // Data is struct of 3 bytes. RGB - leds is number of leds in data
 | ||||
|     apa102_start_frame(); | ||||
|     while (leds--) { | ||||
|         apa102_send_frame(0xFF000000 | (data->b << 16) | (data->g << 8) | data->r); | ||||
|         data++; | ||||
|     } | ||||
|     apa102_end_frame(leds); | ||||
| } | ||||
| 
 | ||||
| void apa102_send_array(uint8_t *data, uint16_t leds){ // Data is struct of 3 bytes. RGB - leds is number of leds in data
 | ||||
|   apa102_start_frame(); | ||||
|   while(leds--){ | ||||
|     apa102_send_frame(0xFF000000 | (data->b << 16) | (data->g << 8) | data->r); | ||||
|     data++; | ||||
|   } | ||||
|   apa102_end_frame(leds); | ||||
| void apa102_send_frame(uint32_t frame) { | ||||
|     for (uint32_t i = 0xFF; i > 0;) { | ||||
|         apa102_send_byte(frame & i); | ||||
|         i = i << 8; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void apa102_send_frame(uint32_t frame){ | ||||
|   for(uint32_t i=0xFF; i>0;){ | ||||
|     apa102_send_byte(frame & i); | ||||
|     i = i << 8; | ||||
|   } | ||||
| void apa102_start_frame() { apa102_send_frame(0); } | ||||
| 
 | ||||
| void apa102_end_frame(uint16_t leds) { | ||||
|     // This function has been taken from: https://github.com/pololu/apa102-arduino/blob/master/APA102.h
 | ||||
|     // and adapted. The code is MIT licensed. I think thats compatible?
 | ||||
| 
 | ||||
|     // We need to send some more bytes to ensure that all the LEDs in the
 | ||||
|     // chain see their new color and start displaying it.
 | ||||
|     //
 | ||||
|     // The data stream seen by the last LED in the chain will be delayed by
 | ||||
|     // (count - 1) clock edges, because each LED before it inverts the clock
 | ||||
|     // line and delays the data by one clock edge.  Therefore, to make sure
 | ||||
|     // the last LED actually receives the data we wrote, the number of extra
 | ||||
|     // edges we send at the end of the frame must be at least (count - 1).
 | ||||
|     // For the APA102C, that is sufficient.
 | ||||
|     //
 | ||||
|     // The SK9822 only updates after it sees 32 zero bits followed by one more
 | ||||
|     // rising edge.  To avoid having the update time depend on the color of
 | ||||
|     // the last LED, we send a dummy 0xFF byte.  (Unfortunately, this means
 | ||||
|     // that partial updates of the beginning of an LED strip are not possible;
 | ||||
|     // the LED after the last one you are trying to update will be black.)
 | ||||
|     // After that, to ensure that the last LED in the chain sees 32 zero bits
 | ||||
|     // and a rising edge, we need to send at least 65 + (count - 1) edges.  It
 | ||||
|     // is sufficent and simpler to just send (5 + count/16) bytes of zeros.
 | ||||
|     //
 | ||||
|     // We are ignoring the specification for the end frame in the APA102/SK9822
 | ||||
|     // datasheets because it does not actually ensure that all the LEDs will
 | ||||
|     // start displaying their new colors right away.
 | ||||
| 
 | ||||
|     apa102_send_byte(0xFF); | ||||
|     for (uint16_t i = 0; i < 5 + leds / 16; i++) { | ||||
|         apa102_send_byte(0); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void apa102_start_frame(){ | ||||
|   apa102_send_frame(0); | ||||
| } | ||||
| 
 | ||||
| void apa102_end_frame(uint16_t leds) | ||||
| { | ||||
|   // This function has been taken from: https://github.com/pololu/apa102-arduino/blob/master/APA102.h
 | ||||
|   // and adapted. The code is MIT licensed. I think thats compatible?
 | ||||
| 
 | ||||
|   // We need to send some more bytes to ensure that all the LEDs in the
 | ||||
|   // chain see their new color and start displaying it.
 | ||||
|   //
 | ||||
|   // The data stream seen by the last LED in the chain will be delayed by
 | ||||
|   // (count - 1) clock edges, because each LED before it inverts the clock
 | ||||
|   // line and delays the data by one clock edge.  Therefore, to make sure
 | ||||
|   // the last LED actually receives the data we wrote, the number of extra
 | ||||
|   // edges we send at the end of the frame must be at least (count - 1).
 | ||||
|   // For the APA102C, that is sufficient.
 | ||||
|   //
 | ||||
|   // The SK9822 only updates after it sees 32 zero bits followed by one more
 | ||||
|   // rising edge.  To avoid having the update time depend on the color of
 | ||||
|   // the last LED, we send a dummy 0xFF byte.  (Unfortunately, this means
 | ||||
|   // that partial updates of the beginning of an LED strip are not possible;
 | ||||
|   // the LED after the last one you are trying to update will be black.)
 | ||||
|   // After that, to ensure that the last LED in the chain sees 32 zero bits
 | ||||
|   // and a rising edge, we need to send at least 65 + (count - 1) edges.  It
 | ||||
|   // is sufficent and simpler to just send (5 + count/16) bytes of zeros.
 | ||||
|   //
 | ||||
|   // We are ignoring the specification for the end frame in the APA102/SK9822
 | ||||
|   // datasheets because it does not actually ensure that all the LEDs will
 | ||||
|   // start displaying their new colors right away.
 | ||||
| 
 | ||||
|   apa102_send_byte(0xFF); | ||||
|   for (uint16_t i = 0; i < 5 + leds / 16; i++){ | ||||
|     apa102_send_byte(0); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void apa102_send_byte(uint8_t byte){ | ||||
|   uint8_t i; | ||||
|   for (i = 0; i < 8; i++){ | ||||
| void apa102_send_byte(uint8_t byte) { | ||||
|     uint8_t i; | ||||
|     for (i = 0; i < 8; i++) { | ||||
|     digitalWrite(RGB_DI_PIN, !!(byte & (1 << (7-i))); | ||||
|     digitalWrite(RGB_CLK_PIN, PinLevelHigh); | ||||
|   } | ||||
|     } | ||||
| } | ||||
|  |  | |||
							
								
								
									
										5
									
								
								drivers/avr/apa102.h
									
										
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										5
									
								
								drivers/avr/apa102.h
									
										
									
									
									
										
										
										Executable file → Normal file
									
								
							|  | @ -27,7 +27,6 @@ | |||
| 
 | ||||
| #include "color.h" | ||||
| 
 | ||||
| 
 | ||||
| /* User Interface
 | ||||
|  * | ||||
|  * Input: | ||||
|  | @ -41,6 +40,6 @@ | |||
|  *         - Wait 50<EFBFBD>s to reset the LEDs | ||||
|  */ | ||||
| 
 | ||||
| void apa102_setleds     (LED_TYPE *ledarray, uint16_t number_of_leds); | ||||
| void apa102_setleds_pin (LED_TYPE *ledarray, uint16_t number_of_leds,uint8_t pinmask); | ||||
| void apa102_setleds(LED_TYPE *ledarray, uint16_t number_of_leds); | ||||
| void apa102_setleds_pin(LED_TYPE *ledarray, uint16_t number_of_leds, uint8_t pinmask); | ||||
| void apa102_setleds_rgbw(LED_TYPE *ledarray, uint16_t number_of_leds); | ||||
|  |  | |||
|  | @ -5,272 +5,30 @@ | |||
| #define FONT5X7_H | ||||
| 
 | ||||
| #ifdef __AVR__ | ||||
|  #include <avr/io.h> | ||||
|  #include <avr/pgmspace.h> | ||||
| #    include <avr/io.h> | ||||
| #    include <avr/pgmspace.h> | ||||
| #elif defined(ESP8266) | ||||
|  #include <pgmspace.h> | ||||
| #    include <pgmspace.h> | ||||
| #else | ||||
|  #define PROGMEM | ||||
| #    define PROGMEM | ||||
| #endif | ||||
| 
 | ||||
| // Standard ASCII 5x7 font
 | ||||
| 
 | ||||
| static const unsigned char font[] PROGMEM = { | ||||
| 	0x00, 0x00, 0x00, 0x00, 0x00, | ||||
| 	0x3E, 0x5B, 0x4F, 0x5B, 0x3E, | ||||
| 	0x3E, 0x6B, 0x4F, 0x6B, 0x3E, | ||||
| 	0x1C, 0x3E, 0x7C, 0x3E, 0x1C, | ||||
| 	0x18, 0x3C, 0x7E, 0x3C, 0x18, | ||||
| 	0x1C, 0x57, 0x7D, 0x57, 0x1C, | ||||
| 	0x1C, 0x5E, 0x7F, 0x5E, 0x1C, | ||||
| 	0x00, 0x18, 0x3C, 0x18, 0x00, | ||||
| 	0xFF, 0xE7, 0xC3, 0xE7, 0xFF, | ||||
| 	0x00, 0x18, 0x24, 0x18, 0x00, | ||||
| 	0xFF, 0xE7, 0xDB, 0xE7, 0xFF, | ||||
| 	0x30, 0x48, 0x3A, 0x06, 0x0E, | ||||
| 	0x26, 0x29, 0x79, 0x29, 0x26, | ||||
| 	0x40, 0x7F, 0x05, 0x05, 0x07, | ||||
| 	0x40, 0x7F, 0x05, 0x25, 0x3F, | ||||
| 	0x5A, 0x3C, 0xE7, 0x3C, 0x5A, | ||||
| 	0x7F, 0x3E, 0x1C, 0x1C, 0x08, | ||||
| 	0x08, 0x1C, 0x1C, 0x3E, 0x7F, | ||||
| 	0x14, 0x22, 0x7F, 0x22, 0x14, | ||||
| 	0x5F, 0x5F, 0x00, 0x5F, 0x5F, | ||||
| 	0x06, 0x09, 0x7F, 0x01, 0x7F, | ||||
| 	0x00, 0x66, 0x89, 0x95, 0x6A, | ||||
| 	0x60, 0x60, 0x60, 0x60, 0x60, | ||||
| 	0x94, 0xA2, 0xFF, 0xA2, 0x94, | ||||
| 	0x08, 0x04, 0x7E, 0x04, 0x08, | ||||
| 	0x10, 0x20, 0x7E, 0x20, 0x10, | ||||
| 	0x08, 0x08, 0x2A, 0x1C, 0x08, | ||||
| 	0x08, 0x1C, 0x2A, 0x08, 0x08, | ||||
| 	0x1E, 0x10, 0x10, 0x10, 0x10, | ||||
| 	0x0C, 0x1E, 0x0C, 0x1E, 0x0C, | ||||
| 	0x30, 0x38, 0x3E, 0x38, 0x30, | ||||
| 	0x06, 0x0E, 0x3E, 0x0E, 0x06, | ||||
| 	0x00, 0x00, 0x00, 0x00, 0x00, | ||||
| 	0x00, 0x00, 0x5F, 0x00, 0x00, | ||||
| 	0x00, 0x07, 0x00, 0x07, 0x00, | ||||
| 	0x14, 0x7F, 0x14, 0x7F, 0x14, | ||||
| 	0x24, 0x2A, 0x7F, 0x2A, 0x12, | ||||
| 	0x23, 0x13, 0x08, 0x64, 0x62, | ||||
| 	0x36, 0x49, 0x56, 0x20, 0x50, | ||||
| 	0x00, 0x08, 0x07, 0x03, 0x00, | ||||
| 	0x00, 0x1C, 0x22, 0x41, 0x00, | ||||
| 	0x00, 0x41, 0x22, 0x1C, 0x00, | ||||
| 	0x2A, 0x1C, 0x7F, 0x1C, 0x2A, | ||||
| 	0x08, 0x08, 0x3E, 0x08, 0x08, | ||||
| 	0x00, 0x80, 0x70, 0x30, 0x00, | ||||
| 	0x08, 0x08, 0x08, 0x08, 0x08, | ||||
| 	0x00, 0x00, 0x60, 0x60, 0x00, | ||||
| 	0x20, 0x10, 0x08, 0x04, 0x02, | ||||
| 	0x3E, 0x51, 0x49, 0x45, 0x3E, | ||||
| 	0x00, 0x42, 0x7F, 0x40, 0x00, | ||||
| 	0x72, 0x49, 0x49, 0x49, 0x46, | ||||
| 	0x21, 0x41, 0x49, 0x4D, 0x33, | ||||
| 	0x18, 0x14, 0x12, 0x7F, 0x10, | ||||
| 	0x27, 0x45, 0x45, 0x45, 0x39, | ||||
| 	0x3C, 0x4A, 0x49, 0x49, 0x31, | ||||
| 	0x41, 0x21, 0x11, 0x09, 0x07, | ||||
| 	0x36, 0x49, 0x49, 0x49, 0x36, | ||||
| 	0x46, 0x49, 0x49, 0x29, 0x1E, | ||||
| 	0x00, 0x00, 0x14, 0x00, 0x00, | ||||
| 	0x00, 0x40, 0x34, 0x00, 0x00, | ||||
| 	0x00, 0x08, 0x14, 0x22, 0x41, | ||||
| 	0x14, 0x14, 0x14, 0x14, 0x14, | ||||
| 	0x00, 0x41, 0x22, 0x14, 0x08, | ||||
| 	0x02, 0x01, 0x59, 0x09, 0x06, | ||||
| 	0x3E, 0x41, 0x5D, 0x59, 0x4E, | ||||
| 	0x7C, 0x12, 0x11, 0x12, 0x7C, | ||||
| 	0x7F, 0x49, 0x49, 0x49, 0x36, | ||||
| 	0x3E, 0x41, 0x41, 0x41, 0x22, | ||||
| 	0x7F, 0x41, 0x41, 0x41, 0x3E, | ||||
| 	0x7F, 0x49, 0x49, 0x49, 0x41, | ||||
| 	0x7F, 0x09, 0x09, 0x09, 0x01, | ||||
| 	0x3E, 0x41, 0x41, 0x51, 0x73, | ||||
| 	0x7F, 0x08, 0x08, 0x08, 0x7F, | ||||
| 	0x00, 0x41, 0x7F, 0x41, 0x00, | ||||
| 	0x20, 0x40, 0x41, 0x3F, 0x01, | ||||
| 	0x7F, 0x08, 0x14, 0x22, 0x41, | ||||
| 	0x7F, 0x40, 0x40, 0x40, 0x40, | ||||
| 	0x7F, 0x02, 0x1C, 0x02, 0x7F, | ||||
| 	0x7F, 0x04, 0x08, 0x10, 0x7F, | ||||
| 	0x3E, 0x41, 0x41, 0x41, 0x3E, | ||||
| 	0x7F, 0x09, 0x09, 0x09, 0x06, | ||||
| 	0x3E, 0x41, 0x51, 0x21, 0x5E, | ||||
| 	0x7F, 0x09, 0x19, 0x29, 0x46, | ||||
| 	0x26, 0x49, 0x49, 0x49, 0x32, | ||||
| 	0x03, 0x01, 0x7F, 0x01, 0x03, | ||||
| 	0x3F, 0x40, 0x40, 0x40, 0x3F, | ||||
| 	0x1F, 0x20, 0x40, 0x20, 0x1F, | ||||
| 	0x3F, 0x40, 0x38, 0x40, 0x3F, | ||||
| 	0x63, 0x14, 0x08, 0x14, 0x63, | ||||
| 	0x03, 0x04, 0x78, 0x04, 0x03, | ||||
| 	0x61, 0x59, 0x49, 0x4D, 0x43, | ||||
| 	0x00, 0x7F, 0x41, 0x41, 0x41, | ||||
| 	0x02, 0x04, 0x08, 0x10, 0x20, | ||||
| 	0x00, 0x41, 0x41, 0x41, 0x7F, | ||||
| 	0x04, 0x02, 0x01, 0x02, 0x04, | ||||
| 	0x40, 0x40, 0x40, 0x40, 0x40, | ||||
| 	0x00, 0x03, 0x07, 0x08, 0x00, | ||||
| 	0x20, 0x54, 0x54, 0x78, 0x40, | ||||
| 	0x7F, 0x28, 0x44, 0x44, 0x38, | ||||
| 	0x38, 0x44, 0x44, 0x44, 0x28, | ||||
| 	0x38, 0x44, 0x44, 0x28, 0x7F, | ||||
| 	0x38, 0x54, 0x54, 0x54, 0x18, | ||||
| 	0x00, 0x08, 0x7E, 0x09, 0x02, | ||||
| 	0x18, 0xA4, 0xA4, 0x9C, 0x78, | ||||
| 	0x7F, 0x08, 0x04, 0x04, 0x78, | ||||
| 	0x00, 0x44, 0x7D, 0x40, 0x00, | ||||
| 	0x20, 0x40, 0x40, 0x3D, 0x00, | ||||
| 	0x7F, 0x10, 0x28, 0x44, 0x00, | ||||
| 	0x00, 0x41, 0x7F, 0x40, 0x00, | ||||
| 	0x7C, 0x04, 0x78, 0x04, 0x78, | ||||
| 	0x7C, 0x08, 0x04, 0x04, 0x78, | ||||
| 	0x38, 0x44, 0x44, 0x44, 0x38, | ||||
| 	0xFC, 0x18, 0x24, 0x24, 0x18, | ||||
| 	0x18, 0x24, 0x24, 0x18, 0xFC, | ||||
| 	0x7C, 0x08, 0x04, 0x04, 0x08, | ||||
| 	0x48, 0x54, 0x54, 0x54, 0x24, | ||||
| 	0x04, 0x04, 0x3F, 0x44, 0x24, | ||||
| 	0x3C, 0x40, 0x40, 0x20, 0x7C, | ||||
| 	0x1C, 0x20, 0x40, 0x20, 0x1C, | ||||
| 	0x3C, 0x40, 0x30, 0x40, 0x3C, | ||||
| 	0x44, 0x28, 0x10, 0x28, 0x44, | ||||
| 	0x4C, 0x90, 0x90, 0x90, 0x7C, | ||||
| 	0x44, 0x64, 0x54, 0x4C, 0x44, | ||||
| 	0x00, 0x08, 0x36, 0x41, 0x00, | ||||
| 	0x00, 0x00, 0x77, 0x00, 0x00, | ||||
| 	0x00, 0x41, 0x36, 0x08, 0x00, | ||||
| 	0x02, 0x01, 0x02, 0x04, 0x02, | ||||
| 	0x3C, 0x26, 0x23, 0x26, 0x3C, | ||||
| 	0x1E, 0xA1, 0xA1, 0x61, 0x12, | ||||
| 	0x3A, 0x40, 0x40, 0x20, 0x7A, | ||||
| 	0x38, 0x54, 0x54, 0x55, 0x59, | ||||
| 	0x21, 0x55, 0x55, 0x79, 0x41, | ||||
| 	0x22, 0x54, 0x54, 0x78, 0x42, // a-umlaut
 | ||||
| 	0x21, 0x55, 0x54, 0x78, 0x40, | ||||
| 	0x20, 0x54, 0x55, 0x79, 0x40, | ||||
| 	0x0C, 0x1E, 0x52, 0x72, 0x12, | ||||
| 	0x39, 0x55, 0x55, 0x55, 0x59, | ||||
| 	0x39, 0x54, 0x54, 0x54, 0x59, | ||||
| 	0x39, 0x55, 0x54, 0x54, 0x58, | ||||
| 	0x00, 0x00, 0x45, 0x7C, 0x41, | ||||
| 	0x00, 0x02, 0x45, 0x7D, 0x42, | ||||
| 	0x00, 0x01, 0x45, 0x7C, 0x40, | ||||
| 	0x7D, 0x12, 0x11, 0x12, 0x7D, // A-umlaut
 | ||||
| 	0xF0, 0x28, 0x25, 0x28, 0xF0, | ||||
| 	0x7C, 0x54, 0x55, 0x45, 0x00, | ||||
| 	0x20, 0x54, 0x54, 0x7C, 0x54, | ||||
| 	0x7C, 0x0A, 0x09, 0x7F, 0x49, | ||||
| 	0x32, 0x49, 0x49, 0x49, 0x32, | ||||
| 	0x3A, 0x44, 0x44, 0x44, 0x3A, // o-umlaut
 | ||||
| 	0x32, 0x4A, 0x48, 0x48, 0x30, | ||||
| 	0x3A, 0x41, 0x41, 0x21, 0x7A, | ||||
| 	0x3A, 0x42, 0x40, 0x20, 0x78, | ||||
| 	0x00, 0x9D, 0xA0, 0xA0, 0x7D, | ||||
| 	0x3D, 0x42, 0x42, 0x42, 0x3D, // O-umlaut
 | ||||
| 	0x3D, 0x40, 0x40, 0x40, 0x3D, | ||||
| 	0x3C, 0x24, 0xFF, 0x24, 0x24, | ||||
| 	0x48, 0x7E, 0x49, 0x43, 0x66, | ||||
| 	0x2B, 0x2F, 0xFC, 0x2F, 0x2B, | ||||
| 	0xFF, 0x09, 0x29, 0xF6, 0x20, | ||||
| 	0xC0, 0x88, 0x7E, 0x09, 0x03, | ||||
| 	0x20, 0x54, 0x54, 0x79, 0x41, | ||||
| 	0x00, 0x00, 0x44, 0x7D, 0x41, | ||||
| 	0x30, 0x48, 0x48, 0x4A, 0x32, | ||||
| 	0x38, 0x40, 0x40, 0x22, 0x7A, | ||||
| 	0x00, 0x7A, 0x0A, 0x0A, 0x72, | ||||
| 	0x7D, 0x0D, 0x19, 0x31, 0x7D, | ||||
| 	0x26, 0x29, 0x29, 0x2F, 0x28, | ||||
| 	0x26, 0x29, 0x29, 0x29, 0x26, | ||||
| 	0x30, 0x48, 0x4D, 0x40, 0x20, | ||||
| 	0x38, 0x08, 0x08, 0x08, 0x08, | ||||
| 	0x08, 0x08, 0x08, 0x08, 0x38, | ||||
| 	0x2F, 0x10, 0xC8, 0xAC, 0xBA, | ||||
| 	0x2F, 0x10, 0x28, 0x34, 0xFA, | ||||
| 	0x00, 0x00, 0x7B, 0x00, 0x00, | ||||
| 	0x08, 0x14, 0x2A, 0x14, 0x22, | ||||
| 	0x22, 0x14, 0x2A, 0x14, 0x08, | ||||
| 	0x55, 0x00, 0x55, 0x00, 0x55, // #176 (25% block) missing in old code
 | ||||
| 	0xAA, 0x55, 0xAA, 0x55, 0xAA, // 50% block
 | ||||
| 	0xFF, 0x55, 0xFF, 0x55, 0xFF, // 75% block
 | ||||
| 	0x00, 0x00, 0x00, 0xFF, 0x00, | ||||
| 	0x10, 0x10, 0x10, 0xFF, 0x00, | ||||
| 	0x14, 0x14, 0x14, 0xFF, 0x00, | ||||
| 	0x10, 0x10, 0xFF, 0x00, 0xFF, | ||||
| 	0x10, 0x10, 0xF0, 0x10, 0xF0, | ||||
| 	0x14, 0x14, 0x14, 0xFC, 0x00, | ||||
| 	0x14, 0x14, 0xF7, 0x00, 0xFF, | ||||
| 	0x00, 0x00, 0xFF, 0x00, 0xFF, | ||||
| 	0x14, 0x14, 0xF4, 0x04, 0xFC, | ||||
| 	0x14, 0x14, 0x17, 0x10, 0x1F, | ||||
| 	0x10, 0x10, 0x1F, 0x10, 0x1F, | ||||
| 	0x14, 0x14, 0x14, 0x1F, 0x00, | ||||
| 	0x10, 0x10, 0x10, 0xF0, 0x00, | ||||
| 	0x00, 0x00, 0x00, 0x1F, 0x10, | ||||
| 	0x10, 0x10, 0x10, 0x1F, 0x10, | ||||
| 	0x10, 0x10, 0x10, 0xF0, 0x10, | ||||
| 	0x00, 0x00, 0x00, 0xFF, 0x10, | ||||
| 	0x10, 0x10, 0x10, 0x10, 0x10, | ||||
| 	0x10, 0x10, 0x10, 0xFF, 0x10, | ||||
| 	0x00, 0x00, 0x00, 0xFF, 0x14, | ||||
| 	0x00, 0x00, 0xFF, 0x00, 0xFF, | ||||
| 	0x00, 0x00, 0x1F, 0x10, 0x17, | ||||
| 	0x00, 0x00, 0xFC, 0x04, 0xF4, | ||||
| 	0x14, 0x14, 0x17, 0x10, 0x17, | ||||
| 	0x14, 0x14, 0xF4, 0x04, 0xF4, | ||||
| 	0x00, 0x00, 0xFF, 0x00, 0xF7, | ||||
| 	0x14, 0x14, 0x14, 0x14, 0x14, | ||||
| 	0x14, 0x14, 0xF7, 0x00, 0xF7, | ||||
| 	0x14, 0x14, 0x14, 0x17, 0x14, | ||||
| 	0x10, 0x10, 0x1F, 0x10, 0x1F, | ||||
| 	0x14, 0x14, 0x14, 0xF4, 0x14, | ||||
| 	0x10, 0x10, 0xF0, 0x10, 0xF0, | ||||
| 	0x00, 0x00, 0x1F, 0x10, 0x1F, | ||||
| 	0x00, 0x00, 0x00, 0x1F, 0x14, | ||||
| 	0x00, 0x00, 0x00, 0xFC, 0x14, | ||||
| 	0x00, 0x00, 0xF0, 0x10, 0xF0, | ||||
| 	0x10, 0x10, 0xFF, 0x10, 0xFF, | ||||
| 	0x14, 0x14, 0x14, 0xFF, 0x14, | ||||
| 	0x10, 0x10, 0x10, 0x1F, 0x00, | ||||
| 	0x00, 0x00, 0x00, 0xF0, 0x10, | ||||
| 	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||||
| 	0xF0, 0xF0, 0xF0, 0xF0, 0xF0, | ||||
| 	0xFF, 0xFF, 0xFF, 0x00, 0x00, | ||||
| 	0x00, 0x00, 0x00, 0xFF, 0xFF, | ||||
| 	0x0F, 0x0F, 0x0F, 0x0F, 0x0F, | ||||
| 	0x38, 0x44, 0x44, 0x38, 0x44, | ||||
| 	0xFC, 0x4A, 0x4A, 0x4A, 0x34, // sharp-s or beta
 | ||||
| 	0x7E, 0x02, 0x02, 0x06, 0x06, | ||||
| 	0x02, 0x7E, 0x02, 0x7E, 0x02, | ||||
| 	0x63, 0x55, 0x49, 0x41, 0x63, | ||||
| 	0x38, 0x44, 0x44, 0x3C, 0x04, | ||||
| 	0x40, 0x7E, 0x20, 0x1E, 0x20, | ||||
| 	0x06, 0x02, 0x7E, 0x02, 0x02, | ||||
| 	0x99, 0xA5, 0xE7, 0xA5, 0x99, | ||||
| 	0x1C, 0x2A, 0x49, 0x2A, 0x1C, | ||||
| 	0x4C, 0x72, 0x01, 0x72, 0x4C, | ||||
| 	0x30, 0x4A, 0x4D, 0x4D, 0x30, | ||||
| 	0x30, 0x48, 0x78, 0x48, 0x30, | ||||
| 	0xBC, 0x62, 0x5A, 0x46, 0x3D, | ||||
| 	0x3E, 0x49, 0x49, 0x49, 0x00, | ||||
| 	0x7E, 0x01, 0x01, 0x01, 0x7E, | ||||
| 	0x2A, 0x2A, 0x2A, 0x2A, 0x2A, | ||||
| 	0x44, 0x44, 0x5F, 0x44, 0x44, | ||||
| 	0x40, 0x51, 0x4A, 0x44, 0x40, | ||||
| 	0x40, 0x44, 0x4A, 0x51, 0x40, | ||||
| 	0x00, 0x00, 0xFF, 0x01, 0x03, | ||||
| 	0xE0, 0x80, 0xFF, 0x00, 0x00, | ||||
| 	0x08, 0x08, 0x6B, 0x6B, 0x08, | ||||
| 	0x36, 0x12, 0x36, 0x24, 0x36, | ||||
| 	0x06, 0x0F, 0x09, 0x0F, 0x06, | ||||
| 	0x00, 0x00, 0x18, 0x18, 0x00, | ||||
| 	0x00, 0x00, 0x10, 0x10, 0x00, | ||||
| 	0x30, 0x40, 0xFF, 0x01, 0x01, | ||||
| 	0x00, 0x1F, 0x01, 0x01, 0x1E, | ||||
| 	0x00, 0x19, 0x1D, 0x17, 0x12, | ||||
| 	0x00, 0x3C, 0x3C, 0x3C, 0x3C, | ||||
| 	0x00, 0x00, 0x00, 0x00, 0x00  // #255 NBSP
 | ||||
|     0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, 0x18, 0x3C, 0x7E, 0x3C, 0x18, 0x1C, 0x57, 0x7D, 0x57, 0x1C, 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, 0x00, 0x18, 0x3C, 0x18, 0x00, 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, 0x00, 0x18, 0x24, 0x18, 0x00, 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, 0x30, 0x48, 0x3A, 0x06, 0x0E, 0x26, 0x29, 0x79, 0x29, 0x26, 0x40, 0x7F, 0x05, 0x05, 0x07, 0x40, 0x7F, 0x05, 0x25, 0x3F, 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, 0x7F, 0x3E, 0x1C, 0x1C, 0x08, 0x08, 0x1C, 0x1C, 0x3E, 0x7F, 0x14, 0x22, 0x7F, 0x22, 0x14, 0x5F, 0x5F, 0x00, 0x5F, 0x5F, 0x06, 0x09, 0x7F, 0x01, 0x7F, 0x00, 0x66, 0x89, 0x95, 0x6A, 0x60, 0x60, 0x60, 0x60, 0x60, 0x94, 0xA2, 0xFF, 0xA2, 0x94, 0x08, 0x04, 0x7E, 0x04, 0x08, 0x10, 0x20, 0x7E, 0x20, 0x10, 0x08, 0x08, 0x2A, 0x1C, 0x08, 0x08, 0x1C, 0x2A, 0x08, 0x08, 0x1E, 0x10, 0x10, 0x10, 0x10, 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, | ||||
|     0x30, 0x38, 0x3E, 0x38, 0x30, 0x06, 0x0E, 0x3E, 0x0E, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x14, 0x7F, 0x14, 0x7F, 0x14, 0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x23, 0x13, 0x08, 0x64, 0x62, 0x36, 0x49, 0x56, 0x20, 0x50, 0x00, 0x08, 0x07, 0x03, 0x00, 0x00, 0x1C, 0x22, 0x41, 0x00, 0x00, 0x41, 0x22, 0x1C, 0x00, 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, 0x80, 0x70, 0x30, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x60, 0x60, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00, 0x42, 0x7F, 0x40, 0x00, 0x72, 0x49, 0x49, 0x49, 0x46, 0x21, 0x41, 0x49, 0x4D, 0x33, 0x18, 0x14, 0x12, 0x7F, 0x10, 0x27, 0x45, 0x45, 0x45, 0x39, 0x3C, 0x4A, 0x49, 0x49, 0x31, 0x41, 0x21, 0x11, 0x09, 0x07, 0x36, 0x49, 0x49, 0x49, 0x36, 0x46, 0x49, 0x49, 0x29, 0x1E, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x40, 0x34, 0x00, 0x00, | ||||
|     0x00, 0x08, 0x14, 0x22, 0x41, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, 0x41, 0x22, 0x14, 0x08, 0x02, 0x01, 0x59, 0x09, 0x06, 0x3E, 0x41, 0x5D, 0x59, 0x4E, 0x7C, 0x12, 0x11, 0x12, 0x7C, 0x7F, 0x49, 0x49, 0x49, 0x36, 0x3E, 0x41, 0x41, 0x41, 0x22, 0x7F, 0x41, 0x41, 0x41, 0x3E, 0x7F, 0x49, 0x49, 0x49, 0x41, 0x7F, 0x09, 0x09, 0x09, 0x01, 0x3E, 0x41, 0x41, 0x51, 0x73, 0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00, 0x41, 0x7F, 0x41, 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, 0x7F, 0x08, 0x14, 0x22, 0x41, 0x7F, 0x40, 0x40, 0x40, 0x40, 0x7F, 0x02, 0x1C, 0x02, 0x7F, 0x7F, 0x04, 0x08, 0x10, 0x7F, 0x3E, 0x41, 0x41, 0x41, 0x3E, 0x7F, 0x09, 0x09, 0x09, 0x06, 0x3E, 0x41, 0x51, 0x21, 0x5E, 0x7F, 0x09, 0x19, 0x29, 0x46, 0x26, 0x49, 0x49, 0x49, 0x32, 0x03, 0x01, 0x7F, 0x01, 0x03, 0x3F, 0x40, 0x40, 0x40, 0x3F, 0x1F, 0x20, 0x40, 0x20, 0x1F, 0x3F, 0x40, 0x38, 0x40, 0x3F, 0x63, 0x14, 0x08, 0x14, 0x63, 0x03, 0x04, 0x78, 0x04, 0x03, | ||||
|     0x61, 0x59, 0x49, 0x4D, 0x43, 0x00, 0x7F, 0x41, 0x41, 0x41, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x41, 0x41, 0x41, 0x7F, 0x04, 0x02, 0x01, 0x02, 0x04, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x03, 0x07, 0x08, 0x00, 0x20, 0x54, 0x54, 0x78, 0x40, 0x7F, 0x28, 0x44, 0x44, 0x38, 0x38, 0x44, 0x44, 0x44, 0x28, 0x38, 0x44, 0x44, 0x28, 0x7F, 0x38, 0x54, 0x54, 0x54, 0x18, 0x00, 0x08, 0x7E, 0x09, 0x02, 0x18, 0xA4, 0xA4, 0x9C, 0x78, 0x7F, 0x08, 0x04, 0x04, 0x78, 0x00, 0x44, 0x7D, 0x40, 0x00, 0x20, 0x40, 0x40, 0x3D, 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, 0x7C, 0x04, 0x78, 0x04, 0x78, 0x7C, 0x08, 0x04, 0x04, 0x78, 0x38, 0x44, 0x44, 0x44, 0x38, 0xFC, 0x18, 0x24, 0x24, 0x18, 0x18, 0x24, 0x24, 0x18, 0xFC, 0x7C, 0x08, 0x04, 0x04, 0x08, 0x48, 0x54, 0x54, 0x54, 0x24, 0x04, 0x04, 0x3F, 0x44, 0x24, 0x3C, 0x40, 0x40, 0x20, 0x7C, 0x1C, 0x20, 0x40, 0x20, 0x1C, 0x3C, 0x40, 0x30, 0x40, 0x3C, | ||||
|     0x44, 0x28, 0x10, 0x28, 0x44, 0x4C, 0x90, 0x90, 0x90, 0x7C, 0x44, 0x64, 0x54, 0x4C, 0x44, 0x00, 0x08, 0x36, 0x41, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x41, 0x36, 0x08, 0x00, 0x02, 0x01, 0x02, 0x04, 0x02, 0x3C, 0x26, 0x23, 0x26, 0x3C, 0x1E, 0xA1, 0xA1, 0x61, 0x12, 0x3A, 0x40, 0x40, 0x20, 0x7A, 0x38, 0x54, 0x54, 0x55, 0x59, 0x21, 0x55, 0x55, 0x79, 0x41, 0x22, 0x54, 0x54, 0x78, 0x42,                                                                                                                                                                                                                                                                                                              // a-umlaut
 | ||||
|     0x21, 0x55, 0x54, 0x78, 0x40, 0x20, 0x54, 0x55, 0x79, 0x40, 0x0C, 0x1E, 0x52, 0x72, 0x12, 0x39, 0x55, 0x55, 0x55, 0x59, 0x39, 0x54, 0x54, 0x54, 0x59, 0x39, 0x55, 0x54, 0x54, 0x58, 0x00, 0x00, 0x45, 0x7C, 0x41, 0x00, 0x02, 0x45, 0x7D, 0x42, 0x00, 0x01, 0x45, 0x7C, 0x40, 0x7D, 0x12, 0x11, 0x12, 0x7D,                                                                                                                                                                                                                                                                                                                                                                                                        // A-umlaut
 | ||||
|     0xF0, 0x28, 0x25, 0x28, 0xF0, 0x7C, 0x54, 0x55, 0x45, 0x00, 0x20, 0x54, 0x54, 0x7C, 0x54, 0x7C, 0x0A, 0x09, 0x7F, 0x49, 0x32, 0x49, 0x49, 0x49, 0x32, 0x3A, 0x44, 0x44, 0x44, 0x3A,                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                // o-umlaut
 | ||||
|     0x32, 0x4A, 0x48, 0x48, 0x30, 0x3A, 0x41, 0x41, 0x21, 0x7A, 0x3A, 0x42, 0x40, 0x20, 0x78, 0x00, 0x9D, 0xA0, 0xA0, 0x7D, 0x3D, 0x42, 0x42, 0x42, 0x3D,                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              // O-umlaut
 | ||||
|     0x3D, 0x40, 0x40, 0x40, 0x3D, 0x3C, 0x24, 0xFF, 0x24, 0x24, 0x48, 0x7E, 0x49, 0x43, 0x66, 0x2B, 0x2F, 0xFC, 0x2F, 0x2B, 0xFF, 0x09, 0x29, 0xF6, 0x20, 0xC0, 0x88, 0x7E, 0x09, 0x03, 0x20, 0x54, 0x54, 0x79, 0x41, 0x00, 0x00, 0x44, 0x7D, 0x41, 0x30, 0x48, 0x48, 0x4A, 0x32, 0x38, 0x40, 0x40, 0x22, 0x7A, 0x00, 0x7A, 0x0A, 0x0A, 0x72, 0x7D, 0x0D, 0x19, 0x31, 0x7D, 0x26, 0x29, 0x29, 0x2F, 0x28, 0x26, 0x29, 0x29, 0x29, 0x26, 0x30, 0x48, 0x4D, 0x40, 0x20, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x2F, 0x10, 0xC8, 0xAC, 0xBA, 0x2F, 0x10, 0x28, 0x34, 0xFA, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x08, 0x14, 0x2A, 0x14, 0x22, 0x22, 0x14, 0x2A, 0x14, 0x08, 0x55, 0x00, 0x55, 0x00, 0x55,  // #176 (25% block) missing in old code
 | ||||
|     0xAA, 0x55, 0xAA, 0x55, 0xAA,                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      // 50% block
 | ||||
|     0xFF, 0x55, 0xFF, 0x55, 0xFF,                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      // 75% block
 | ||||
|     0x00, 0x00, 0x00, 0xFF, 0x00, 0x10, 0x10, 0x10, 0xFF, 0x00, 0x14, 0x14, 0x14, 0xFF, 0x00, 0x10, 0x10, 0xFF, 0x00, 0xFF, 0x10, 0x10, 0xF0, 0x10, 0xF0, 0x14, 0x14, 0x14, 0xFC, 0x00, 0x14, 0x14, 0xF7, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x14, 0x14, 0xF4, 0x04, 0xFC, 0x14, 0x14, 0x17, 0x10, 0x1F, 0x10, 0x10, 0x1F, 0x10, 0x1F, 0x14, 0x14, 0x14, 0x1F, 0x00, 0x10, 0x10, 0x10, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x1F, 0x10, 0x10, 0x10, 0x10, 0xF0, 0x10, 0x00, 0x00, 0x00, 0xFF, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xFF, 0x10, 0x00, 0x00, 0x00, 0xFF, 0x14, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x1F, 0x10, 0x17, 0x00, 0x00, 0xFC, 0x04, 0xF4, 0x14, 0x14, 0x17, 0x10, 0x17, 0x14, 0x14, 0xF4, 0x04, 0xF4, 0x00, 0x00, 0xFF, 0x00, 0xF7, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0xF7, 0x00, 0xF7, 0x14, 0x14, 0x14, 0x17, 0x14, 0x10, 0x10, 0x1F, 0x10, 0x1F, | ||||
|     0x14, 0x14, 0x14, 0xF4, 0x14, 0x10, 0x10, 0xF0, 0x10, 0xF0, 0x00, 0x00, 0x1F, 0x10, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x14, 0x00, 0x00, 0x00, 0xFC, 0x14, 0x00, 0x00, 0xF0, 0x10, 0xF0, 0x10, 0x10, 0xFF, 0x10, 0xFF, 0x14, 0x14, 0x14, 0xFF, 0x14, 0x10, 0x10, 0x10, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x38, 0x44, 0x44, 0x38, 0x44, 0xFC, 0x4A, 0x4A, 0x4A, 0x34,                                                                                                                                                                                                                                                                                                                                                                                                       // sharp-s or beta
 | ||||
|     0x7E, 0x02, 0x02, 0x06, 0x06, 0x02, 0x7E, 0x02, 0x7E, 0x02, 0x63, 0x55, 0x49, 0x41, 0x63, 0x38, 0x44, 0x44, 0x3C, 0x04, 0x40, 0x7E, 0x20, 0x1E, 0x20, 0x06, 0x02, 0x7E, 0x02, 0x02, 0x99, 0xA5, 0xE7, 0xA5, 0x99, 0x1C, 0x2A, 0x49, 0x2A, 0x1C, 0x4C, 0x72, 0x01, 0x72, 0x4C, 0x30, 0x4A, 0x4D, 0x4D, 0x30, 0x30, 0x48, 0x78, 0x48, 0x30, 0xBC, 0x62, 0x5A, 0x46, 0x3D, 0x3E, 0x49, 0x49, 0x49, 0x00, 0x7E, 0x01, 0x01, 0x01, 0x7E, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x44, 0x44, 0x5F, 0x44, 0x44, 0x40, 0x51, 0x4A, 0x44, 0x40, 0x40, 0x44, 0x4A, 0x51, 0x40, 0x00, 0x00, 0xFF, 0x01, 0x03, 0xE0, 0x80, 0xFF, 0x00, 0x00, 0x08, 0x08, 0x6B, 0x6B, 0x08, 0x36, 0x12, 0x36, 0x24, 0x36, 0x06, 0x0F, 0x09, 0x0F, 0x06, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x30, 0x40, 0xFF, 0x01, 0x01, 0x00, 0x1F, 0x01, 0x01, 0x1E, 0x00, 0x19, 0x1D, 0x17, 0x12, 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00  // #255 NBSP
 | ||||
| }; | ||||
| #endif // FONT5X7_H
 | ||||
| #endif  // FONT5X7_H
 | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ | |||
|  Author:    Peter Fleury <pfleury@gmx.ch>  http://tinyurl.com/peterfleury
 | ||||
|  License:   GNU General Public License Version 3 | ||||
|  File:	    $Id: lcd.c,v 1.15.2.2 2015/01/17 12:16:05 peter Exp $ | ||||
|  Software:  AVR-GCC 3.3  | ||||
|  Software:  AVR-GCC 3.3 | ||||
|  Target:    any AVR device, memory mapped mode only for AT90S4414/8515/Mega | ||||
| 
 | ||||
|  DESCRIPTION | ||||
|  | @ -13,15 +13,15 @@ | |||
|        changed lcd_init(), added additional constants for lcd_command(), | ||||
|        added 4-bit I/O mode, improved and optimized code. | ||||
| 
 | ||||
|        Library can be operated in memory mapped mode (LCD_IO_MODE=0) or in  | ||||
|        Library can be operated in memory mapped mode (LCD_IO_MODE=0) or in | ||||
|        4-bit IO port mode (LCD_IO_MODE=1). 8-bit IO port mode not supported. | ||||
|         | ||||
| 
 | ||||
|        Memory mapped mode compatible with Kanda STK200, but supports also | ||||
|        generation of R/W signal through A8 address line. | ||||
| 
 | ||||
|  USAGE | ||||
|        See the C include lcd.h file for a description of each function | ||||
|         | ||||
| 
 | ||||
| *****************************************************************************/ | ||||
| #include <inttypes.h> | ||||
| #include <avr/io.h> | ||||
|  | @ -29,55 +29,54 @@ | |||
| #include <util/delay.h> | ||||
| #include "hd44780.h" | ||||
| 
 | ||||
| /* 
 | ||||
| ** constants/macros  | ||||
| /*
 | ||||
| ** constants/macros | ||||
| */ | ||||
| #define DDR(x) (*(&x - 1))      /* address of data direction register of port x */ | ||||
| #define DDR(x) (*(&x - 1)) /* address of data direction register of port x */ | ||||
| #if defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) | ||||
|     /* on ATmega64/128 PINF is on port 0x00 and not 0x60 */ | ||||
|     #define PIN(x) ( &PORTF==&(x) ? _SFR_IO8(0x00) : (*(&x - 2)) ) | ||||
| /* on ATmega64/128 PINF is on port 0x00 and not 0x60 */ | ||||
| #    define PIN(x) (&PORTF == &(x) ? _SFR_IO8(0x00) : (*(&x - 2))) | ||||
| #else | ||||
| 	#define PIN(x) (*(&x - 2))    /* address of input register of port x          */ | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| #if LCD_IO_MODE | ||||
| #define lcd_e_delay()   _delay_us(LCD_DELAY_ENABLE_PULSE) | ||||
| #define lcd_e_high()    LCD_E_PORT  |=  _BV(LCD_E_PIN); | ||||
| #define lcd_e_low()     LCD_E_PORT  &= ~_BV(LCD_E_PIN); | ||||
| #define lcd_e_toggle()  toggle_e() | ||||
| #define lcd_rw_high()   LCD_RW_PORT |=  _BV(LCD_RW_PIN) | ||||
| #define lcd_rw_low()    LCD_RW_PORT &= ~_BV(LCD_RW_PIN) | ||||
| #define lcd_rs_high()   LCD_RS_PORT |=  _BV(LCD_RS_PIN) | ||||
| #define lcd_rs_low()    LCD_RS_PORT &= ~_BV(LCD_RS_PIN) | ||||
| #    define PIN(x) (*(&x - 2)) /* address of input register of port x          */ | ||||
| #endif | ||||
| 
 | ||||
| #if LCD_IO_MODE | ||||
| #if LCD_LINES==1 | ||||
| #define LCD_FUNCTION_DEFAULT    LCD_FUNCTION_4BIT_1LINE  | ||||
| #else | ||||
| #define LCD_FUNCTION_DEFAULT    LCD_FUNCTION_4BIT_2LINES  | ||||
| #    define lcd_e_delay() _delay_us(LCD_DELAY_ENABLE_PULSE) | ||||
| #    define lcd_e_high() LCD_E_PORT |= _BV(LCD_E_PIN); | ||||
| #    define lcd_e_low() LCD_E_PORT &= ~_BV(LCD_E_PIN); | ||||
| #    define lcd_e_toggle() toggle_e() | ||||
| #    define lcd_rw_high() LCD_RW_PORT |= _BV(LCD_RW_PIN) | ||||
| #    define lcd_rw_low() LCD_RW_PORT &= ~_BV(LCD_RW_PIN) | ||||
| #    define lcd_rs_high() LCD_RS_PORT |= _BV(LCD_RS_PIN) | ||||
| #    define lcd_rs_low() LCD_RS_PORT &= ~_BV(LCD_RS_PIN) | ||||
| #endif | ||||
| 
 | ||||
| #if LCD_IO_MODE | ||||
| #    if LCD_LINES == 1 | ||||
| #        define LCD_FUNCTION_DEFAULT LCD_FUNCTION_4BIT_1LINE | ||||
| #    else | ||||
| #        define LCD_FUNCTION_DEFAULT LCD_FUNCTION_4BIT_2LINES | ||||
| #    endif | ||||
| #else | ||||
| #if LCD_LINES==1 | ||||
| #define LCD_FUNCTION_DEFAULT    LCD_FUNCTION_8BIT_1LINE | ||||
| #else | ||||
| #define LCD_FUNCTION_DEFAULT    LCD_FUNCTION_8BIT_2LINES | ||||
| #endif | ||||
| #    if LCD_LINES == 1 | ||||
| #        define LCD_FUNCTION_DEFAULT LCD_FUNCTION_8BIT_1LINE | ||||
| #    else | ||||
| #        define LCD_FUNCTION_DEFAULT LCD_FUNCTION_8BIT_2LINES | ||||
| #    endif | ||||
| #endif | ||||
| 
 | ||||
| #if LCD_CONTROLLER_KS0073 | ||||
| #if LCD_LINES==4 | ||||
| #    if LCD_LINES == 4 | ||||
| 
 | ||||
| #define KS0073_EXTENDED_FUNCTION_REGISTER_ON  0x2C   /* |0|010|1100 4-bit mode, extension-bit RE = 1 */ | ||||
| #define KS0073_EXTENDED_FUNCTION_REGISTER_OFF 0x28   /* |0|010|1000 4-bit mode, extension-bit RE = 0 */ | ||||
| #define KS0073_4LINES_MODE                    0x09   /* |0|000|1001 4 lines mode */ | ||||
| #        define KS0073_EXTENDED_FUNCTION_REGISTER_ON 0x2C  /* |0|010|1100 4-bit mode, extension-bit RE = 1 */ | ||||
| #        define KS0073_EXTENDED_FUNCTION_REGISTER_OFF 0x28 /* |0|010|1000 4-bit mode, extension-bit RE = 0 */ | ||||
| #        define KS0073_4LINES_MODE 0x09                    /* |0|000|1001 4 lines mode */ | ||||
| 
 | ||||
| #endif | ||||
| #    endif | ||||
| #endif | ||||
| 
 | ||||
| /* 
 | ||||
| ** function prototypes  | ||||
| /*
 | ||||
| ** function prototypes | ||||
| */ | ||||
| #if LCD_IO_MODE | ||||
| static void toggle_e(void); | ||||
|  | @ -87,93 +86,83 @@ static void toggle_e(void); | |||
| ** local functions | ||||
| */ | ||||
| 
 | ||||
| 
 | ||||
| /************************************************************************* 
 | ||||
| /*************************************************************************
 | ||||
| delay for a minimum of <us> microseconds | ||||
| the number of loops is calculated at compile-time from MCU clock frequency | ||||
| *************************************************************************/ | ||||
| #define delay(us)  _delay_us(us)  | ||||
| 
 | ||||
| #define delay(us) _delay_us(us) | ||||
| 
 | ||||
| #if LCD_IO_MODE | ||||
| /* toggle Enable Pin to initiate write */ | ||||
| static void toggle_e(void) | ||||
| { | ||||
| static void toggle_e(void) { | ||||
|     lcd_e_high(); | ||||
|     lcd_e_delay(); | ||||
|     lcd_e_low(); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /*************************************************************************
 | ||||
| Low-level function to write byte to LCD controller | ||||
| Input:    data   byte to write to LCD | ||||
|           rs     1: write data     | ||||
|           rs     1: write data | ||||
|                  0: write instruction | ||||
| Returns:  none | ||||
| *************************************************************************/ | ||||
| #if LCD_IO_MODE | ||||
| static void lcd_write(uint8_t data,uint8_t rs)  | ||||
| { | ||||
|     unsigned char dataBits ; | ||||
| static void lcd_write(uint8_t data, uint8_t rs) { | ||||
|     unsigned char dataBits; | ||||
| 
 | ||||
| 
 | ||||
|     if (rs) {        /* write data        (RS=1, RW=0) */ | ||||
|        lcd_rs_high(); | ||||
|     } else {         /* write instruction (RS=0, RW=0) */ | ||||
|        lcd_rs_low(); | ||||
|     if (rs) { /* write data        (RS=1, RW=0) */ | ||||
|         lcd_rs_high(); | ||||
|     } else { /* write instruction (RS=0, RW=0) */ | ||||
|         lcd_rs_low(); | ||||
|     } | ||||
|     lcd_rw_low();    /* RW=0  write mode      */ | ||||
|     lcd_rw_low(); /* RW=0  write mode      */ | ||||
| 
 | ||||
|     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) ) | ||||
|     { | ||||
|     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)) { | ||||
|         /* configure data pins as output */ | ||||
|         DDR(LCD_DATA0_PORT) |= 0x0F; | ||||
| 
 | ||||
|         /* output high nibble first */ | ||||
|         dataBits = LCD_DATA0_PORT & 0xF0; | ||||
|         LCD_DATA0_PORT = dataBits |((data>>4)&0x0F); | ||||
|         dataBits       = LCD_DATA0_PORT & 0xF0; | ||||
|         LCD_DATA0_PORT = dataBits | ((data >> 4) & 0x0F); | ||||
|         lcd_e_toggle(); | ||||
| 
 | ||||
|         /* output low nibble */ | ||||
|         LCD_DATA0_PORT = dataBits | (data&0x0F); | ||||
|         LCD_DATA0_PORT = dataBits | (data & 0x0F); | ||||
|         lcd_e_toggle(); | ||||
| 
 | ||||
|         /* all data pins high (inactive) */ | ||||
|         LCD_DATA0_PORT = dataBits | 0x0F; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|     } else { | ||||
|         /* configure data pins as output */ | ||||
|         DDR(LCD_DATA0_PORT) |= _BV(LCD_DATA0_PIN); | ||||
|         DDR(LCD_DATA1_PORT) |= _BV(LCD_DATA1_PIN); | ||||
|         DDR(LCD_DATA2_PORT) |= _BV(LCD_DATA2_PIN); | ||||
|         DDR(LCD_DATA3_PORT) |= _BV(LCD_DATA3_PIN); | ||||
|          | ||||
| 
 | ||||
|         /* output high nibble first */ | ||||
|         LCD_DATA3_PORT &= ~_BV(LCD_DATA3_PIN); | ||||
|         LCD_DATA2_PORT &= ~_BV(LCD_DATA2_PIN); | ||||
|         LCD_DATA1_PORT &= ~_BV(LCD_DATA1_PIN); | ||||
|         LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN); | ||||
|     	if(data & 0x80) LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN); | ||||
|     	if(data & 0x40) LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN); | ||||
|     	if(data & 0x20) LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); | ||||
|     	if(data & 0x10) LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN);    | ||||
|         if (data & 0x80) LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN); | ||||
|         if (data & 0x40) LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN); | ||||
|         if (data & 0x20) LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); | ||||
|         if (data & 0x10) LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); | ||||
|         lcd_e_toggle(); | ||||
|          | ||||
| 
 | ||||
|         /* output low nibble */ | ||||
|         LCD_DATA3_PORT &= ~_BV(LCD_DATA3_PIN); | ||||
|         LCD_DATA2_PORT &= ~_BV(LCD_DATA2_PIN); | ||||
|         LCD_DATA1_PORT &= ~_BV(LCD_DATA1_PIN); | ||||
|         LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN); | ||||
|     	if(data & 0x08) LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN); | ||||
|     	if(data & 0x04) LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN); | ||||
|     	if(data & 0x02) LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); | ||||
|     	if(data & 0x01) LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); | ||||
|         lcd_e_toggle();         | ||||
|          | ||||
|         if (data & 0x08) LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN); | ||||
|         if (data & 0x04) LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN); | ||||
|         if (data & 0x02) LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); | ||||
|         if (data & 0x01) LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); | ||||
|         lcd_e_toggle(); | ||||
| 
 | ||||
|         /* all data pins high (inactive) */ | ||||
|         LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); | ||||
|         LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); | ||||
|  | @ -182,85 +171,81 @@ static void lcd_write(uint8_t data,uint8_t rs) | |||
|     } | ||||
| } | ||||
| #else | ||||
| #define lcd_write(d,rs) if (rs) *(volatile uint8_t*)(LCD_IO_DATA) = d; else *(volatile uint8_t*)(LCD_IO_FUNCTION) = d; | ||||
| #    define lcd_write(d, rs)                        \ | ||||
|         if (rs)                                     \ | ||||
|             *(volatile uint8_t *)(LCD_IO_DATA) = d; \ | ||||
|         else                                        \ | ||||
|             *(volatile uint8_t *)(LCD_IO_FUNCTION) = d; | ||||
| /* rs==0 -> write instruction to LCD_IO_FUNCTION */ | ||||
| /* rs==1 -> write data to LCD_IO_DATA */ | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /*************************************************************************
 | ||||
| Low-level function to read byte from LCD controller | ||||
| Input:    rs     1: read data     | ||||
| Input:    rs     1: read data | ||||
|                  0: read busy flag / address counter | ||||
| Returns:  byte read from LCD controller | ||||
| *************************************************************************/ | ||||
| #if LCD_IO_MODE | ||||
| static uint8_t lcd_read(uint8_t rs)  | ||||
| { | ||||
| static uint8_t lcd_read(uint8_t rs) { | ||||
|     uint8_t data; | ||||
|      | ||||
|      | ||||
| 
 | ||||
|     if (rs) | ||||
|         lcd_rs_high();                       /* RS=1: read data      */ | ||||
|         lcd_rs_high(); /* RS=1: read data      */ | ||||
|     else | ||||
|         lcd_rs_low();                        /* RS=0: read busy flag */ | ||||
|     lcd_rw_high();                           /* RW=1  read mode      */ | ||||
|      | ||||
|     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) ) | ||||
|     { | ||||
|         DDR(LCD_DATA0_PORT) &= 0xF0;         /* configure data pins as input */ | ||||
|          | ||||
|         lcd_e_high(); | ||||
|         lcd_e_delay();         | ||||
|         data = PIN(LCD_DATA0_PORT) << 4;     /* read high nibble first */ | ||||
|         lcd_e_low(); | ||||
|          | ||||
|         lcd_e_delay();                       /* Enable 500ns low       */ | ||||
|          | ||||
|         lcd_rs_low(); /* RS=0: read busy flag */ | ||||
|     lcd_rw_high();    /* RW=1  read mode      */ | ||||
| 
 | ||||
|     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)) { | ||||
|         DDR(LCD_DATA0_PORT) &= 0xF0; /* configure data pins as input */ | ||||
| 
 | ||||
|         lcd_e_high(); | ||||
|         lcd_e_delay(); | ||||
|         data |= PIN(LCD_DATA0_PORT)&0x0F;    /* read low nibble        */ | ||||
|         data = PIN(LCD_DATA0_PORT) << 4; /* read high nibble first */ | ||||
|         lcd_e_low(); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
| 
 | ||||
|         lcd_e_delay(); /* Enable 500ns low       */ | ||||
| 
 | ||||
|         lcd_e_high(); | ||||
|         lcd_e_delay(); | ||||
|         data |= PIN(LCD_DATA0_PORT) & 0x0F; /* read low nibble        */ | ||||
|         lcd_e_low(); | ||||
|     } else { | ||||
|         /* configure data pins as input */ | ||||
|         DDR(LCD_DATA0_PORT) &= ~_BV(LCD_DATA0_PIN); | ||||
|         DDR(LCD_DATA1_PORT) &= ~_BV(LCD_DATA1_PIN); | ||||
|         DDR(LCD_DATA2_PORT) &= ~_BV(LCD_DATA2_PIN); | ||||
|         DDR(LCD_DATA3_PORT) &= ~_BV(LCD_DATA3_PIN); | ||||
|                  | ||||
| 
 | ||||
|         /* read high nibble first */ | ||||
|         lcd_e_high(); | ||||
|         lcd_e_delay();         | ||||
|         lcd_e_delay(); | ||||
|         data = 0; | ||||
|         if ( PIN(LCD_DATA0_PORT) & _BV(LCD_DATA0_PIN) ) data |= 0x10; | ||||
|         if ( PIN(LCD_DATA1_PORT) & _BV(LCD_DATA1_PIN) ) data |= 0x20; | ||||
|         if ( PIN(LCD_DATA2_PORT) & _BV(LCD_DATA2_PIN) ) data |= 0x40; | ||||
|         if ( PIN(LCD_DATA3_PORT) & _BV(LCD_DATA3_PIN) ) data |= 0x80; | ||||
|         if (PIN(LCD_DATA0_PORT) & _BV(LCD_DATA0_PIN)) data |= 0x10; | ||||
|         if (PIN(LCD_DATA1_PORT) & _BV(LCD_DATA1_PIN)) data |= 0x20; | ||||
|         if (PIN(LCD_DATA2_PORT) & _BV(LCD_DATA2_PIN)) data |= 0x40; | ||||
|         if (PIN(LCD_DATA3_PORT) & _BV(LCD_DATA3_PIN)) data |= 0x80; | ||||
|         lcd_e_low(); | ||||
| 
 | ||||
|         lcd_e_delay();                       /* Enable 500ns low       */ | ||||
|      | ||||
|         /* read low nibble */     | ||||
|         lcd_e_delay(); /* Enable 500ns low       */ | ||||
| 
 | ||||
|         /* read low nibble */ | ||||
|         lcd_e_high(); | ||||
|         lcd_e_delay(); | ||||
|         if ( PIN(LCD_DATA0_PORT) & _BV(LCD_DATA0_PIN) ) data |= 0x01; | ||||
|         if ( PIN(LCD_DATA1_PORT) & _BV(LCD_DATA1_PIN) ) data |= 0x02; | ||||
|         if ( PIN(LCD_DATA2_PORT) & _BV(LCD_DATA2_PIN) ) data |= 0x04; | ||||
|         if ( PIN(LCD_DATA3_PORT) & _BV(LCD_DATA3_PIN) ) data |= 0x08;         | ||||
|         if (PIN(LCD_DATA0_PORT) & _BV(LCD_DATA0_PIN)) data |= 0x01; | ||||
|         if (PIN(LCD_DATA1_PORT) & _BV(LCD_DATA1_PIN)) data |= 0x02; | ||||
|         if (PIN(LCD_DATA2_PORT) & _BV(LCD_DATA2_PIN)) data |= 0x04; | ||||
|         if (PIN(LCD_DATA3_PORT) & _BV(LCD_DATA3_PIN)) data |= 0x08; | ||||
|         lcd_e_low(); | ||||
|     } | ||||
|     return data; | ||||
| } | ||||
| #else | ||||
| #define lcd_read(rs) (rs) ? *(volatile uint8_t*)(LCD_IO_DATA+LCD_IO_READ) : *(volatile uint8_t*)(LCD_IO_FUNCTION+LCD_IO_READ) | ||||
| #    define lcd_read(rs) (rs) ? *(volatile uint8_t *)(LCD_IO_DATA + LCD_IO_READ) : *(volatile uint8_t *)(LCD_IO_FUNCTION + LCD_IO_READ) | ||||
| /* rs==0 -> read instruction from LCD_IO_FUNCTION */ | ||||
| /* rs==1 -> read data from LCD_IO_DATA */ | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /*************************************************************************
 | ||||
| loops while lcd is busy, returns address counter | ||||
| *************************************************************************/ | ||||
|  | @ -268,65 +253,62 @@ static uint8_t lcd_waitbusy(void) | |||
| 
 | ||||
| { | ||||
|     register uint8_t c; | ||||
|      | ||||
| 
 | ||||
|     /* wait until busy flag is cleared */ | ||||
|     while ( (c=lcd_read(0)) & (1<<LCD_BUSY)) {} | ||||
|      | ||||
|     while ((c = lcd_read(0)) & (1 << LCD_BUSY)) { | ||||
|     } | ||||
| 
 | ||||
|     /* the address counter is updated 4us after the busy flag is cleared */ | ||||
|     delay(LCD_DELAY_BUSY_FLAG); | ||||
| 
 | ||||
|     /* now read the address counter */ | ||||
|     return (lcd_read(0));  // return address counter
 | ||||
|      | ||||
| }/* lcd_waitbusy */ | ||||
| 
 | ||||
| } /* lcd_waitbusy */ | ||||
| 
 | ||||
| /*************************************************************************
 | ||||
| Move cursor to the start of next line or to the first line if the cursor  | ||||
| Move cursor to the start of next line or to the first line if the cursor | ||||
| is already on the last line. | ||||
| *************************************************************************/ | ||||
| static inline void lcd_newline(uint8_t pos) | ||||
| { | ||||
| static inline void lcd_newline(uint8_t pos) { | ||||
|     register uint8_t addressCounter; | ||||
| 
 | ||||
| 
 | ||||
| #if LCD_LINES==1 | ||||
| #if LCD_LINES == 1 | ||||
|     addressCounter = 0; | ||||
| #endif | ||||
| #if LCD_LINES==2 | ||||
|     if ( pos < (LCD_START_LINE2) ) | ||||
| #if LCD_LINES == 2 | ||||
|     if (pos < (LCD_START_LINE2)) | ||||
|         addressCounter = LCD_START_LINE2; | ||||
|     else | ||||
|         addressCounter = LCD_START_LINE1; | ||||
| #endif | ||||
| #if LCD_LINES==4 | ||||
| #if KS0073_4LINES_MODE | ||||
|     if ( pos < LCD_START_LINE2 ) | ||||
| #if LCD_LINES == 4 | ||||
| #    if KS0073_4LINES_MODE | ||||
|     if (pos < LCD_START_LINE2) | ||||
|         addressCounter = LCD_START_LINE2; | ||||
|     else if ( (pos >= LCD_START_LINE2) && (pos < LCD_START_LINE3) ) | ||||
|     else if ((pos >= LCD_START_LINE2) && (pos < LCD_START_LINE3)) | ||||
|         addressCounter = LCD_START_LINE3; | ||||
|     else if ( (pos >= LCD_START_LINE3) && (pos < LCD_START_LINE4) ) | ||||
|     else if ((pos >= LCD_START_LINE3) && (pos < LCD_START_LINE4)) | ||||
|         addressCounter = LCD_START_LINE4; | ||||
|     else  | ||||
|     else | ||||
|         addressCounter = LCD_START_LINE1; | ||||
| #else | ||||
|     if ( pos < LCD_START_LINE3 ) | ||||
| #    else | ||||
|     if (pos < LCD_START_LINE3) | ||||
|         addressCounter = LCD_START_LINE2; | ||||
|     else if ( (pos >= LCD_START_LINE2) && (pos < LCD_START_LINE4) ) | ||||
|     else if ((pos >= LCD_START_LINE2) && (pos < LCD_START_LINE4)) | ||||
|         addressCounter = LCD_START_LINE3; | ||||
|     else if ( (pos >= LCD_START_LINE3) && (pos < LCD_START_LINE2) ) | ||||
|     else if ((pos >= LCD_START_LINE3) && (pos < LCD_START_LINE2)) | ||||
|         addressCounter = LCD_START_LINE4; | ||||
|     else  | ||||
|     else | ||||
|         addressCounter = LCD_START_LINE1; | ||||
| #    endif | ||||
| #endif | ||||
| #endif | ||||
|     lcd_command((1<<LCD_DDRAM)+addressCounter); | ||||
| 
 | ||||
| }/* lcd_newline */ | ||||
|     lcd_command((1 << LCD_DDRAM) + addressCounter); | ||||
| 
 | ||||
| } /* lcd_newline */ | ||||
| 
 | ||||
| /*
 | ||||
| ** PUBLIC FUNCTIONS  | ||||
| ** PUBLIC FUNCTIONS | ||||
| */ | ||||
| 
 | ||||
| /*************************************************************************
 | ||||
|  | @ -334,132 +316,107 @@ Send LCD controller instruction command | |||
| Input:   instruction to send to LCD controller, see HD44780 data sheet | ||||
| Returns: none | ||||
| *************************************************************************/ | ||||
| void lcd_command(uint8_t cmd) | ||||
| { | ||||
| void lcd_command(uint8_t cmd) { | ||||
|     lcd_waitbusy(); | ||||
|     lcd_write(cmd,0); | ||||
|     lcd_write(cmd, 0); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*************************************************************************
 | ||||
| Send data byte to LCD controller  | ||||
| Send data byte to LCD controller | ||||
| Input:   data to send to LCD controller, see HD44780 data sheet | ||||
| Returns: none | ||||
| *************************************************************************/ | ||||
| void lcd_data(uint8_t data) | ||||
| { | ||||
| void lcd_data(uint8_t data) { | ||||
|     lcd_waitbusy(); | ||||
|     lcd_write(data,1); | ||||
|     lcd_write(data, 1); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /*************************************************************************
 | ||||
| Set cursor to specified position | ||||
| Input:    x  horizontal position  (0: left most position) | ||||
|           y  vertical position    (0: first line) | ||||
| Returns:  none | ||||
| *************************************************************************/ | ||||
| void lcd_gotoxy(uint8_t x, uint8_t y) | ||||
| { | ||||
| #if LCD_LINES==1 | ||||
|     lcd_command((1<<LCD_DDRAM)+LCD_START_LINE1+x); | ||||
| void lcd_gotoxy(uint8_t x, uint8_t y) { | ||||
| #if LCD_LINES == 1 | ||||
|     lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x); | ||||
| #endif | ||||
| #if LCD_LINES==2 | ||||
|     if ( y==0 )  | ||||
|         lcd_command((1<<LCD_DDRAM)+LCD_START_LINE1+x); | ||||
| #if LCD_LINES == 2 | ||||
|     if (y == 0) | ||||
|         lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x); | ||||
|     else | ||||
|         lcd_command((1<<LCD_DDRAM)+LCD_START_LINE2+x); | ||||
|         lcd_command((1 << LCD_DDRAM) + LCD_START_LINE2 + x); | ||||
| #endif | ||||
| #if LCD_LINES==4 | ||||
|     if ( y==0 ) | ||||
|         lcd_command((1<<LCD_DDRAM)+LCD_START_LINE1+x); | ||||
|     else if ( y==1) | ||||
|         lcd_command((1<<LCD_DDRAM)+LCD_START_LINE2+x); | ||||
|     else if ( y==2) | ||||
|         lcd_command((1<<LCD_DDRAM)+LCD_START_LINE3+x); | ||||
| #if LCD_LINES == 4 | ||||
|     if (y == 0) | ||||
|         lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x); | ||||
|     else if (y == 1) | ||||
|         lcd_command((1 << LCD_DDRAM) + LCD_START_LINE2 + x); | ||||
|     else if (y == 2) | ||||
|         lcd_command((1 << LCD_DDRAM) + LCD_START_LINE3 + x); | ||||
|     else /* y==3 */ | ||||
|         lcd_command((1<<LCD_DDRAM)+LCD_START_LINE4+x); | ||||
|         lcd_command((1 << LCD_DDRAM) + LCD_START_LINE4 + x); | ||||
| #endif | ||||
| 
 | ||||
| }/* lcd_gotoxy */ | ||||
| 
 | ||||
| } /* lcd_gotoxy */ | ||||
| 
 | ||||
| /*************************************************************************
 | ||||
| *************************************************************************/ | ||||
| int lcd_getxy(void) | ||||
| { | ||||
|     return lcd_waitbusy(); | ||||
| } | ||||
| 
 | ||||
| int lcd_getxy(void) { return lcd_waitbusy(); } | ||||
| 
 | ||||
| /*************************************************************************
 | ||||
| Clear display and set cursor to home position | ||||
| *************************************************************************/ | ||||
| void lcd_clrscr(void) | ||||
| { | ||||
|     lcd_command(1<<LCD_CLR); | ||||
| } | ||||
| 
 | ||||
| void lcd_clrscr(void) { lcd_command(1 << LCD_CLR); } | ||||
| 
 | ||||
| /*************************************************************************
 | ||||
| Set cursor to home position | ||||
| *************************************************************************/ | ||||
| void lcd_home(void) | ||||
| { | ||||
|     lcd_command(1<<LCD_HOME); | ||||
| } | ||||
| 
 | ||||
| void lcd_home(void) { lcd_command(1 << LCD_HOME); } | ||||
| 
 | ||||
| /*************************************************************************
 | ||||
| Display character at current cursor position  | ||||
| Input:    character to be displayed                                        | ||||
| Display character at current cursor position | ||||
| Input:    character to be displayed | ||||
| Returns:  none | ||||
| *************************************************************************/ | ||||
| void lcd_putc(char c) | ||||
| { | ||||
| void lcd_putc(char c) { | ||||
|     uint8_t pos; | ||||
| 
 | ||||
| 
 | ||||
|     pos = lcd_waitbusy();   // read busy-flag and address counter
 | ||||
|     if (c=='\n') | ||||
|     { | ||||
|     pos = lcd_waitbusy();  // read busy-flag and address counter
 | ||||
|     if (c == '\n') { | ||||
|         lcd_newline(pos); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
| #if LCD_WRAP_LINES==1 | ||||
| #if LCD_LINES==1 | ||||
|         if ( pos == LCD_START_LINE1+LCD_DISP_LENGTH ) { | ||||
|             lcd_write((1<<LCD_DDRAM)+LCD_START_LINE1,0); | ||||
|     } else { | ||||
| #if LCD_WRAP_LINES == 1 | ||||
| #    if LCD_LINES == 1 | ||||
|         if (pos == LCD_START_LINE1 + LCD_DISP_LENGTH) { | ||||
|             lcd_write((1 << LCD_DDRAM) + LCD_START_LINE1, 0); | ||||
|         } | ||||
| #elif LCD_LINES==2 | ||||
|         if ( pos == LCD_START_LINE1+LCD_DISP_LENGTH ) { | ||||
|             lcd_write((1<<LCD_DDRAM)+LCD_START_LINE2,0);     | ||||
|         }else if ( pos == LCD_START_LINE2+LCD_DISP_LENGTH ){ | ||||
|             lcd_write((1<<LCD_DDRAM)+LCD_START_LINE1,0); | ||||
| #    elif LCD_LINES == 2 | ||||
|         if (pos == LCD_START_LINE1 + LCD_DISP_LENGTH) { | ||||
|             lcd_write((1 << LCD_DDRAM) + LCD_START_LINE2, 0); | ||||
|         } else if (pos == LCD_START_LINE2 + LCD_DISP_LENGTH) { | ||||
|             lcd_write((1 << LCD_DDRAM) + LCD_START_LINE1, 0); | ||||
|         } | ||||
| #elif LCD_LINES==4 | ||||
|         if ( pos == LCD_START_LINE1+LCD_DISP_LENGTH ) { | ||||
|             lcd_write((1<<LCD_DDRAM)+LCD_START_LINE2,0);     | ||||
|         }else if ( pos == LCD_START_LINE2+LCD_DISP_LENGTH ) { | ||||
|             lcd_write((1<<LCD_DDRAM)+LCD_START_LINE3,0); | ||||
|         }else if ( pos == LCD_START_LINE3+LCD_DISP_LENGTH ) { | ||||
|             lcd_write((1<<LCD_DDRAM)+LCD_START_LINE4,0); | ||||
|         }else if ( pos == LCD_START_LINE4+LCD_DISP_LENGTH ) { | ||||
|             lcd_write((1<<LCD_DDRAM)+LCD_START_LINE1,0); | ||||
| #    elif LCD_LINES == 4 | ||||
|         if (pos == LCD_START_LINE1 + LCD_DISP_LENGTH) { | ||||
|             lcd_write((1 << LCD_DDRAM) + LCD_START_LINE2, 0); | ||||
|         } else if (pos == LCD_START_LINE2 + LCD_DISP_LENGTH) { | ||||
|             lcd_write((1 << LCD_DDRAM) + LCD_START_LINE3, 0); | ||||
|         } else if (pos == LCD_START_LINE3 + LCD_DISP_LENGTH) { | ||||
|             lcd_write((1 << LCD_DDRAM) + LCD_START_LINE4, 0); | ||||
|         } else if (pos == LCD_START_LINE4 + LCD_DISP_LENGTH) { | ||||
|             lcd_write((1 << LCD_DDRAM) + LCD_START_LINE1, 0); | ||||
|         } | ||||
| #endif | ||||
| #    endif | ||||
|         lcd_waitbusy(); | ||||
| #endif | ||||
|         lcd_write(c, 1); | ||||
|     } | ||||
| 
 | ||||
| }/* lcd_putc */ | ||||
| 
 | ||||
| } /* lcd_putc */ | ||||
| 
 | ||||
| /*************************************************************************
 | ||||
| Display string without auto linefeed  | ||||
| Display string without auto linefeed | ||||
| Input:    string to be displayed | ||||
| Returns:  none | ||||
| *************************************************************************/ | ||||
|  | @ -468,16 +425,15 @@ void lcd_puts(const char *s) | |||
| { | ||||
|     register char c; | ||||
| 
 | ||||
|     while ( (c = *s++) ) { | ||||
|     while ((c = *s++)) { | ||||
|         lcd_putc(c); | ||||
|     } | ||||
| 
 | ||||
| }/* lcd_puts */ | ||||
| 
 | ||||
| } /* lcd_puts */ | ||||
| 
 | ||||
| /*************************************************************************
 | ||||
| Display string from program memory without auto linefeed  | ||||
| Input:     string from program memory be be displayed                                         | ||||
| Display string from program memory without auto linefeed | ||||
| Input:     string from program memory be be displayed | ||||
| Returns:   none | ||||
| *************************************************************************/ | ||||
| void lcd_puts_p(const char *progmem_s) | ||||
|  | @ -485,108 +441,96 @@ void lcd_puts_p(const char *progmem_s) | |||
| { | ||||
|     register char c; | ||||
| 
 | ||||
|     while ( (c = pgm_read_byte(progmem_s++)) ) { | ||||
|     while ((c = pgm_read_byte(progmem_s++))) { | ||||
|         lcd_putc(c); | ||||
|     } | ||||
| 
 | ||||
| }/* lcd_puts_p */ | ||||
| 
 | ||||
| } /* lcd_puts_p */ | ||||
| 
 | ||||
| /*************************************************************************
 | ||||
| Initialize display and select type of cursor  | ||||
| Initialize display and select type of cursor | ||||
| Input:    dispAttr LCD_DISP_OFF            display off | ||||
|                    LCD_DISP_ON             display on, cursor off | ||||
|                    LCD_DISP_ON_CURSOR      display on, cursor on | ||||
|                    LCD_DISP_CURSOR_BLINK   display on, cursor on flashing | ||||
| Returns:  none | ||||
| *************************************************************************/ | ||||
| void lcd_init(uint8_t dispAttr) | ||||
| { | ||||
| void lcd_init(uint8_t dispAttr) { | ||||
| #if LCD_IO_MODE | ||||
|     /*
 | ||||
|      *  Initialize LCD to 4 bit I/O mode | ||||
|      */ | ||||
|       | ||||
|     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 ) ) | ||||
|     { | ||||
| 
 | ||||
|     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)) { | ||||
|         /* configure all port bits as output (all LCD lines on same port) */ | ||||
|         DDR(LCD_DATA0_PORT) |= 0x7F; | ||||
|     } | ||||
|     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) ) | ||||
|     { | ||||
|     } 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)) { | ||||
|         /* configure all port bits as output (all LCD data lines on same port, but control lines on different ports) */ | ||||
|         DDR(LCD_DATA0_PORT) |= 0x0F; | ||||
|         DDR(LCD_RS_PORT)    |= _BV(LCD_RS_PIN); | ||||
|         DDR(LCD_RW_PORT)    |= _BV(LCD_RW_PIN); | ||||
|         DDR(LCD_E_PORT)     |= _BV(LCD_E_PIN); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         DDR(LCD_RS_PORT) |= _BV(LCD_RS_PIN); | ||||
|         DDR(LCD_RW_PORT) |= _BV(LCD_RW_PIN); | ||||
|         DDR(LCD_E_PORT) |= _BV(LCD_E_PIN); | ||||
|     } else { | ||||
|         /* configure all port bits as output (LCD data and control lines on different ports */ | ||||
|         DDR(LCD_RS_PORT)    |= _BV(LCD_RS_PIN); | ||||
|         DDR(LCD_RW_PORT)    |= _BV(LCD_RW_PIN); | ||||
|         DDR(LCD_E_PORT)     |= _BV(LCD_E_PIN); | ||||
|         DDR(LCD_RS_PORT) |= _BV(LCD_RS_PIN); | ||||
|         DDR(LCD_RW_PORT) |= _BV(LCD_RW_PIN); | ||||
|         DDR(LCD_E_PORT) |= _BV(LCD_E_PIN); | ||||
|         DDR(LCD_DATA0_PORT) |= _BV(LCD_DATA0_PIN); | ||||
|         DDR(LCD_DATA1_PORT) |= _BV(LCD_DATA1_PIN); | ||||
|         DDR(LCD_DATA2_PORT) |= _BV(LCD_DATA2_PIN); | ||||
|         DDR(LCD_DATA3_PORT) |= _BV(LCD_DATA3_PIN); | ||||
|     } | ||||
|     delay(LCD_DELAY_BOOTUP);             /* wait 16ms or more after power-on       */ | ||||
|      | ||||
|     delay(LCD_DELAY_BOOTUP); /* wait 16ms or more after power-on       */ | ||||
| 
 | ||||
|     /* initial write to lcd is 8bit */ | ||||
|     LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN);    // LCD_FUNCTION>>4;
 | ||||
|     LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN);    // LCD_FUNCTION_8BIT>>4;
 | ||||
|     LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN);  // LCD_FUNCTION>>4;
 | ||||
|     LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN);  // LCD_FUNCTION_8BIT>>4;
 | ||||
|     lcd_e_toggle(); | ||||
|     delay(LCD_DELAY_INIT);               /* delay, busy flag can't be checked here */ | ||||
|     | ||||
|     /* repeat last command */  | ||||
|     lcd_e_toggle();       | ||||
|     delay(LCD_DELAY_INIT_REP);           /* delay, busy flag can't be checked here */ | ||||
|      | ||||
|     delay(LCD_DELAY_INIT); /* delay, busy flag can't be checked here */ | ||||
| 
 | ||||
|     /* repeat last command */ | ||||
|     lcd_e_toggle(); | ||||
|     delay(LCD_DELAY_INIT_REP); /* delay, busy flag can't be checked here */ | ||||
| 
 | ||||
|     /* repeat last command a third time */ | ||||
|     lcd_e_toggle();       | ||||
|     delay(LCD_DELAY_INIT_REP);           /* delay, busy flag can't be checked here */ | ||||
|     lcd_e_toggle(); | ||||
|     delay(LCD_DELAY_INIT_REP); /* delay, busy flag can't be checked here */ | ||||
| 
 | ||||
|     /* now configure for 4bit mode */ | ||||
|     LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN);   // LCD_FUNCTION_4BIT_1LINE>>4
 | ||||
|     LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN);  // LCD_FUNCTION_4BIT_1LINE>>4
 | ||||
|     lcd_e_toggle(); | ||||
|     delay(LCD_DELAY_INIT_4BIT);          /* some displays need this additional delay */ | ||||
|      | ||||
|     /* from now the LCD only accepts 4 bit I/O, we can use lcd_command() */     | ||||
|     delay(LCD_DELAY_INIT_4BIT); /* some displays need this additional delay */ | ||||
| 
 | ||||
|     /* from now the LCD only accepts 4 bit I/O, we can use lcd_command() */ | ||||
| #else | ||||
|     /*
 | ||||
|      * Initialize LCD to 8 bit memory mapped mode | ||||
|      */ | ||||
|      | ||||
|     /* enable external SRAM (memory mapped lcd) and one wait state */         | ||||
| 
 | ||||
|     /* enable external SRAM (memory mapped lcd) and one wait state */ | ||||
|     MCUCR = _BV(SRE) | _BV(SRW); | ||||
| 
 | ||||
|     /* reset LCD */ | ||||
|     delay(LCD_DELAY_BOOTUP);                    /* wait 16ms after power-on     */ | ||||
|     lcd_write(LCD_FUNCTION_8BIT_1LINE,0);   /* function set: 8bit interface */                    | ||||
|     delay(LCD_DELAY_INIT);                      /* wait 5ms                     */ | ||||
|     lcd_write(LCD_FUNCTION_8BIT_1LINE,0);   /* function set: 8bit interface */                  | ||||
|     delay(LCD_DELAY_INIT_REP);                  /* wait 64us                    */ | ||||
|     lcd_write(LCD_FUNCTION_8BIT_1LINE,0);   /* function set: 8bit interface */                 | ||||
|     delay(LCD_DELAY_INIT_REP);                  /* wait 64us                    */ | ||||
|     delay(LCD_DELAY_BOOTUP);               /* wait 16ms after power-on     */ | ||||
|     lcd_write(LCD_FUNCTION_8BIT_1LINE, 0); /* function set: 8bit interface */ | ||||
|     delay(LCD_DELAY_INIT);                 /* wait 5ms                     */ | ||||
|     lcd_write(LCD_FUNCTION_8BIT_1LINE, 0); /* function set: 8bit interface */ | ||||
|     delay(LCD_DELAY_INIT_REP);             /* wait 64us                    */ | ||||
|     lcd_write(LCD_FUNCTION_8BIT_1LINE, 0); /* function set: 8bit interface */ | ||||
|     delay(LCD_DELAY_INIT_REP);             /* wait 64us                    */ | ||||
| #endif | ||||
| 
 | ||||
| #if KS0073_4LINES_MODE | ||||
|     /* Display with KS0073 controller requires special commands for enabling 4 line mode */ | ||||
| 	lcd_command(KS0073_EXTENDED_FUNCTION_REGISTER_ON); | ||||
| 	lcd_command(KS0073_4LINES_MODE); | ||||
| 	lcd_command(KS0073_EXTENDED_FUNCTION_REGISTER_OFF); | ||||
|     lcd_command(KS0073_EXTENDED_FUNCTION_REGISTER_ON); | ||||
|     lcd_command(KS0073_4LINES_MODE); | ||||
|     lcd_command(KS0073_EXTENDED_FUNCTION_REGISTER_OFF); | ||||
| #else | ||||
|     lcd_command(LCD_FUNCTION_DEFAULT);      /* function set: display lines  */ | ||||
|     lcd_command(LCD_FUNCTION_DEFAULT);     /* function set: display lines  */ | ||||
| #endif | ||||
|     lcd_command(LCD_DISP_OFF);              /* display off                  */ | ||||
|     lcd_clrscr();                           /* display clear                */  | ||||
|     lcd_command(LCD_MODE_DEFAULT);          /* set entry mode               */ | ||||
|     lcd_command(dispAttr);                  /* display/cursor control       */ | ||||
| 
 | ||||
| }/* lcd_init */ | ||||
|     lcd_command(LCD_DISP_OFF);     /* display off                  */ | ||||
|     lcd_clrscr();                  /* display clear                */ | ||||
|     lcd_command(LCD_MODE_DEFAULT); /* set entry mode               */ | ||||
|     lcd_command(dispAttr);         /* display/cursor control       */ | ||||
| 
 | ||||
| } /* lcd_init */ | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ | |||
|  License:   GNU General Public License Version 3 | ||||
|  File:	    $Id: lcd.h,v 1.14.2.4 2015/01/20 17:16:07 peter Exp $ | ||||
|  Software:  AVR-GCC 4.x | ||||
|  Hardware:  any AVR device, memory mapped mode only for AVR with  | ||||
|  Hardware:  any AVR device, memory mapped mode only for AVR with | ||||
|             memory mapped interface (AT90S8515/ATmega8515/ATmega128) | ||||
| ***************************************************************************/ | ||||
| 
 | ||||
|  | @ -15,333 +15,315 @@ | |||
|  Collection of libraries for AVR-GCC | ||||
|  @author Peter Fleury pfleury@gmx.ch http://tinyurl.com/peterfleury
 | ||||
|  @copyright (C) 2015 Peter Fleury, GNU General Public License Version 3 | ||||
|   | ||||
| 
 | ||||
|  @file | ||||
|  @defgroup pfleury_lcd LCD library <lcd.h> | ||||
|  @code #include <lcd.h> @endcode | ||||
|   | ||||
| 
 | ||||
|  @brief Basic routines for interfacing a HD44780U-based character LCD display | ||||
| 
 | ||||
|  LCD character displays can be found in many devices, like espresso machines, laser printers.  | ||||
|  The Hitachi HD44780 controller and its compatible controllers like Samsung KS0066U have become an industry standard for these types of displays.  | ||||
|   | ||||
|  LCD character displays can be found in many devices, like espresso machines, laser printers. | ||||
|  The Hitachi HD44780 controller and its compatible controllers like Samsung KS0066U have become an industry standard for these types of displays. | ||||
| 
 | ||||
|  This library allows easy interfacing with a HD44780 compatible display and can be | ||||
|  operated in memory mapped mode (LCD_IO_MODE defined as 0 in the include file lcd.h.) or in  | ||||
|  operated in memory mapped mode (LCD_IO_MODE defined as 0 in the include file lcd.h.) or in | ||||
|  4-bit IO port mode (LCD_IO_MODE defined as 1). 8-bit IO port mode is not supported. | ||||
| 
 | ||||
|  Memory mapped mode is compatible with old Kanda STK200 starter kit, but also supports | ||||
|  generation of R/W signal through A8 address line. | ||||
| 
 | ||||
|  @see The chapter <a href=" http://homepage.hispeed.ch/peterfleury/avr-lcd44780.html" target="_blank">Interfacing a HD44780 Based LCD to an AVR</a> | ||||
|       on my home page, which shows example circuits how to connect an LCD to an AVR controller.  | ||||
|       on my home page, which shows example circuits how to connect an LCD to an AVR controller. | ||||
| 
 | ||||
|  @author Peter Fleury pfleury@gmx.ch http://tinyurl.com/peterfleury
 | ||||
|   | ||||
| 
 | ||||
|  @version   2.0 | ||||
|   | ||||
| 
 | ||||
|  @copyright (C) 2015 Peter Fleury, GNU General Public License Version 3 | ||||
|    | ||||
| 
 | ||||
| */ | ||||
| 
 | ||||
| #include <inttypes.h> | ||||
| #include <avr/pgmspace.h> | ||||
| 
 | ||||
| #if (__GNUC__ * 100 + __GNUC_MINOR__) < 405 | ||||
| #error "This library requires AVR-GCC 4.5 or later, update to newer AVR-GCC compiler !" | ||||
| #    error "This library requires AVR-GCC 4.5 or later, update to newer AVR-GCC compiler !" | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /**@{*/ | ||||
| 
 | ||||
| /*
 | ||||
|  * LCD and target specific definitions below can be defined in a separate include file with name lcd_definitions.h instead modifying this file  | ||||
|  * LCD and target specific definitions below can be defined in a separate include file with name lcd_definitions.h instead modifying this file | ||||
|  * by adding -D_LCD_DEFINITIONS_FILE to the CDEFS section in the Makefile | ||||
|  * All definitions added to the file lcd_definitions.h will override the default definitions from lcd.h | ||||
|  */ | ||||
| #ifdef _LCD_DEFINITIONS_FILE | ||||
| #include "lcd_definitions.h" | ||||
| #    include "lcd_definitions.h" | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  * @name  Definition for LCD controller type | ||||
|  * Use 0 for HD44780 controller, change to 1 for displays with KS0073 controller. | ||||
|  */ | ||||
| #ifndef LCD_CONTROLLER_KS0073  | ||||
| #define LCD_CONTROLLER_KS0073 0  /**< Use 0 for HD44780 controller, 1 for KS0073 controller */ | ||||
| #ifndef LCD_CONTROLLER_KS0073 | ||||
| #    define LCD_CONTROLLER_KS0073 0 /**< Use 0 for HD44780 controller, 1 for KS0073 controller */ | ||||
| #endif | ||||
| 
 | ||||
| /** 
 | ||||
|  * @name  Definitions for Display Size  | ||||
| /**
 | ||||
|  * @name  Definitions for Display Size | ||||
|  * Change these definitions to adapt setting to your display | ||||
|  * | ||||
|  * These definitions can be defined in a separate include file \b lcd_definitions.h instead modifying this file by  | ||||
|  * These definitions can be defined in a separate include file \b lcd_definitions.h instead modifying this file by | ||||
|  * adding -D_LCD_DEFINITIONS_FILE to the CDEFS section in the Makefile. | ||||
|  * All definitions added to the file lcd_definitions.h will override the default definitions from lcd.h | ||||
|  * | ||||
|  */ | ||||
| #ifndef LCD_LINES | ||||
| #define LCD_LINES           2     /**< number of visible lines of the display */ | ||||
| #    define LCD_LINES 2 /**< number of visible lines of the display */ | ||||
| #endif | ||||
| #ifndef LCD_DISP_LENGTH | ||||
| #define LCD_DISP_LENGTH    16     /**< visibles characters per line of the display */ | ||||
| #    define LCD_DISP_LENGTH 16 /**< visibles characters per line of the display */ | ||||
| #endif | ||||
| #ifndef LCD_LINE_LENGTH | ||||
| #define LCD_LINE_LENGTH  0x40     /**< internal line length of the display    */ | ||||
| #    define LCD_LINE_LENGTH 0x40 /**< internal line length of the display    */ | ||||
| #endif | ||||
| #ifndef LCD_START_LINE1 | ||||
| #define LCD_START_LINE1  0x00     /**< DDRAM address of first char of line 1 */ | ||||
| #    define LCD_START_LINE1 0x00 /**< DDRAM address of first char of line 1 */ | ||||
| #endif | ||||
| #ifndef LCD_START_LINE2 | ||||
| #define LCD_START_LINE2  0x40     /**< DDRAM address of first char of line 2 */ | ||||
| #    define LCD_START_LINE2 0x40 /**< DDRAM address of first char of line 2 */ | ||||
| #endif | ||||
| #ifndef LCD_START_LINE3 | ||||
| #define LCD_START_LINE3  0x14     /**< DDRAM address of first char of line 3 */ | ||||
| #    define LCD_START_LINE3 0x14 /**< DDRAM address of first char of line 3 */ | ||||
| #endif | ||||
| #ifndef LCD_START_LINE4 | ||||
| #define LCD_START_LINE4  0x54     /**< DDRAM address of first char of line 4 */ | ||||
| #    define LCD_START_LINE4 0x54 /**< DDRAM address of first char of line 4 */ | ||||
| #endif | ||||
| #ifndef LCD_WRAP_LINES | ||||
| #define LCD_WRAP_LINES      0     /**< 0: no wrap, 1: wrap at end of visibile line */ | ||||
| #    define LCD_WRAP_LINES 0 /**< 0: no wrap, 1: wrap at end of visibile line */ | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  * @name Definitions for 4-bit IO mode | ||||
|  * | ||||
|  * The four LCD data lines and the three control lines RS, RW, E can be on the  | ||||
|  * same port or on different ports.  | ||||
|  * The four LCD data lines and the three control lines RS, RW, E can be on the | ||||
|  * same port or on different ports. | ||||
|  * Change LCD_RS_PORT, LCD_RW_PORT, LCD_E_PORT if you want the control lines on | ||||
|  * different ports.  | ||||
|  * different ports. | ||||
|  * | ||||
|  * Normally the four data lines should be mapped to bit 0..3 on one port, but it | ||||
|  * is possible to connect these data lines in different order or even on different | ||||
|  * ports by adapting the LCD_DATAx_PORT and LCD_DATAx_PIN definitions. | ||||
|  * | ||||
|  * Adjust these definitions to your target.\n  | ||||
|  * These definitions can be defined in a separate include file \b lcd_definitions.h instead modifying this file by  | ||||
|  * Adjust these definitions to your target.\n | ||||
|  * These definitions can be defined in a separate include file \b lcd_definitions.h instead modifying this file by | ||||
|  * adding \b -D_LCD_DEFINITIONS_FILE to the \b CDEFS section in the Makefile. | ||||
|  * All definitions added to the file lcd_definitions.h will override the default definitions from lcd.h | ||||
|  *   | ||||
|  * | ||||
|  */ | ||||
| #define LCD_IO_MODE      1            /**< 0: memory mapped mode, 1: IO port mode */ | ||||
| #define LCD_IO_MODE 1 /**< 0: memory mapped mode, 1: IO port mode */ | ||||
| 
 | ||||
| #if LCD_IO_MODE | ||||
| 
 | ||||
| #ifndef LCD_PORT | ||||
| #define LCD_PORT         PORTA        /**< port for the LCD lines   */ | ||||
| #endif | ||||
| #ifndef LCD_DATA0_PORT | ||||
| #define LCD_DATA0_PORT   LCD_PORT     /**< port for 4bit data bit 0 */ | ||||
| #endif | ||||
| #ifndef LCD_DATA1_PORT | ||||
| #define LCD_DATA1_PORT   LCD_PORT     /**< port for 4bit data bit 1 */ | ||||
| #endif | ||||
| #ifndef LCD_DATA2_PORT | ||||
| #define LCD_DATA2_PORT   LCD_PORT     /**< port for 4bit data bit 2 */ | ||||
| #endif | ||||
| #ifndef LCD_DATA3_PORT | ||||
| #define LCD_DATA3_PORT   LCD_PORT     /**< port for 4bit data bit 3 */ | ||||
| #endif | ||||
| #ifndef LCD_DATA0_PIN | ||||
| #define LCD_DATA0_PIN    4            /**< pin for 4bit data bit 0  */ | ||||
| #endif | ||||
| #ifndef LCD_DATA1_PIN | ||||
| #define LCD_DATA1_PIN    5            /**< pin for 4bit data bit 1  */ | ||||
| #endif | ||||
| #ifndef LCD_DATA2_PIN | ||||
| #define LCD_DATA2_PIN    6            /**< pin for 4bit data bit 2  */ | ||||
| #endif | ||||
| #ifndef LCD_DATA3_PIN | ||||
| #define LCD_DATA3_PIN    7            /**< pin for 4bit data bit 3  */ | ||||
| #endif | ||||
| #ifndef LCD_RS_PORT | ||||
| #define LCD_RS_PORT      LCD_PORT     /**< port for RS line         */ | ||||
| #endif | ||||
| #ifndef LCD_RS_PIN | ||||
| #define LCD_RS_PIN       3            /**< pin  for RS line         */ | ||||
| #endif | ||||
| #ifndef LCD_RW_PORT | ||||
| #define LCD_RW_PORT      LCD_PORT     /**< port for RW line         */ | ||||
| #endif | ||||
| #ifndef LCD_RW_PIN | ||||
| #define LCD_RW_PIN       2            /**< pin  for RW line         */ | ||||
| #endif | ||||
| #ifndef LCD_E_PORT | ||||
| #define LCD_E_PORT       LCD_PORT     /**< port for Enable line     */ | ||||
| #endif | ||||
| #ifndef LCD_E_PIN | ||||
| #define LCD_E_PIN        1            /**< pin  for Enable line     */ | ||||
| #endif | ||||
| #    ifndef LCD_PORT | ||||
| #        define LCD_PORT PORTA /**< port for the LCD lines   */ | ||||
| #    endif | ||||
| #    ifndef LCD_DATA0_PORT | ||||
| #        define LCD_DATA0_PORT LCD_PORT /**< port for 4bit data bit 0 */ | ||||
| #    endif | ||||
| #    ifndef LCD_DATA1_PORT | ||||
| #        define LCD_DATA1_PORT LCD_PORT /**< port for 4bit data bit 1 */ | ||||
| #    endif | ||||
| #    ifndef LCD_DATA2_PORT | ||||
| #        define LCD_DATA2_PORT LCD_PORT /**< port for 4bit data bit 2 */ | ||||
| #    endif | ||||
| #    ifndef LCD_DATA3_PORT | ||||
| #        define LCD_DATA3_PORT LCD_PORT /**< port for 4bit data bit 3 */ | ||||
| #    endif | ||||
| #    ifndef LCD_DATA0_PIN | ||||
| #        define LCD_DATA0_PIN 4 /**< pin for 4bit data bit 0  */ | ||||
| #    endif | ||||
| #    ifndef LCD_DATA1_PIN | ||||
| #        define LCD_DATA1_PIN 5 /**< pin for 4bit data bit 1  */ | ||||
| #    endif | ||||
| #    ifndef LCD_DATA2_PIN | ||||
| #        define LCD_DATA2_PIN 6 /**< pin for 4bit data bit 2  */ | ||||
| #    endif | ||||
| #    ifndef LCD_DATA3_PIN | ||||
| #        define LCD_DATA3_PIN 7 /**< pin for 4bit data bit 3  */ | ||||
| #    endif | ||||
| #    ifndef LCD_RS_PORT | ||||
| #        define LCD_RS_PORT LCD_PORT /**< port for RS line         */ | ||||
| #    endif | ||||
| #    ifndef LCD_RS_PIN | ||||
| #        define LCD_RS_PIN 3 /**< pin  for RS line         */ | ||||
| #    endif | ||||
| #    ifndef LCD_RW_PORT | ||||
| #        define LCD_RW_PORT LCD_PORT /**< port for RW line         */ | ||||
| #    endif | ||||
| #    ifndef LCD_RW_PIN | ||||
| #        define LCD_RW_PIN 2 /**< pin  for RW line         */ | ||||
| #    endif | ||||
| #    ifndef LCD_E_PORT | ||||
| #        define LCD_E_PORT LCD_PORT /**< port for Enable line     */ | ||||
| #    endif | ||||
| #    ifndef LCD_E_PIN | ||||
| #        define LCD_E_PIN 1 /**< pin  for Enable line     */ | ||||
| #    endif | ||||
| 
 | ||||
| #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__) | ||||
| #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__) | ||||
| /*
 | ||||
|  * memory mapped mode is only supported when the device has an external data memory interface | ||||
|  */ | ||||
| #define LCD_IO_DATA      0xC000    /* A15=E=1, A14=RS=1                 */ | ||||
| #define LCD_IO_FUNCTION  0x8000    /* A15=E=1, A14=RS=0                 */ | ||||
| #define LCD_IO_READ      0x0100    /* A8 =R/W=1 (R/W: 1=Read, 0=Write   */ | ||||
| #    define LCD_IO_DATA 0xC000     /* A15=E=1, A14=RS=1                 */ | ||||
| #    define LCD_IO_FUNCTION 0x8000 /* A15=E=1, A14=RS=0                 */ | ||||
| #    define LCD_IO_READ 0x0100     /* A8 =R/W=1 (R/W: 1=Read, 0=Write   */ | ||||
| 
 | ||||
| #else | ||||
| #error "external data memory interface not available for this device, use 4-bit IO port mode" | ||||
| #    error "external data memory interface not available for this device, use 4-bit IO port mode" | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  * @name Definitions of delays | ||||
|  * Used to calculate delay timers. | ||||
|  * Adapt the F_CPU define in the Makefile to the clock frequency in Hz of your target | ||||
|  * | ||||
|  * These delay times can be adjusted, if some displays require different delays.\n  | ||||
|  * These definitions can be defined in a separate include file \b lcd_definitions.h instead modifying this file by  | ||||
|  * These delay times can be adjusted, if some displays require different delays.\n | ||||
|  * These definitions can be defined in a separate include file \b lcd_definitions.h instead modifying this file by | ||||
|  * adding \b -D_LCD_DEFINITIONS_FILE to the \b CDEFS section in the Makefile. | ||||
|  * All definitions added to the file lcd_definitions.h will override the default definitions from lcd.h | ||||
|  */ | ||||
| #ifndef LCD_DELAY_BOOTUP | ||||
| #define LCD_DELAY_BOOTUP   16000      /**< delay in micro seconds after power-on  */ | ||||
| #    define LCD_DELAY_BOOTUP 16000 /**< delay in micro seconds after power-on  */ | ||||
| #endif | ||||
| #ifndef LCD_DELAY_INIT | ||||
| #define LCD_DELAY_INIT      5000      /**< delay in micro seconds after initialization command sent  */ | ||||
| #    define LCD_DELAY_INIT 5000 /**< delay in micro seconds after initialization command sent  */ | ||||
| #endif | ||||
| #ifndef LCD_DELAY_INIT_REP | ||||
| #define LCD_DELAY_INIT_REP    64      /**< delay in micro seconds after initialization command repeated */ | ||||
| #    define LCD_DELAY_INIT_REP 64 /**< delay in micro seconds after initialization command repeated */ | ||||
| #endif | ||||
| #ifndef LCD_DELAY_INIT_4BIT | ||||
| #define LCD_DELAY_INIT_4BIT   64      /**< delay in micro seconds after setting 4-bit mode */  | ||||
| #    define LCD_DELAY_INIT_4BIT 64 /**< delay in micro seconds after setting 4-bit mode */ | ||||
| #endif | ||||
| #ifndef LCD_DELAY_BUSY_FLAG | ||||
| #define LCD_DELAY_BUSY_FLAG    4      /**< time in micro seconds the address counter is updated after busy flag is cleared */ | ||||
| #    define LCD_DELAY_BUSY_FLAG 4 /**< time in micro seconds the address counter is updated after busy flag is cleared */ | ||||
| #endif | ||||
| #ifndef LCD_DELAY_ENABLE_PULSE | ||||
| #define LCD_DELAY_ENABLE_PULSE 1      /**< enable signal pulse width in micro seconds */ | ||||
| #    define LCD_DELAY_ENABLE_PULSE 1 /**< enable signal pulse width in micro seconds */ | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  * @name Definitions for LCD command instructions | ||||
|  * The constants define the various LCD controller instructions which can be passed to the  | ||||
|  * The constants define the various LCD controller instructions which can be passed to the | ||||
|  * function lcd_command(), see HD44780 data sheet for a complete description. | ||||
|  */ | ||||
| 
 | ||||
| /* instruction register bit positions, see HD44780U data sheet */ | ||||
| #define LCD_CLR               0      /* DB0: clear display                  */ | ||||
| #define LCD_HOME              1      /* DB1: return to home position        */ | ||||
| #define LCD_ENTRY_MODE        2      /* DB2: set entry mode                 */ | ||||
| #define LCD_ENTRY_INC         1      /*   DB1: 1=increment, 0=decrement     */ | ||||
| #define LCD_ENTRY_SHIFT       0      /*   DB2: 1=display shift on           */ | ||||
| #define LCD_ON                3      /* DB3: turn lcd/cursor on             */ | ||||
| #define LCD_ON_DISPLAY        2      /*   DB2: turn display on              */ | ||||
| #define LCD_ON_CURSOR         1      /*   DB1: turn cursor on               */ | ||||
| #define LCD_ON_BLINK          0      /*     DB0: blinking cursor ?          */ | ||||
| #define LCD_MOVE              4      /* DB4: move cursor/display            */ | ||||
| #define LCD_MOVE_DISP         3      /*   DB3: move display (0-> cursor) ?  */ | ||||
| #define LCD_MOVE_RIGHT        2      /*   DB2: move right (0-> left) ?      */ | ||||
| #define LCD_FUNCTION          5      /* DB5: function set                   */ | ||||
| #define LCD_FUNCTION_8BIT     4      /*   DB4: set 8BIT mode (0->4BIT mode) */ | ||||
| #define LCD_FUNCTION_2LINES   3      /*   DB3: two lines (0->one line)      */ | ||||
| #define LCD_FUNCTION_10DOTS   2      /*   DB2: 5x10 font (0->5x7 font)      */ | ||||
| #define LCD_CGRAM             6      /* DB6: set CG RAM address             */ | ||||
| #define LCD_DDRAM             7      /* DB7: set DD RAM address             */ | ||||
| #define LCD_BUSY              7      /* DB7: LCD is busy                    */ | ||||
| #define LCD_CLR 0             /* DB0: clear display                  */ | ||||
| #define LCD_HOME 1            /* DB1: return to home position        */ | ||||
| #define LCD_ENTRY_MODE 2      /* DB2: set entry mode                 */ | ||||
| #define LCD_ENTRY_INC 1       /*   DB1: 1=increment, 0=decrement     */ | ||||
| #define LCD_ENTRY_SHIFT 0     /*   DB2: 1=display shift on           */ | ||||
| #define LCD_ON 3              /* DB3: turn lcd/cursor on             */ | ||||
| #define LCD_ON_DISPLAY 2      /*   DB2: turn display on              */ | ||||
| #define LCD_ON_CURSOR 1       /*   DB1: turn cursor on               */ | ||||
| #define LCD_ON_BLINK 0        /*     DB0: blinking cursor ?          */ | ||||
| #define LCD_MOVE 4            /* DB4: move cursor/display            */ | ||||
| #define LCD_MOVE_DISP 3       /*   DB3: move display (0-> cursor) ?  */ | ||||
| #define LCD_MOVE_RIGHT 2      /*   DB2: move right (0-> left) ?      */ | ||||
| #define LCD_FUNCTION 5        /* DB5: function set                   */ | ||||
| #define LCD_FUNCTION_8BIT 4   /*   DB4: set 8BIT mode (0->4BIT mode) */ | ||||
| #define LCD_FUNCTION_2LINES 3 /*   DB3: two lines (0->one line)      */ | ||||
| #define LCD_FUNCTION_10DOTS 2 /*   DB2: 5x10 font (0->5x7 font)      */ | ||||
| #define LCD_CGRAM 6           /* DB6: set CG RAM address             */ | ||||
| #define LCD_DDRAM 7           /* DB7: set DD RAM address             */ | ||||
| #define LCD_BUSY 7            /* DB7: LCD is busy                    */ | ||||
| 
 | ||||
| /* set entry mode: display shift on/off, dec/inc cursor move direction */ | ||||
| #define LCD_ENTRY_DEC            0x04   /* display shift off, dec cursor move dir */ | ||||
| #define LCD_ENTRY_DEC_SHIFT      0x05   /* display shift on,  dec cursor move dir */ | ||||
| #define LCD_ENTRY_INC_           0x06   /* display shift off, inc cursor move dir */ | ||||
| #define LCD_ENTRY_INC_SHIFT      0x07   /* display shift on,  inc cursor move dir */ | ||||
| #define LCD_ENTRY_DEC 0x04       /* display shift off, dec cursor move dir */ | ||||
| #define LCD_ENTRY_DEC_SHIFT 0x05 /* display shift on,  dec cursor move dir */ | ||||
| #define LCD_ENTRY_INC_ 0x06      /* display shift off, inc cursor move dir */ | ||||
| #define LCD_ENTRY_INC_SHIFT 0x07 /* display shift on,  inc cursor move dir */ | ||||
| 
 | ||||
| /* display on/off, cursor on/off, blinking char at cursor position */ | ||||
| #define LCD_DISP_OFF             0x08   /* display off                            */ | ||||
| #define LCD_DISP_ON              0x0C   /* display on, cursor off                 */ | ||||
| #define LCD_DISP_ON_BLINK        0x0D   /* display on, cursor off, blink char     */ | ||||
| #define LCD_DISP_ON_CURSOR       0x0E   /* display on, cursor on                  */ | ||||
| #define LCD_DISP_ON_CURSOR_BLINK 0x0F   /* display on, cursor on, blink char      */ | ||||
| #define LCD_DISP_OFF 0x08             /* display off                            */ | ||||
| #define LCD_DISP_ON 0x0C              /* display on, cursor off                 */ | ||||
| #define LCD_DISP_ON_BLINK 0x0D        /* display on, cursor off, blink char     */ | ||||
| #define LCD_DISP_ON_CURSOR 0x0E       /* display on, cursor on                  */ | ||||
| #define LCD_DISP_ON_CURSOR_BLINK 0x0F /* display on, cursor on, blink char      */ | ||||
| 
 | ||||
| /* move cursor/shift display */ | ||||
| #define LCD_MOVE_CURSOR_LEFT     0x10   /* move cursor left  (decrement)          */ | ||||
| #define LCD_MOVE_CURSOR_RIGHT    0x14   /* move cursor right (increment)          */ | ||||
| #define LCD_MOVE_DISP_LEFT       0x18   /* shift display left                     */ | ||||
| #define LCD_MOVE_DISP_RIGHT      0x1C   /* shift display right                    */ | ||||
| #define LCD_MOVE_CURSOR_LEFT 0x10  /* move cursor left  (decrement)          */ | ||||
| #define LCD_MOVE_CURSOR_RIGHT 0x14 /* move cursor right (increment)          */ | ||||
| #define LCD_MOVE_DISP_LEFT 0x18    /* shift display left                     */ | ||||
| #define LCD_MOVE_DISP_RIGHT 0x1C   /* shift display right                    */ | ||||
| 
 | ||||
| /* function set: set interface data length and number of display lines */ | ||||
| #define LCD_FUNCTION_4BIT_1LINE  0x20   /* 4-bit interface, single line, 5x7 dots */ | ||||
| #define LCD_FUNCTION_4BIT_2LINES 0x28   /* 4-bit interface, dual line,   5x7 dots */ | ||||
| #define LCD_FUNCTION_8BIT_1LINE  0x30   /* 8-bit interface, single line, 5x7 dots */ | ||||
| #define LCD_FUNCTION_8BIT_2LINES 0x38   /* 8-bit interface, dual line,   5x7 dots */ | ||||
| #define LCD_FUNCTION_4BIT_1LINE 0x20  /* 4-bit interface, single line, 5x7 dots */ | ||||
| #define LCD_FUNCTION_4BIT_2LINES 0x28 /* 4-bit interface, dual line,   5x7 dots */ | ||||
| #define LCD_FUNCTION_8BIT_1LINE 0x30  /* 8-bit interface, single line, 5x7 dots */ | ||||
| #define LCD_FUNCTION_8BIT_2LINES 0x38 /* 8-bit interface, dual line,   5x7 dots */ | ||||
| 
 | ||||
| #define LCD_MODE_DEFAULT ((1 << LCD_ENTRY_MODE) | (1 << LCD_ENTRY_INC)) | ||||
| 
 | ||||
| #define LCD_MODE_DEFAULT     ((1<<LCD_ENTRY_MODE) | (1<<LCD_ENTRY_INC) ) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /** 
 | ||||
| /**
 | ||||
|  *  @name Functions | ||||
|  */ | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  @brief    Initialize display and select type of cursor | ||||
|  @param    dispAttr \b LCD_DISP_OFF display off\n | ||||
|                     \b LCD_DISP_ON display on, cursor off\n | ||||
|                     \b LCD_DISP_ON_CURSOR display on, cursor on\n | ||||
|                     \b LCD_DISP_ON_CURSOR_BLINK display on, cursor on flashing              | ||||
|                     \b LCD_DISP_ON_CURSOR_BLINK display on, cursor on flashing | ||||
|  @return  none | ||||
| */ | ||||
| extern void lcd_init(uint8_t dispAttr); | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  @brief    Clear display and set cursor to home position | ||||
|  @return   none | ||||
| */ | ||||
| extern void lcd_clrscr(void); | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  @brief    Set cursor to home position | ||||
|  @return   none | ||||
| */ | ||||
| extern void lcd_home(void); | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  @brief    Set cursor to specified position | ||||
|   | ||||
| 
 | ||||
|  @param    x horizontal position\n (0: left most position) | ||||
|  @param    y vertical position\n   (0: first line) | ||||
|  @return   none | ||||
| */ | ||||
| extern void lcd_gotoxy(uint8_t x, uint8_t y); | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  @brief    Display character at current cursor position | ||||
|  @param    c character to be displayed                                        | ||||
|  @param    c character to be displayed | ||||
|  @return   none | ||||
| */ | ||||
| extern void lcd_putc(char c); | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  @brief    Display string without auto linefeed | ||||
|  @param    s string to be displayed                                         | ||||
|  @param    s string to be displayed | ||||
|  @return   none | ||||
| */ | ||||
| extern void lcd_puts(const char *s); | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  @brief    Display string from program memory without auto linefeed | ||||
|  @param    progmem_s string from program memory be be displayed                                         | ||||
|  @param    progmem_s string from program memory be be displayed | ||||
|  @return   none | ||||
|  @see      lcd_puts_P | ||||
| */ | ||||
| extern void lcd_puts_p(const char *progmem_s); | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  @brief    Send LCD controller instruction command | ||||
|  @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); | |||
| */ | ||||
| extern void lcd_command(uint8_t cmd); | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  @brief    Send data byte to LCD controller  | ||||
|   | ||||
|  @brief    Send data byte to LCD controller | ||||
| 
 | ||||
|  Similar to lcd_putc(), but without interpreting LF | ||||
|  @param    data byte to send to LCD controller, see HD44780 data sheet | ||||
|  @return   none | ||||
| */ | ||||
| extern void lcd_data(uint8_t data); | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  @brief macros for automatically storing string constant in program memory | ||||
| */ | ||||
| #define lcd_puts_P(__s)         lcd_puts_p(PSTR(__s)) | ||||
| #define lcd_puts_P(__s) lcd_puts_p(PSTR(__s)) | ||||
| 
 | ||||
| /**@}*/ | ||||
| 
 | ||||
| #endif //LCD_H
 | ||||
| 
 | ||||
| #endif  // LCD_H
 | ||||
|  |  | |||
							
								
								
									
										250
									
								
								drivers/avr/i2c_master.c
									
										
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										250
									
								
								drivers/avr/i2c_master.c
									
										
									
									
									
										
										
										Executable file → Normal file
									
								
							|  | @ -25,200 +25,200 @@ | |||
| #include "wait.h" | ||||
| 
 | ||||
| #ifndef F_SCL | ||||
| #  define F_SCL 400000UL  // SCL frequency
 | ||||
| #    define F_SCL 400000UL  // SCL frequency
 | ||||
| #endif | ||||
| #define Prescaler 1 | ||||
| #define TWBR_val ((((F_CPU / F_SCL) / Prescaler) - 16) / 2) | ||||
| 
 | ||||
| void i2c_init(void) { | ||||
|   TWSR = 0; /* no prescaler */ | ||||
|   TWBR = (uint8_t)TWBR_val; | ||||
|     TWSR = 0; /* no prescaler */ | ||||
|     TWBR = (uint8_t)TWBR_val; | ||||
| 
 | ||||
|   #ifdef __AVR_ATmega32A__ | ||||
|   // set pull-up resistors on I2C bus pins
 | ||||
|   PORTC |= 0b11; | ||||
| #ifdef __AVR_ATmega32A__ | ||||
|     // set pull-up resistors on I2C bus pins
 | ||||
|     PORTC |= 0b11; | ||||
| 
 | ||||
|   // enable TWI (two-wire interface)
 | ||||
|   TWCR |= (1 << TWEN); | ||||
|     // enable TWI (two-wire interface)
 | ||||
|     TWCR |= (1 << TWEN); | ||||
| 
 | ||||
|   // enable TWI interrupt and slave address ACK
 | ||||
|   TWCR |= (1 << TWIE); | ||||
|   TWCR |= (1 << TWEA); | ||||
|   #endif | ||||
|     // enable TWI interrupt and slave address ACK
 | ||||
|     TWCR |= (1 << TWIE); | ||||
|     TWCR |= (1 << TWEA); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| i2c_status_t i2c_start(uint8_t address, uint16_t timeout) { | ||||
|   // reset TWI control register
 | ||||
|   TWCR = 0; | ||||
|   // transmit START condition
 | ||||
|   TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); | ||||
|     // reset TWI control register
 | ||||
|     TWCR = 0; | ||||
|     // transmit START condition
 | ||||
|     TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); | ||||
| 
 | ||||
|   uint16_t timeout_timer = timer_read(); | ||||
|   while (!(TWCR & (1 << TWINT))) { | ||||
|     if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { | ||||
|       return I2C_STATUS_TIMEOUT; | ||||
|     uint16_t timeout_timer = timer_read(); | ||||
|     while (!(TWCR & (1 << TWINT))) { | ||||
|         if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { | ||||
|             return I2C_STATUS_TIMEOUT; | ||||
|         } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   // check if the start condition was successfully transmitted
 | ||||
|   if (((TW_STATUS & 0xF8) != TW_START) && ((TW_STATUS & 0xF8) != TW_REP_START)) { | ||||
|     return I2C_STATUS_ERROR; | ||||
|   } | ||||
| 
 | ||||
|   // load slave address into data register
 | ||||
|   TWDR = address; | ||||
|   // start transmission of address
 | ||||
|   TWCR = (1 << TWINT) | (1 << TWEN); | ||||
| 
 | ||||
|   timeout_timer = timer_read(); | ||||
|   while (!(TWCR & (1 << TWINT))) { | ||||
|     if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { | ||||
|       return I2C_STATUS_TIMEOUT; | ||||
|     // check if the start condition was successfully transmitted
 | ||||
|     if (((TW_STATUS & 0xF8) != TW_START) && ((TW_STATUS & 0xF8) != TW_REP_START)) { | ||||
|         return I2C_STATUS_ERROR; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   // check if the device has acknowledged the READ / WRITE mode
 | ||||
|   uint8_t twst = TW_STATUS & 0xF8; | ||||
|   if ((twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK)) { | ||||
|     return I2C_STATUS_ERROR; | ||||
|   } | ||||
|     // load slave address into data register
 | ||||
|     TWDR = address; | ||||
|     // start transmission of address
 | ||||
|     TWCR = (1 << TWINT) | (1 << TWEN); | ||||
| 
 | ||||
|   return I2C_STATUS_SUCCESS; | ||||
|     timeout_timer = timer_read(); | ||||
|     while (!(TWCR & (1 << TWINT))) { | ||||
|         if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { | ||||
|             return I2C_STATUS_TIMEOUT; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // check if the device has acknowledged the READ / WRITE mode
 | ||||
|     uint8_t twst = TW_STATUS & 0xF8; | ||||
|     if ((twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK)) { | ||||
|         return I2C_STATUS_ERROR; | ||||
|     } | ||||
| 
 | ||||
|     return I2C_STATUS_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| i2c_status_t i2c_write(uint8_t data, uint16_t timeout) { | ||||
|   // load data into data register
 | ||||
|   TWDR = data; | ||||
|   // start transmission of data
 | ||||
|   TWCR = (1 << TWINT) | (1 << TWEN); | ||||
|     // load data into data register
 | ||||
|     TWDR = data; | ||||
|     // start transmission of data
 | ||||
|     TWCR = (1 << TWINT) | (1 << TWEN); | ||||
| 
 | ||||
|   uint16_t timeout_timer = timer_read(); | ||||
|   while (!(TWCR & (1 << TWINT))) { | ||||
|     if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { | ||||
|       return I2C_STATUS_TIMEOUT; | ||||
|     uint16_t timeout_timer = timer_read(); | ||||
|     while (!(TWCR & (1 << TWINT))) { | ||||
|         if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { | ||||
|             return I2C_STATUS_TIMEOUT; | ||||
|         } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   if ((TW_STATUS & 0xF8) != TW_MT_DATA_ACK) { | ||||
|     return I2C_STATUS_ERROR; | ||||
|   } | ||||
|     if ((TW_STATUS & 0xF8) != TW_MT_DATA_ACK) { | ||||
|         return I2C_STATUS_ERROR; | ||||
|     } | ||||
| 
 | ||||
|   return I2C_STATUS_SUCCESS; | ||||
|     return I2C_STATUS_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| int16_t i2c_read_ack(uint16_t timeout) { | ||||
|   // start TWI module and acknowledge data after reception
 | ||||
|   TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA); | ||||
|     // start TWI module and acknowledge data after reception
 | ||||
|     TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA); | ||||
| 
 | ||||
|   uint16_t timeout_timer = timer_read(); | ||||
|   while (!(TWCR & (1 << TWINT))) { | ||||
|     if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { | ||||
|       return I2C_STATUS_TIMEOUT; | ||||
|     uint16_t timeout_timer = timer_read(); | ||||
|     while (!(TWCR & (1 << TWINT))) { | ||||
|         if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { | ||||
|             return I2C_STATUS_TIMEOUT; | ||||
|         } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   // return received data from TWDR
 | ||||
|   return TWDR; | ||||
|     // return received data from TWDR
 | ||||
|     return TWDR; | ||||
| } | ||||
| 
 | ||||
| int16_t i2c_read_nack(uint16_t timeout) { | ||||
|   // start receiving without acknowledging reception
 | ||||
|   TWCR = (1 << TWINT) | (1 << TWEN); | ||||
|     // start receiving without acknowledging reception
 | ||||
|     TWCR = (1 << TWINT) | (1 << TWEN); | ||||
| 
 | ||||
|   uint16_t timeout_timer = timer_read(); | ||||
|   while (!(TWCR & (1 << TWINT))) { | ||||
|     if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { | ||||
|       return I2C_STATUS_TIMEOUT; | ||||
|     uint16_t timeout_timer = timer_read(); | ||||
|     while (!(TWCR & (1 << TWINT))) { | ||||
|         if ((timeout != I2C_TIMEOUT_INFINITE) && ((timer_read() - timeout_timer) >= timeout)) { | ||||
|             return I2C_STATUS_TIMEOUT; | ||||
|         } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   // return received data from TWDR
 | ||||
|   return TWDR; | ||||
|     // return received data from TWDR
 | ||||
|     return TWDR; | ||||
| } | ||||
| 
 | ||||
| i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout) { | ||||
|   i2c_status_t status = i2c_start(address | I2C_WRITE, timeout); | ||||
|     i2c_status_t status = i2c_start(address | I2C_WRITE, timeout); | ||||
| 
 | ||||
|   for (uint16_t i = 0; i < length && status >= 0; i++) { | ||||
|     status = i2c_write(data[i], timeout); | ||||
|   } | ||||
|     for (uint16_t i = 0; i < length && status >= 0; i++) { | ||||
|         status = i2c_write(data[i], timeout); | ||||
|     } | ||||
| 
 | ||||
|   i2c_stop(); | ||||
|     i2c_stop(); | ||||
| 
 | ||||
|   return status; | ||||
|     return status; | ||||
| } | ||||
| 
 | ||||
| i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) { | ||||
|   i2c_status_t status = i2c_start(address | I2C_READ, timeout); | ||||
|     i2c_status_t status = i2c_start(address | I2C_READ, timeout); | ||||
| 
 | ||||
|   for (uint16_t i = 0; i < (length - 1) && status >= 0; i++) { | ||||
|     status = i2c_read_ack(timeout); | ||||
|     if (status >= 0) { | ||||
|       data[i] = status; | ||||
|     for (uint16_t i = 0; i < (length - 1) && status >= 0; i++) { | ||||
|         status = i2c_read_ack(timeout); | ||||
|         if (status >= 0) { | ||||
|             data[i] = status; | ||||
|         } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   if (status >= 0) { | ||||
|     status = i2c_read_nack(timeout); | ||||
|     if (status >= 0) { | ||||
|       data[(length - 1)] = status; | ||||
|         status = i2c_read_nack(timeout); | ||||
|         if (status >= 0) { | ||||
|             data[(length - 1)] = status; | ||||
|         } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   i2c_stop(); | ||||
|     i2c_stop(); | ||||
| 
 | ||||
|   return (status < 0) ? status : I2C_STATUS_SUCCESS; | ||||
|     return (status < 0) ? status : I2C_STATUS_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) { | ||||
|   i2c_status_t status = i2c_start(devaddr | 0x00, timeout); | ||||
|   if (status >= 0) { | ||||
|     status = i2c_write(regaddr, timeout); | ||||
|     i2c_status_t status = i2c_start(devaddr | 0x00, timeout); | ||||
|     if (status >= 0) { | ||||
|         status = i2c_write(regaddr, timeout); | ||||
| 
 | ||||
|     for (uint16_t i = 0; i < length && status >= 0; i++) { | ||||
|       status = i2c_write(data[i], timeout); | ||||
|         for (uint16_t i = 0; i < length && status >= 0; i++) { | ||||
|             status = i2c_write(data[i], timeout); | ||||
|         } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   i2c_stop(); | ||||
|     i2c_stop(); | ||||
| 
 | ||||
|   return status; | ||||
|     return status; | ||||
| } | ||||
| 
 | ||||
| i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) { | ||||
|   i2c_status_t status = i2c_start(devaddr, timeout); | ||||
|   if (status < 0) { | ||||
|     goto error; | ||||
|   } | ||||
| 
 | ||||
|   status = i2c_write(regaddr, timeout); | ||||
|   if (status < 0) { | ||||
|     goto error; | ||||
|   } | ||||
| 
 | ||||
|   status = i2c_start(devaddr | 0x01, timeout); | ||||
| 
 | ||||
|   for (uint16_t i = 0; i < (length - 1) && status >= 0; i++) { | ||||
|     status = i2c_read_ack(timeout); | ||||
|     if (status >= 0) { | ||||
|       data[i] = status; | ||||
|     i2c_status_t status = i2c_start(devaddr, timeout); | ||||
|     if (status < 0) { | ||||
|         goto error; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   if (status >= 0) { | ||||
|     status = i2c_read_nack(timeout); | ||||
|     if (status >= 0) { | ||||
|       data[(length - 1)] = status; | ||||
|     status = i2c_write(regaddr, timeout); | ||||
|     if (status < 0) { | ||||
|         goto error; | ||||
|     } | ||||
| 
 | ||||
|     status = i2c_start(devaddr | 0x01, timeout); | ||||
| 
 | ||||
|     for (uint16_t i = 0; i < (length - 1) && status >= 0; i++) { | ||||
|         status = i2c_read_ack(timeout); | ||||
|         if (status >= 0) { | ||||
|             data[i] = status; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (status >= 0) { | ||||
|         status = i2c_read_nack(timeout); | ||||
|         if (status >= 0) { | ||||
|             data[(length - 1)] = status; | ||||
|         } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| error: | ||||
|   i2c_stop(); | ||||
|     i2c_stop(); | ||||
| 
 | ||||
|   return (status < 0) ? status : I2C_STATUS_SUCCESS; | ||||
|     return (status < 0) ? status : I2C_STATUS_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| void i2c_stop(void) { | ||||
|   // transmit STOP condition
 | ||||
|   TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); | ||||
|     // transmit STOP condition
 | ||||
|     TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); | ||||
| } | ||||
|  |  | |||
							
								
								
									
										12
									
								
								drivers/avr/i2c_master.h
									
										
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										12
									
								
								drivers/avr/i2c_master.h
									
										
									
									
									
										
										
										Executable file → Normal file
									
								
							|  | @ -26,21 +26,21 @@ | |||
| typedef int16_t i2c_status_t; | ||||
| 
 | ||||
| #define I2C_STATUS_SUCCESS (0) | ||||
| #define I2C_STATUS_ERROR   (-1) | ||||
| #define I2C_STATUS_ERROR (-1) | ||||
| #define I2C_STATUS_TIMEOUT (-2) | ||||
| 
 | ||||
| #define I2C_TIMEOUT_IMMEDIATE (0) | ||||
| #define I2C_TIMEOUT_INFINITE (0xFFFF) | ||||
| 
 | ||||
| void i2c_init(void); | ||||
| void         i2c_init(void); | ||||
| i2c_status_t i2c_start(uint8_t address, uint16_t timeout); | ||||
| i2c_status_t i2c_write(uint8_t data, uint16_t timeout); | ||||
| int16_t i2c_read_ack(uint16_t timeout); | ||||
| int16_t i2c_read_nack(uint16_t timeout); | ||||
| int16_t      i2c_read_ack(uint16_t timeout); | ||||
| int16_t      i2c_read_nack(uint16_t timeout); | ||||
| i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout); | ||||
| i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout); | ||||
| i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); | ||||
| i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); | ||||
| void i2c_stop(void); | ||||
| void         i2c_stop(void); | ||||
| 
 | ||||
| #endif // I2C_MASTER_H
 | ||||
| #endif  // I2C_MASTER_H
 | ||||
|  |  | |||
							
								
								
									
										18
									
								
								drivers/avr/i2c_slave.c
									
										
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										18
									
								
								drivers/avr/i2c_slave.c
									
										
									
									
									
										
										
										Executable file → Normal file
									
								
							|  | @ -27,24 +27,24 @@ | |||
| volatile uint8_t i2c_slave_reg[I2C_SLAVE_REG_COUNT]; | ||||
| 
 | ||||
| static volatile uint8_t buffer_address; | ||||
| static volatile bool slave_has_register_set = false; | ||||
| static volatile bool    slave_has_register_set = false; | ||||
| 
 | ||||
| void i2c_slave_init(uint8_t address){ | ||||
| void i2c_slave_init(uint8_t address) { | ||||
|     // load address into TWI address register
 | ||||
|     TWAR = address; | ||||
|     // set the TWCR to enable address matching and enable TWI, clear TWINT, enable TWI interrupt
 | ||||
|     TWCR = (1 << TWIE) | (1 << TWEA) | (1 << TWINT) | (1 << TWEN); | ||||
| } | ||||
| 
 | ||||
| void i2c_slave_stop(void){ | ||||
| void i2c_slave_stop(void) { | ||||
|     // clear acknowledge and enable bits
 | ||||
|     TWCR &= ~((1 << TWEA) | (1 << TWEN)); | ||||
| } | ||||
| 
 | ||||
| ISR(TWI_vect){ | ||||
| ISR(TWI_vect) { | ||||
|     uint8_t ack = 1; | ||||
| 
 | ||||
|     switch(TW_STATUS){ | ||||
|     switch (TW_STATUS) { | ||||
|         case TW_SR_SLA_ACK: | ||||
|             // The device is now a slave receiver
 | ||||
|             slave_has_register_set = false; | ||||
|  | @ -53,14 +53,14 @@ ISR(TWI_vect){ | |||
|         case TW_SR_DATA_ACK: | ||||
|             // This device is a slave receiver and has received data
 | ||||
|             // First byte is the location then the bytes will be writen in buffer with auto-incriment
 | ||||
|             if(!slave_has_register_set){ | ||||
|             if (!slave_has_register_set) { | ||||
|                 buffer_address = TWDR; | ||||
| 
 | ||||
|                 if (buffer_address >= I2C_SLAVE_REG_COUNT) {  // address out of bounds dont ack
 | ||||
|                   ack            = 0; | ||||
|                   buffer_address = 0; | ||||
|                     ack            = 0; | ||||
|                     buffer_address = 0; | ||||
|                 } | ||||
|                 slave_has_register_set = true; // address has been receaved now fill in buffer
 | ||||
|                 slave_has_register_set = true;  // address has been receaved now fill in buffer
 | ||||
|             } else { | ||||
|                 i2c_slave_reg[buffer_address] = TWDR; | ||||
|                 buffer_address++; | ||||
|  |  | |||
							
								
								
									
										2
									
								
								drivers/avr/i2c_slave.h
									
										
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										2
									
								
								drivers/avr/i2c_slave.h
									
										
									
									
									
										
										
										Executable file → Normal file
									
								
							|  | @ -30,4 +30,4 @@ extern volatile uint8_t i2c_slave_reg[I2C_SLAVE_REG_COUNT]; | |||
| void i2c_slave_init(uint8_t address); | ||||
| void i2c_slave_stop(void); | ||||
| 
 | ||||
| #endif // I2C_SLAVE_H
 | ||||
| #endif  // I2C_SLAVE_H
 | ||||
|  |  | |||
|  | @ -90,14 +90,14 @@ | |||
| #undef OCR2_6 | ||||
| #undef OCR2_7 | ||||
| 
 | ||||
| #define NUM_DIGITAL_PINS  30 | ||||
| #define NUM_DIGITAL_PINS 30 | ||||
| #define NUM_ANALOG_INPUTS 12 | ||||
| 
 | ||||
| #define TX_RX_LED_INIT  DDRD |= (1<<5), DDRB |= (1<<0) | ||||
| #define TXLED0          PORTD |= (1<<5) | ||||
| #define TXLED1          PORTD &= ~(1<<5) | ||||
| #define RXLED0          PORTB |= (1<<0) | ||||
| #define RXLED1          PORTB &= ~(1<<0) | ||||
| #define TX_RX_LED_INIT DDRD |= (1 << 5), DDRB |= (1 << 0) | ||||
| #define TXLED0 PORTD |= (1 << 5) | ||||
| #define TXLED1 PORTD &= ~(1 << 5) | ||||
| #define RXLED0 PORTB |= (1 << 0) | ||||
| #define RXLED1 PORTB &= ~(1 << 0) | ||||
| 
 | ||||
| static const uint8_t SDA = 2; | ||||
| static const uint8_t SCL = 3; | ||||
|  | @ -111,27 +111,27 @@ static const uint8_t SCK  = 15; | |||
| 
 | ||||
| // Mapping of analog pins as digital I/O
 | ||||
| // A6-A11 share with digital pins
 | ||||
| static const uint8_t ADC0 = 18; | ||||
| static const uint8_t ADC1 = 19; | ||||
| static const uint8_t ADC2 = 20; | ||||
| static const uint8_t ADC3 = 21; | ||||
| static const uint8_t ADC4 = 22; | ||||
| static const uint8_t ADC5 = 23; | ||||
| static const uint8_t ADC6 = 24;   // D4
 | ||||
| static const uint8_t ADC7 = 25;   // D6
 | ||||
| static const uint8_t ADC8 = 26;   // D8
 | ||||
| static const uint8_t ADC9 = 27;   // D9
 | ||||
| static const uint8_t ADC0  = 18; | ||||
| static const uint8_t ADC1  = 19; | ||||
| static const uint8_t ADC2  = 20; | ||||
| static const uint8_t ADC3  = 21; | ||||
| static const uint8_t ADC4  = 22; | ||||
| static const uint8_t ADC5  = 23; | ||||
| static const uint8_t ADC6  = 24;  // D4
 | ||||
| static const uint8_t ADC7  = 25;  // D6
 | ||||
| static const uint8_t ADC8  = 26;  // D8
 | ||||
| static const uint8_t ADC9  = 27;  // D9
 | ||||
| static const uint8_t ADC10 = 28;  // D10
 | ||||
| static const uint8_t ADC11 = 29;  // D12
 | ||||
| 
 | ||||
| #define digitalPinToPCICR(p)    ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCICR) : ((uint8_t *)0)) | ||||
| #define digitalPinToPCICR(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCICR) : ((uint8_t *)0)) | ||||
| #define digitalPinToPCICRbit(p) 0 | ||||
| #define digitalPinToPCMSK(p)    ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCMSK0) : ((uint8_t *)0)) | ||||
| #define digitalPinToPCMSKbit(p) ( ((p) >= 8 && (p) <= 11) ? (p) - 4 : ((p) == 14 ? 3 : ((p) == 15 ? 1 : ((p) == 16 ? 2 : ((p) == 17 ? 0 : (p - A8 + 4)))))) | ||||
| #define digitalPinToPCMSK(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCMSK0) : ((uint8_t *)0)) | ||||
| #define digitalPinToPCMSKbit(p) (((p) >= 8 && (p) <= 11) ? (p)-4 : ((p) == 14 ? 3 : ((p) == 15 ? 1 : ((p) == 16 ? 2 : ((p) == 17 ? 0 : (p - A8 + 4)))))) | ||||
| 
 | ||||
| //  __AVR_ATmega32U4__ has an unusual mapping of pins to channels
 | ||||
| extern const uint8_t PROGMEM analog_pin_to_channel_PGM[]; | ||||
| #define analogPinToChannel(P)  ( pgm_read_byte( analog_pin_to_channel_PGM + (P) ) ) | ||||
| #define analogPinToChannel(P) (pgm_read_byte(analog_pin_to_channel_PGM + (P))) | ||||
| 
 | ||||
| #define digitalPinToInterrupt(p) ((p) == 0 ? 2 : ((p) == 1 ? 3 : ((p) == 2 ? 1 : ((p) == 3 ? 0 : ((p) == 7 ? 4 : NOT_AN_INTERRUPT))))) | ||||
| 
 | ||||
|  | @ -182,159 +182,121 @@ extern const uint8_t PROGMEM analog_pin_to_channel_PGM[]; | |||
| // appropriate addresses for various functions (e.g. reading
 | ||||
| // and writing)
 | ||||
| const uint16_t PROGMEM port_to_mode_PGM[] = { | ||||
|     NOT_A_PORT, | ||||
|     NOT_A_PORT, | ||||
|     (uint16_t) &DDRB, | ||||
|     (uint16_t) &DDRC, | ||||
|     (uint16_t) &DDRD, | ||||
|     (uint16_t) &DDRE, | ||||
|     (uint16_t) &DDRF, | ||||
|     NOT_A_PORT, NOT_A_PORT, (uint16_t)&DDRB, (uint16_t)&DDRC, (uint16_t)&DDRD, (uint16_t)&DDRE, (uint16_t)&DDRF, | ||||
| }; | ||||
| 
 | ||||
| const uint16_t PROGMEM port_to_output_PGM[] = { | ||||
|     NOT_A_PORT, | ||||
|     NOT_A_PORT, | ||||
|     (uint16_t) &PORTB, | ||||
|     (uint16_t) &PORTC, | ||||
|     (uint16_t) &PORTD, | ||||
|     (uint16_t) &PORTE, | ||||
|     (uint16_t) &PORTF, | ||||
|     NOT_A_PORT, NOT_A_PORT, (uint16_t)&PORTB, (uint16_t)&PORTC, (uint16_t)&PORTD, (uint16_t)&PORTE, (uint16_t)&PORTF, | ||||
| }; | ||||
| 
 | ||||
| const uint16_t PROGMEM port_to_input_PGM[] = { | ||||
|     NOT_A_PORT, | ||||
|     NOT_A_PORT, | ||||
|     (uint16_t) &PINB, | ||||
|     (uint16_t) &PINC, | ||||
|     (uint16_t) &PIND, | ||||
|     (uint16_t) &PINE, | ||||
|     (uint16_t) &PINF, | ||||
|     NOT_A_PORT, NOT_A_PORT, (uint16_t)&PINB, (uint16_t)&PINC, (uint16_t)&PIND, (uint16_t)&PINE, (uint16_t)&PINF, | ||||
| }; | ||||
| 
 | ||||
| const uint8_t PROGMEM digital_pin_to_port_PGM[] = { | ||||
|     PD, // D0 - PD2
 | ||||
|     PD, // D1 - PD3
 | ||||
|     PD, // D2 - PD1
 | ||||
|     PD, // D3 - PD0
 | ||||
|     PD, // D4 - PD4
 | ||||
|     PC, // D5 - PC6
 | ||||
|     PD, // D6 - PD7
 | ||||
|     PE, // D7 - PE6
 | ||||
|     PD,  // D0 - PD2
 | ||||
|     PD,  // D1 - PD3
 | ||||
|     PD,  // D2 - PD1
 | ||||
|     PD,  // D3 - PD0
 | ||||
|     PD,  // D4 - PD4
 | ||||
|     PC,  // D5 - PC6
 | ||||
|     PD,  // D6 - PD7
 | ||||
|     PE,  // D7 - PE6
 | ||||
| 
 | ||||
|     PB, // D8 - PB4
 | ||||
|     PB, // D9 - PB5
 | ||||
|     PB, // D10 - PB6
 | ||||
|     PB, // D11 - PB7
 | ||||
|     PD, // D12 - PD6
 | ||||
|     PC, // D13 - PC7
 | ||||
|     PB,  // D8 - PB4
 | ||||
|     PB,  // D9 - PB5
 | ||||
|     PB,  // D10 - PB6
 | ||||
|     PB,  // D11 - PB7
 | ||||
|     PD,  // D12 - PD6
 | ||||
|     PC,  // D13 - PC7
 | ||||
| 
 | ||||
|     PB, // D14 - MISO - PB3
 | ||||
|     PB, // D15 - SCK - PB1
 | ||||
|     PB, // D16 - MOSI - PB2
 | ||||
|     PB, // D17 - SS - PB0
 | ||||
|     PB,  // D14 - MISO - PB3
 | ||||
|     PB,  // D15 - SCK - PB1
 | ||||
|     PB,  // D16 - MOSI - PB2
 | ||||
|     PB,  // D17 - SS - PB0
 | ||||
| 
 | ||||
|     PF, // D18 - A0 - PF7
 | ||||
|     PF, // D19 - A1 - PF6
 | ||||
|     PF, // D20 - A2 - PF5
 | ||||
|     PF, // D21 - A3 - PF4
 | ||||
|     PF, // D22 - A4 - PF1
 | ||||
|     PF, // D23 - A5 - PF0
 | ||||
|     PF,  // D18 - A0 - PF7
 | ||||
|     PF,  // D19 - A1 - PF6
 | ||||
|     PF,  // D20 - A2 - PF5
 | ||||
|     PF,  // D21 - A3 - PF4
 | ||||
|     PF,  // D22 - A4 - PF1
 | ||||
|     PF,  // D23 - A5 - PF0
 | ||||
| 
 | ||||
|     PD, // D24 - PD5
 | ||||
|     PD, // D25 / D6 - A7 - PD7
 | ||||
|     PB, // D26 / D8 - A8 - PB4
 | ||||
|     PB, // D27 / D9 - A9 - PB5
 | ||||
|     PB, // D28 / D10 - A10 - PB6
 | ||||
|     PD, // D29 / D12 - A11 - PD6
 | ||||
|     PD,  // D24 - PD5
 | ||||
|     PD,  // D25 / D6 - A7 - PD7
 | ||||
|     PB,  // D26 / D8 - A8 - PB4
 | ||||
|     PB,  // D27 / D9 - A9 - PB5
 | ||||
|     PB,  // D28 / D10 - A10 - PB6
 | ||||
|     PD,  // D29 / D12 - A11 - PD6
 | ||||
| }; | ||||
| 
 | ||||
| const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = { | ||||
|     _BV(2), // D0 - PD2
 | ||||
|     _BV(3), // D1 - PD3
 | ||||
|     _BV(1), // D2 - PD1
 | ||||
|     _BV(0), // D3 - PD0
 | ||||
|     _BV(4), // D4 - PD4
 | ||||
|     _BV(6), // D5 - PC6
 | ||||
|     _BV(7), // D6 - PD7
 | ||||
|     _BV(6), // D7 - PE6
 | ||||
|     _BV(2),  // D0 - PD2
 | ||||
|     _BV(3),  // D1 - PD3
 | ||||
|     _BV(1),  // D2 - PD1
 | ||||
|     _BV(0),  // D3 - PD0
 | ||||
|     _BV(4),  // D4 - PD4
 | ||||
|     _BV(6),  // D5 - PC6
 | ||||
|     _BV(7),  // D6 - PD7
 | ||||
|     _BV(6),  // D7 - PE6
 | ||||
| 
 | ||||
|     _BV(4), // D8 - PB4
 | ||||
|     _BV(5), // D9 - PB5
 | ||||
|     _BV(6), // D10 - PB6
 | ||||
|     _BV(7), // D11 - PB7
 | ||||
|     _BV(6), // D12 - PD6
 | ||||
|     _BV(7), // D13 - PC7
 | ||||
|     _BV(4),  // D8 - PB4
 | ||||
|     _BV(5),  // D9 - PB5
 | ||||
|     _BV(6),  // D10 - PB6
 | ||||
|     _BV(7),  // D11 - PB7
 | ||||
|     _BV(6),  // D12 - PD6
 | ||||
|     _BV(7),  // D13 - PC7
 | ||||
| 
 | ||||
|     _BV(3), // D14 - MISO - PB3
 | ||||
|     _BV(1), // D15 - SCK - PB1
 | ||||
|     _BV(2), // D16 - MOSI - PB2
 | ||||
|     _BV(0), // D17 - SS - PB0
 | ||||
|     _BV(3),  // D14 - MISO - PB3
 | ||||
|     _BV(1),  // D15 - SCK - PB1
 | ||||
|     _BV(2),  // D16 - MOSI - PB2
 | ||||
|     _BV(0),  // D17 - SS - PB0
 | ||||
| 
 | ||||
|     _BV(7), // D18 - A0 - PF7
 | ||||
|     _BV(6), // D19 - A1 - PF6
 | ||||
|     _BV(5), // D20 - A2 - PF5
 | ||||
|     _BV(4), // D21 - A3 - PF4
 | ||||
|     _BV(1), // D22 - A4 - PF1
 | ||||
|     _BV(0), // D23 - A5 - PF0
 | ||||
|     _BV(7),  // D18 - A0 - PF7
 | ||||
|     _BV(6),  // D19 - A1 - PF6
 | ||||
|     _BV(5),  // D20 - A2 - PF5
 | ||||
|     _BV(4),  // D21 - A3 - PF4
 | ||||
|     _BV(1),  // D22 - A4 - PF1
 | ||||
|     _BV(0),  // D23 - A5 - PF0
 | ||||
| 
 | ||||
|     _BV(5), // D24 - PD5
 | ||||
|     _BV(7), // D25 / D6 - A7 - PD7
 | ||||
|     _BV(4), // D26 / D8 - A8 - PB4
 | ||||
|     _BV(5), // D27 / D9 - A9 - PB5
 | ||||
|     _BV(6), // D28 / D10 - A10 - PB6
 | ||||
|     _BV(6), // D29 / D12 - A11 - PD6
 | ||||
|     _BV(5),  // D24 - PD5
 | ||||
|     _BV(7),  // D25 / D6 - A7 - PD7
 | ||||
|     _BV(4),  // D26 / D8 - A8 - PB4
 | ||||
|     _BV(5),  // D27 / D9 - A9 - PB5
 | ||||
|     _BV(6),  // D28 / D10 - A10 - PB6
 | ||||
|     _BV(6),  // D29 / D12 - A11 - PD6
 | ||||
| }; | ||||
| 
 | ||||
| const uint8_t PROGMEM digital_pin_to_timer_PGM[] = { | ||||
|     NOT_ON_TIMER, | ||||
|     NOT_ON_TIMER, | ||||
|     NOT_ON_TIMER, | ||||
|     TIMER0B,        /* 3 */ | ||||
|     NOT_ON_TIMER, | ||||
|     TIMER3A,        /* 5 */ | ||||
|     TIMER4D,        /* 6 */ | ||||
|     NOT_ON_TIMER, NOT_ON_TIMER, NOT_ON_TIMER, TIMER0B, /* 3 */ | ||||
|     NOT_ON_TIMER, TIMER3A,                             /* 5 */ | ||||
|     TIMER4D,                                           /* 6 */ | ||||
|     NOT_ON_TIMER, | ||||
| 
 | ||||
|     NOT_ON_TIMER, | ||||
|     TIMER1A,        /* 9 */ | ||||
|     TIMER1B,        /* 10 */ | ||||
|     TIMER0A,        /* 11 */ | ||||
|     NOT_ON_TIMER, TIMER1A, /* 9 */ | ||||
|     TIMER1B,               /* 10 */ | ||||
|     TIMER0A,               /* 11 */ | ||||
| 
 | ||||
|     NOT_ON_TIMER, | ||||
|     TIMER4A,        /* 13 */ | ||||
|     NOT_ON_TIMER, TIMER4A, /* 13 */ | ||||
| 
 | ||||
|     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, 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, | ||||
|     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, NOT_ON_TIMER, NOT_ON_TIMER, | ||||
| }; | ||||
| 
 | ||||
| const uint8_t PROGMEM analog_pin_to_channel_PGM[] = { | ||||
|     7,  // A0               PF7                 ADC7
 | ||||
|     6,  // A1               PF6                 ADC6
 | ||||
|     5,  // A2               PF5                 ADC5
 | ||||
|     4,  // A3               PF4                 ADC4
 | ||||
|     1,  // A4               PF1                 ADC1
 | ||||
|     0,  // A5               PF0                 ADC0
 | ||||
|     8,  // A6       D4      PD4                 ADC8
 | ||||
|     10, // A7       D6      PD7                 ADC10
 | ||||
|     11, // A8       D8      PB4                 ADC11
 | ||||
|     12, // A9       D9      PB5                 ADC12
 | ||||
|     13, // A10      D10     PB6                 ADC13
 | ||||
|     9   // A11      D12     PD6                 ADC9
 | ||||
|     7,   // A0               PF7                 ADC7
 | ||||
|     6,   // A1               PF6                 ADC6
 | ||||
|     5,   // A2               PF5                 ADC5
 | ||||
|     4,   // A3               PF4                 ADC4
 | ||||
|     1,   // A4               PF1                 ADC1
 | ||||
|     0,   // A5               PF0                 ADC0
 | ||||
|     8,   // A6       D4      PD4                 ADC8
 | ||||
|     10,  // A7       D6      PD7                 ADC10
 | ||||
|     11,  // A8       D8      PB4                 ADC11
 | ||||
|     12,  // A9       D9      PB5                 ADC12
 | ||||
|     13,  // A10      D10     PB6                 ADC13
 | ||||
|     9    // A11      D12     PD6                 ADC9
 | ||||
| }; | ||||
| 
 | ||||
| #endif /* ARDUINO_MAIN */ | ||||
|  | @ -354,9 +316,9 @@ const uint8_t PROGMEM analog_pin_to_channel_PGM[] = { | |||
| //
 | ||||
| // SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
 | ||||
| //                            pins are NOT connected to anything by default.
 | ||||
| #define SERIAL_PORT_MONITOR        Serial | ||||
| #define SERIAL_PORT_USBVIRTUAL     Serial | ||||
| #define SERIAL_PORT_HARDWARE       Serial1 | ||||
| #define SERIAL_PORT_HARDWARE_OPEN  Serial1 | ||||
| #define SERIAL_PORT_MONITOR Serial | ||||
| #define SERIAL_PORT_USBVIRTUAL Serial | ||||
| #define SERIAL_PORT_HARDWARE Serial1 | ||||
| #define SERIAL_PORT_HARDWARE_OPEN Serial1 | ||||
| 
 | ||||
| #endif /* Pins_Arduino_h */ | ||||
|  |  | |||
|  | @ -1,325 +1,320 @@ | |||
| #ifdef SSD1306OLED | ||||
| 
 | ||||
| #include "ssd1306.h" | ||||
| #include "i2c.h" | ||||
| #include <string.h> | ||||
| #include "print.h" | ||||
| #include "glcdfont.c" | ||||
| #ifdef ADAFRUIT_BLE_ENABLE | ||||
| #include "adafruit_ble.h" | ||||
| #endif | ||||
| #ifdef PROTOCOL_LUFA | ||||
| #include "lufa.h" | ||||
| #endif | ||||
| #include "sendchar.h" | ||||
| #include "timer.h" | ||||
| #    include "ssd1306.h" | ||||
| #    include "i2c.h" | ||||
| #    include <string.h> | ||||
| #    include "print.h" | ||||
| #    include "glcdfont.c" | ||||
| #    ifdef ADAFRUIT_BLE_ENABLE | ||||
| #        include "adafruit_ble.h" | ||||
| #    endif | ||||
| #    ifdef PROTOCOL_LUFA | ||||
| #        include "lufa.h" | ||||
| #    endif | ||||
| #    include "sendchar.h" | ||||
| #    include "timer.h" | ||||
| 
 | ||||
| // Set this to 1 to help diagnose early startup problems
 | ||||
| // when testing power-on with ble.  Turn it off otherwise,
 | ||||
| // as the latency of printing most of the debug info messes
 | ||||
| // with the matrix scan, causing keys to drop.
 | ||||
| #define DEBUG_TO_SCREEN 0 | ||||
| #    define DEBUG_TO_SCREEN 0 | ||||
| 
 | ||||
| //static uint16_t last_battery_update;
 | ||||
| //static uint32_t vbat;
 | ||||
| // static uint16_t last_battery_update;
 | ||||
| // static uint32_t vbat;
 | ||||
| //#define BatteryUpdateInterval 10000 /* milliseconds */
 | ||||
| #define ScreenOffInterval 300000 /* milliseconds */ | ||||
| #if DEBUG_TO_SCREEN | ||||
| #    define ScreenOffInterval 300000 /* milliseconds */ | ||||
| #    if DEBUG_TO_SCREEN | ||||
| static uint8_t displaying; | ||||
| #endif | ||||
| #    endif | ||||
| static uint16_t last_flush; | ||||
| 
 | ||||
| // Write command sequence.
 | ||||
| // Returns true on success.
 | ||||
| static inline bool _send_cmd1(uint8_t cmd) { | ||||
|   bool res = false; | ||||
|     bool res = false; | ||||
| 
 | ||||
|   if (i2c_start_write(SSD1306_ADDRESS)) { | ||||
|     xprintf("failed to start write to %d\n", SSD1306_ADDRESS); | ||||
|     goto done; | ||||
|   } | ||||
|     if (i2c_start_write(SSD1306_ADDRESS)) { | ||||
|         xprintf("failed to start write to %d\n", SSD1306_ADDRESS); | ||||
|         goto done; | ||||
|     } | ||||
| 
 | ||||
|   if (i2c_master_write(0x0 /* command byte follows */)) { | ||||
|     print("failed to write control byte\n"); | ||||
|     if (i2c_master_write(0x0 /* command byte follows */)) { | ||||
|         print("failed to write control byte\n"); | ||||
| 
 | ||||
|     goto done; | ||||
|   } | ||||
|         goto done; | ||||
|     } | ||||
| 
 | ||||
|   if (i2c_master_write(cmd)) { | ||||
|     xprintf("failed to write command %d\n", cmd); | ||||
|     goto done; | ||||
|   } | ||||
|   res = true; | ||||
|     if (i2c_master_write(cmd)) { | ||||
|         xprintf("failed to write command %d\n", cmd); | ||||
|         goto done; | ||||
|     } | ||||
|     res = true; | ||||
| done: | ||||
|   i2c_master_stop(); | ||||
|   return res; | ||||
|     i2c_master_stop(); | ||||
|     return res; | ||||
| } | ||||
| 
 | ||||
| // Write 2-byte command sequence.
 | ||||
| // Returns true on success
 | ||||
| static inline bool _send_cmd2(uint8_t cmd, uint8_t opr) { | ||||
|   if (!_send_cmd1(cmd)) { | ||||
|     return false; | ||||
|   } | ||||
|   return _send_cmd1(opr); | ||||
|     if (!_send_cmd1(cmd)) { | ||||
|         return false; | ||||
|     } | ||||
|     return _send_cmd1(opr); | ||||
| } | ||||
| 
 | ||||
| // Write 3-byte command sequence.
 | ||||
| // Returns true on success
 | ||||
| static inline bool _send_cmd3(uint8_t cmd, uint8_t opr1, uint8_t opr2) { | ||||
|   if (!_send_cmd1(cmd)) { | ||||
|     return false; | ||||
|   } | ||||
|   if (!_send_cmd1(opr1)) { | ||||
|     return false; | ||||
|   } | ||||
|   return _send_cmd1(opr2); | ||||
|     if (!_send_cmd1(cmd)) { | ||||
|         return false; | ||||
|     } | ||||
|     if (!_send_cmd1(opr1)) { | ||||
|         return false; | ||||
|     } | ||||
|     return _send_cmd1(opr2); | ||||
| } | ||||
| 
 | ||||
| #define send_cmd1(c) if (!_send_cmd1(c)) {goto done;} | ||||
| #define send_cmd2(c,o) if (!_send_cmd2(c,o)) {goto done;} | ||||
| #define send_cmd3(c,o1,o2) if (!_send_cmd3(c,o1,o2)) {goto done;} | ||||
| #    define send_cmd1(c)      \ | ||||
|         if (!_send_cmd1(c)) { \ | ||||
|             goto done;        \ | ||||
|         } | ||||
| #    define send_cmd2(c, o)      \ | ||||
|         if (!_send_cmd2(c, o)) { \ | ||||
|             goto done;           \ | ||||
|         } | ||||
| #    define send_cmd3(c, o1, o2)      \ | ||||
|         if (!_send_cmd3(c, o1, o2)) { \ | ||||
|             goto done;                \ | ||||
|         } | ||||
| 
 | ||||
| static void clear_display(void) { | ||||
|   matrix_clear(&display); | ||||
|     matrix_clear(&display); | ||||
| 
 | ||||
|   // Clear all of the display bits (there can be random noise
 | ||||
|   // in the RAM on startup)
 | ||||
|   send_cmd3(PageAddr, 0, (DisplayHeight / 8) - 1); | ||||
|   send_cmd3(ColumnAddr, 0, DisplayWidth - 1); | ||||
|     // Clear all of the display bits (there can be random noise
 | ||||
|     // in the RAM on startup)
 | ||||
|     send_cmd3(PageAddr, 0, (DisplayHeight / 8) - 1); | ||||
|     send_cmd3(ColumnAddr, 0, DisplayWidth - 1); | ||||
| 
 | ||||
|   if (i2c_start_write(SSD1306_ADDRESS)) { | ||||
|     goto done; | ||||
|   } | ||||
|   if (i2c_master_write(0x40)) { | ||||
|     // Data mode
 | ||||
|     goto done; | ||||
|   } | ||||
|   for (uint8_t row = 0; row < MatrixRows; ++row) { | ||||
|     for (uint8_t col = 0; col < DisplayWidth; ++col) { | ||||
|       i2c_master_write(0); | ||||
|     if (i2c_start_write(SSD1306_ADDRESS)) { | ||||
|         goto done; | ||||
|     } | ||||
|     if (i2c_master_write(0x40)) { | ||||
|         // Data mode
 | ||||
|         goto done; | ||||
|     } | ||||
|     for (uint8_t row = 0; row < MatrixRows; ++row) { | ||||
|         for (uint8_t col = 0; col < DisplayWidth; ++col) { | ||||
|             i2c_master_write(0); | ||||
|         } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   display.dirty = false; | ||||
|     display.dirty = false; | ||||
| 
 | ||||
| done: | ||||
|   i2c_master_stop(); | ||||
|     i2c_master_stop(); | ||||
| } | ||||
| 
 | ||||
| #if DEBUG_TO_SCREEN | ||||
| #undef sendchar | ||||
| #    if DEBUG_TO_SCREEN | ||||
| #        undef sendchar | ||||
| static int8_t capture_sendchar(uint8_t c) { | ||||
|   sendchar(c); | ||||
|   iota_gfx_write_char(c); | ||||
|     sendchar(c); | ||||
|     iota_gfx_write_char(c); | ||||
| 
 | ||||
|   if (!displaying) { | ||||
|     iota_gfx_flush(); | ||||
|   } | ||||
|   return 0; | ||||
|     if (!displaying) { | ||||
|         iota_gfx_flush(); | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| bool iota_gfx_init(void) { | ||||
|   bool success = false; | ||||
|     bool success = false; | ||||
| 
 | ||||
|   send_cmd1(DisplayOff); | ||||
|   send_cmd2(SetDisplayClockDiv, 0x80); | ||||
|   send_cmd2(SetMultiPlex, DisplayHeight - 1); | ||||
|     send_cmd1(DisplayOff); | ||||
|     send_cmd2(SetDisplayClockDiv, 0x80); | ||||
|     send_cmd2(SetMultiPlex, DisplayHeight - 1); | ||||
| 
 | ||||
|   send_cmd2(SetDisplayOffset, 0); | ||||
|     send_cmd2(SetDisplayOffset, 0); | ||||
| 
 | ||||
|     send_cmd1(SetStartLine | 0x0); | ||||
|     send_cmd2(SetChargePump, 0x14 /* Enable */); | ||||
|     send_cmd2(SetMemoryMode, 0 /* horizontal addressing */); | ||||
| 
 | ||||
|   send_cmd1(SetStartLine | 0x0); | ||||
|   send_cmd2(SetChargePump, 0x14 /* Enable */); | ||||
|   send_cmd2(SetMemoryMode, 0 /* horizontal addressing */); | ||||
| #    ifdef OLED_ROTATE180 | ||||
|     // the following Flip the display orientation 180 degrees
 | ||||
|     send_cmd1(SegRemap); | ||||
|     send_cmd1(ComScanInc); | ||||
| #    endif | ||||
| #    ifndef OLED_ROTATE180 | ||||
|     // Flips the display orientation 0 degrees
 | ||||
|     send_cmd1(SegRemap | 0x1); | ||||
|     send_cmd1(ComScanDec); | ||||
| #    endif | ||||
| 
 | ||||
| #ifdef OLED_ROTATE180 | ||||
| // the following Flip the display orientation 180 degrees
 | ||||
|   send_cmd1(SegRemap); | ||||
|   send_cmd1(ComScanInc); | ||||
| #endif | ||||
| #ifndef OLED_ROTATE180 | ||||
| // Flips the display orientation 0 degrees
 | ||||
|   send_cmd1(SegRemap | 0x1); | ||||
|   send_cmd1(ComScanDec); | ||||
| #endif | ||||
|    | ||||
|   send_cmd2(SetComPins, 0x2); | ||||
|   send_cmd2(SetContrast, 0x8f); | ||||
|   send_cmd2(SetPreCharge, 0xf1); | ||||
|   send_cmd2(SetVComDetect, 0x40); | ||||
|   send_cmd1(DisplayAllOnResume); | ||||
|   send_cmd1(NormalDisplay); | ||||
|   send_cmd1(DeActivateScroll); | ||||
|   send_cmd1(DisplayOn); | ||||
|     send_cmd2(SetComPins, 0x2); | ||||
|     send_cmd2(SetContrast, 0x8f); | ||||
|     send_cmd2(SetPreCharge, 0xf1); | ||||
|     send_cmd2(SetVComDetect, 0x40); | ||||
|     send_cmd1(DisplayAllOnResume); | ||||
|     send_cmd1(NormalDisplay); | ||||
|     send_cmd1(DeActivateScroll); | ||||
|     send_cmd1(DisplayOn); | ||||
| 
 | ||||
|   send_cmd2(SetContrast, 0); // Dim
 | ||||
|     send_cmd2(SetContrast, 0);  // Dim
 | ||||
| 
 | ||||
|   clear_display(); | ||||
|     clear_display(); | ||||
| 
 | ||||
|   success = true; | ||||
|     success = true; | ||||
| 
 | ||||
|   iota_gfx_flush(); | ||||
|     iota_gfx_flush(); | ||||
| 
 | ||||
| #if DEBUG_TO_SCREEN | ||||
|   print_set_sendchar(capture_sendchar); | ||||
| #endif | ||||
| #    if DEBUG_TO_SCREEN | ||||
|     print_set_sendchar(capture_sendchar); | ||||
| #    endif | ||||
| 
 | ||||
| done: | ||||
|   return success; | ||||
|     return success; | ||||
| } | ||||
| 
 | ||||
| bool iota_gfx_off(void) { | ||||
|   bool success = false; | ||||
|     bool success = false; | ||||
| 
 | ||||
|   send_cmd1(DisplayOff); | ||||
|   success = true; | ||||
|     send_cmd1(DisplayOff); | ||||
|     success = true; | ||||
| 
 | ||||
| done: | ||||
|   return success; | ||||
| }  | ||||
|     return success; | ||||
| } | ||||
| 
 | ||||
| bool iota_gfx_on(void) { | ||||
|   bool success = false; | ||||
|     bool success = false; | ||||
| 
 | ||||
|   send_cmd1(DisplayOn); | ||||
|   success = true; | ||||
|     send_cmd1(DisplayOn); | ||||
|     success = true; | ||||
| 
 | ||||
| done: | ||||
|   return success; | ||||
|     return success; | ||||
| } | ||||
| 
 | ||||
| void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c) { | ||||
|   *matrix->cursor = c; | ||||
|   ++matrix->cursor; | ||||
|     *matrix->cursor = c; | ||||
|     ++matrix->cursor; | ||||
| 
 | ||||
|   if (matrix->cursor - &matrix->display[0][0] == sizeof(matrix->display)) { | ||||
|     // We went off the end; scroll the display upwards by one line
 | ||||
|     memmove(&matrix->display[0], &matrix->display[1], | ||||
|             MatrixCols * (MatrixRows - 1)); | ||||
|     matrix->cursor = &matrix->display[MatrixRows - 1][0]; | ||||
|     memset(matrix->cursor, ' ', MatrixCols); | ||||
|   } | ||||
|     if (matrix->cursor - &matrix->display[0][0] == sizeof(matrix->display)) { | ||||
|         // We went off the end; scroll the display upwards by one line
 | ||||
|         memmove(&matrix->display[0], &matrix->display[1], MatrixCols * (MatrixRows - 1)); | ||||
|         matrix->cursor = &matrix->display[MatrixRows - 1][0]; | ||||
|         memset(matrix->cursor, ' ', MatrixCols); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c) { | ||||
|   matrix->dirty = true; | ||||
|     matrix->dirty = true; | ||||
| 
 | ||||
|   if (c == '\n') { | ||||
|     // Clear to end of line from the cursor and then move to the
 | ||||
|     // start of the next line
 | ||||
|     uint8_t cursor_col = (matrix->cursor - &matrix->display[0][0]) % MatrixCols; | ||||
|     if (c == '\n') { | ||||
|         // Clear to end of line from the cursor and then move to the
 | ||||
|         // start of the next line
 | ||||
|         uint8_t cursor_col = (matrix->cursor - &matrix->display[0][0]) % MatrixCols; | ||||
| 
 | ||||
|     while (cursor_col++ < MatrixCols) { | ||||
|       matrix_write_char_inner(matrix, ' '); | ||||
|         while (cursor_col++ < MatrixCols) { | ||||
|             matrix_write_char_inner(matrix, ' '); | ||||
|         } | ||||
|         return; | ||||
|     } | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   matrix_write_char_inner(matrix, c); | ||||
|     matrix_write_char_inner(matrix, c); | ||||
| } | ||||
| 
 | ||||
| void iota_gfx_write_char(uint8_t c) { | ||||
|   matrix_write_char(&display, c); | ||||
| } | ||||
| void iota_gfx_write_char(uint8_t c) { matrix_write_char(&display, c); } | ||||
| 
 | ||||
| void matrix_write(struct CharacterMatrix *matrix, const char *data) { | ||||
|   const char *end = data + strlen(data); | ||||
|   while (data < end) { | ||||
|     matrix_write_char(matrix, *data); | ||||
|     ++data; | ||||
|   } | ||||
|     const char *end = data + strlen(data); | ||||
|     while (data < end) { | ||||
|         matrix_write_char(matrix, *data); | ||||
|         ++data; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void iota_gfx_write(const char *data) { | ||||
|   matrix_write(&display, data); | ||||
| } | ||||
| void iota_gfx_write(const char *data) { matrix_write(&display, data); } | ||||
| 
 | ||||
| void matrix_write_P(struct CharacterMatrix *matrix, const char *data) { | ||||
|   while (true) { | ||||
|     uint8_t c = pgm_read_byte(data); | ||||
|     if (c == 0) { | ||||
|       return; | ||||
|     while (true) { | ||||
|         uint8_t c = pgm_read_byte(data); | ||||
|         if (c == 0) { | ||||
|             return; | ||||
|         } | ||||
|         matrix_write_char(matrix, c); | ||||
|         ++data; | ||||
|     } | ||||
|     matrix_write_char(matrix, c); | ||||
|     ++data; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void iota_gfx_write_P(const char *data) { | ||||
|   matrix_write_P(&display, data); | ||||
| } | ||||
| void iota_gfx_write_P(const char *data) { matrix_write_P(&display, data); } | ||||
| 
 | ||||
| void matrix_clear(struct CharacterMatrix *matrix) { | ||||
|   memset(matrix->display, ' ', sizeof(matrix->display)); | ||||
|   matrix->cursor = &matrix->display[0][0]; | ||||
|   matrix->dirty = true; | ||||
|     memset(matrix->display, ' ', sizeof(matrix->display)); | ||||
|     matrix->cursor = &matrix->display[0][0]; | ||||
|     matrix->dirty  = true; | ||||
| } | ||||
| 
 | ||||
| void iota_gfx_clear_screen(void) { | ||||
|   matrix_clear(&display); | ||||
| } | ||||
| void iota_gfx_clear_screen(void) { matrix_clear(&display); } | ||||
| 
 | ||||
| void matrix_render(struct CharacterMatrix *matrix) { | ||||
|   last_flush = timer_read(); | ||||
|   iota_gfx_on(); | ||||
| #if DEBUG_TO_SCREEN | ||||
|   ++displaying; | ||||
| #endif | ||||
|     last_flush = timer_read(); | ||||
|     iota_gfx_on(); | ||||
| #    if DEBUG_TO_SCREEN | ||||
|     ++displaying; | ||||
| #    endif | ||||
| 
 | ||||
|   // Move to the home position
 | ||||
|   send_cmd3(PageAddr, 0, MatrixRows - 1); | ||||
|   send_cmd3(ColumnAddr, 0, (MatrixCols * FontWidth) - 1); | ||||
|     // Move to the home position
 | ||||
|     send_cmd3(PageAddr, 0, MatrixRows - 1); | ||||
|     send_cmd3(ColumnAddr, 0, (MatrixCols * FontWidth) - 1); | ||||
| 
 | ||||
|   if (i2c_start_write(SSD1306_ADDRESS)) { | ||||
|     goto done; | ||||
|   } | ||||
|   if (i2c_master_write(0x40)) { | ||||
|     // Data mode
 | ||||
|     goto done; | ||||
|   } | ||||
| 
 | ||||
|   for (uint8_t row = 0; row < MatrixRows; ++row) { | ||||
|     for (uint8_t col = 0; col < MatrixCols; ++col) { | ||||
|       const uint8_t *glyph = font + (matrix->display[row][col] * (FontWidth - 1)); | ||||
| 
 | ||||
|       for (uint8_t glyphCol = 0; glyphCol < FontWidth - 1; ++glyphCol) { | ||||
|         uint8_t colBits = pgm_read_byte(glyph + glyphCol); | ||||
|         i2c_master_write(colBits); | ||||
|       } | ||||
| 
 | ||||
|       // 1 column of space between chars (it's not included in the glyph)
 | ||||
|       i2c_master_write(0); | ||||
|     if (i2c_start_write(SSD1306_ADDRESS)) { | ||||
|         goto done; | ||||
|     } | ||||
|     if (i2c_master_write(0x40)) { | ||||
|         // Data mode
 | ||||
|         goto done; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   matrix->dirty = false; | ||||
|     for (uint8_t row = 0; row < MatrixRows; ++row) { | ||||
|         for (uint8_t col = 0; col < MatrixCols; ++col) { | ||||
|             const uint8_t *glyph = font + (matrix->display[row][col] * (FontWidth - 1)); | ||||
| 
 | ||||
|             for (uint8_t glyphCol = 0; glyphCol < FontWidth - 1; ++glyphCol) { | ||||
|                 uint8_t colBits = pgm_read_byte(glyph + glyphCol); | ||||
|                 i2c_master_write(colBits); | ||||
|             } | ||||
| 
 | ||||
|             // 1 column of space between chars (it's not included in the glyph)
 | ||||
|             i2c_master_write(0); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     matrix->dirty = false; | ||||
| 
 | ||||
| done: | ||||
|   i2c_master_stop(); | ||||
| #if DEBUG_TO_SCREEN | ||||
|   --displaying; | ||||
| #endif | ||||
|     i2c_master_stop(); | ||||
| #    if DEBUG_TO_SCREEN | ||||
|     --displaying; | ||||
| #    endif | ||||
| } | ||||
| 
 | ||||
| void iota_gfx_flush(void) { | ||||
|   matrix_render(&display); | ||||
| } | ||||
| void iota_gfx_flush(void) { matrix_render(&display); } | ||||
| 
 | ||||
| __attribute__ ((weak)) | ||||
| void iota_gfx_task_user(void) { | ||||
| } | ||||
| __attribute__((weak)) void iota_gfx_task_user(void) {} | ||||
| 
 | ||||
| void iota_gfx_task(void) { | ||||
|   iota_gfx_task_user(); | ||||
|     iota_gfx_task_user(); | ||||
| 
 | ||||
|   if (display.dirty) { | ||||
|     iota_gfx_flush(); | ||||
|   } | ||||
|     if (display.dirty) { | ||||
|         iota_gfx_flush(); | ||||
|     } | ||||
| 
 | ||||
|   if (timer_elapsed(last_flush) > ScreenOffInterval) { | ||||
|     iota_gfx_off(); | ||||
|   } | ||||
|     if (timer_elapsed(last_flush) > ScreenOffInterval) { | ||||
|         iota_gfx_off(); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
|  |  | |||
|  | @ -7,49 +7,49 @@ | |||
| #include "config.h" | ||||
| 
 | ||||
| enum ssd1306_cmds { | ||||
|   DisplayOff = 0xAE, | ||||
|   DisplayOn = 0xAF, | ||||
|     DisplayOff = 0xAE, | ||||
|     DisplayOn  = 0xAF, | ||||
| 
 | ||||
|   SetContrast = 0x81, | ||||
|   DisplayAllOnResume = 0xA4, | ||||
|     SetContrast        = 0x81, | ||||
|     DisplayAllOnResume = 0xA4, | ||||
| 
 | ||||
|   DisplayAllOn = 0xA5, | ||||
|   NormalDisplay = 0xA6, | ||||
|   InvertDisplay = 0xA7, | ||||
|   SetDisplayOffset = 0xD3, | ||||
|   SetComPins = 0xda, | ||||
|   SetVComDetect = 0xdb, | ||||
|   SetDisplayClockDiv = 0xD5, | ||||
|   SetPreCharge = 0xd9, | ||||
|   SetMultiPlex = 0xa8, | ||||
|   SetLowColumn = 0x00, | ||||
|   SetHighColumn = 0x10, | ||||
|   SetStartLine = 0x40, | ||||
|     DisplayAllOn       = 0xA5, | ||||
|     NormalDisplay      = 0xA6, | ||||
|     InvertDisplay      = 0xA7, | ||||
|     SetDisplayOffset   = 0xD3, | ||||
|     SetComPins         = 0xda, | ||||
|     SetVComDetect      = 0xdb, | ||||
|     SetDisplayClockDiv = 0xD5, | ||||
|     SetPreCharge       = 0xd9, | ||||
|     SetMultiPlex       = 0xa8, | ||||
|     SetLowColumn       = 0x00, | ||||
|     SetHighColumn      = 0x10, | ||||
|     SetStartLine       = 0x40, | ||||
| 
 | ||||
|   SetMemoryMode = 0x20, | ||||
|   ColumnAddr = 0x21, | ||||
|   PageAddr = 0x22, | ||||
|     SetMemoryMode = 0x20, | ||||
|     ColumnAddr    = 0x21, | ||||
|     PageAddr      = 0x22, | ||||
| 
 | ||||
|   ComScanInc = 0xc0, | ||||
|   ComScanDec = 0xc8, | ||||
|   SegRemap = 0xa0, | ||||
|   SetChargePump = 0x8d, | ||||
|   ExternalVcc = 0x01, | ||||
|   SwitchCapVcc = 0x02, | ||||
|     ComScanInc    = 0xc0, | ||||
|     ComScanDec    = 0xc8, | ||||
|     SegRemap      = 0xa0, | ||||
|     SetChargePump = 0x8d, | ||||
|     ExternalVcc   = 0x01, | ||||
|     SwitchCapVcc  = 0x02, | ||||
| 
 | ||||
|   ActivateScroll = 0x2f, | ||||
|   DeActivateScroll = 0x2e, | ||||
|   SetVerticalScrollArea = 0xa3, | ||||
|   RightHorizontalScroll = 0x26, | ||||
|   LeftHorizontalScroll = 0x27, | ||||
|   VerticalAndRightHorizontalScroll = 0x29, | ||||
|   VerticalAndLeftHorizontalScroll = 0x2a, | ||||
|     ActivateScroll                   = 0x2f, | ||||
|     DeActivateScroll                 = 0x2e, | ||||
|     SetVerticalScrollArea            = 0xa3, | ||||
|     RightHorizontalScroll            = 0x26, | ||||
|     LeftHorizontalScroll             = 0x27, | ||||
|     VerticalAndRightHorizontalScroll = 0x29, | ||||
|     VerticalAndLeftHorizontalScroll  = 0x2a, | ||||
| }; | ||||
| 
 | ||||
| // Controls the SSD1306 128x32 OLED display via i2c
 | ||||
| 
 | ||||
| #ifndef SSD1306_ADDRESS | ||||
| #define SSD1306_ADDRESS 0x3C | ||||
| #    define SSD1306_ADDRESS 0x3C | ||||
| #endif | ||||
| 
 | ||||
| #define DisplayHeight 32 | ||||
|  | @ -62,9 +62,9 @@ enum ssd1306_cmds { | |||
| #define MatrixCols (DisplayWidth / FontWidth) | ||||
| 
 | ||||
| struct CharacterMatrix { | ||||
|   uint8_t display[MatrixRows][MatrixCols]; | ||||
|   uint8_t *cursor; | ||||
|   bool dirty; | ||||
|     uint8_t  display[MatrixRows][MatrixCols]; | ||||
|     uint8_t *cursor; | ||||
|     bool     dirty; | ||||
| }; | ||||
| 
 | ||||
| struct CharacterMatrix display; | ||||
|  | @ -88,6 +88,4 @@ void matrix_write(struct CharacterMatrix *matrix, const char *data); | |||
| void matrix_write_P(struct CharacterMatrix *matrix, const char *data); | ||||
| void matrix_render(struct CharacterMatrix *matrix); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
|  | @ -1,25 +1,25 @@ | |||
| /*
 | ||||
| * light weight WS2812 lib V2.0b | ||||
| * | ||||
| * Controls WS2811/WS2812/WS2812B RGB-LEDs | ||||
| * Author: Tim (cpldcpu@gmail.com) | ||||
| * | ||||
| * Jan 18th, 2014  v2.0b Initial Version | ||||
| * Nov 29th, 2015  v2.3  Added SK6812RGBW support | ||||
| * | ||||
| * This program is free software: you can redistribute it and/or modify | ||||
| * it under the terms of the GNU General Public License as published by | ||||
| * the Free Software Foundation, either version 2 of the License, or | ||||
| * (at your option) any later version. | ||||
| * | ||||
| * This program is distributed in the hope that it will be useful, | ||||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| * GNU General Public License for more details. | ||||
| * | ||||
| * You should have received a copy of the GNU General Public License | ||||
| * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
| */ | ||||
|  * light weight WS2812 lib V2.0b | ||||
|  * | ||||
|  * Controls WS2811/WS2812/WS2812B RGB-LEDs | ||||
|  * Author: Tim (cpldcpu@gmail.com) | ||||
|  * | ||||
|  * Jan 18th, 2014  v2.0b Initial Version | ||||
|  * Nov 29th, 2015  v2.3  Added SK6812RGBW support | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 2 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| 
 | ||||
| #include "ws2812.h" | ||||
| #include <avr/interrupt.h> | ||||
|  | @ -30,44 +30,40 @@ | |||
| #if !defined(LED_ARRAY) && defined(RGB_MATRIX_ENABLE) | ||||
| // LED color buffer
 | ||||
| LED_TYPE led[DRIVER_LED_TOTAL]; | ||||
|   #define LED_ARRAY led | ||||
| #    define LED_ARRAY led | ||||
| #endif | ||||
| 
 | ||||
| #ifdef RGBW_BB_TWI | ||||
| 
 | ||||
| // Port for the I2C
 | ||||
| #define I2C_DDR DDRD | ||||
| #define I2C_PIN PIND | ||||
| #define I2C_PORT PORTD | ||||
| #    define I2C_DDR DDRD | ||||
| #    define I2C_PIN PIND | ||||
| #    define I2C_PORT PORTD | ||||
| 
 | ||||
| // Pins to be used in the bit banging
 | ||||
| #define I2C_CLK 0 | ||||
| #define I2C_DAT 1 | ||||
| #    define I2C_CLK 0 | ||||
| #    define I2C_DAT 1 | ||||
| 
 | ||||
| #define I2C_DATA_HI()\ | ||||
| I2C_DDR &= ~ (1 << I2C_DAT);\ | ||||
| I2C_PORT |= (1 << I2C_DAT); | ||||
| #define I2C_DATA_LO()\ | ||||
| I2C_DDR |= (1 << I2C_DAT);\ | ||||
| I2C_PORT &= ~ (1 << I2C_DAT); | ||||
| #    define I2C_DATA_HI()           \ | ||||
|         I2C_DDR &= ~(1 << I2C_DAT); \ | ||||
|         I2C_PORT |= (1 << I2C_DAT); | ||||
| #    define I2C_DATA_LO()          \ | ||||
|         I2C_DDR |= (1 << I2C_DAT); \ | ||||
|         I2C_PORT &= ~(1 << I2C_DAT); | ||||
| 
 | ||||
| #define I2C_CLOCK_HI()\ | ||||
| I2C_DDR &= ~ (1 << I2C_CLK);\ | ||||
| I2C_PORT |= (1 << I2C_CLK); | ||||
| #define I2C_CLOCK_LO()\ | ||||
| I2C_DDR |= (1 << I2C_CLK);\ | ||||
| I2C_PORT &= ~ (1 << I2C_CLK); | ||||
| #    define I2C_CLOCK_HI()          \ | ||||
|         I2C_DDR &= ~(1 << I2C_CLK); \ | ||||
|         I2C_PORT |= (1 << I2C_CLK); | ||||
| #    define I2C_CLOCK_LO()         \ | ||||
|         I2C_DDR |= (1 << I2C_CLK); \ | ||||
|         I2C_PORT &= ~(1 << I2C_CLK); | ||||
| 
 | ||||
| #define I2C_DELAY 1 | ||||
| #    define I2C_DELAY 1 | ||||
| 
 | ||||
| void I2C_WriteBit(unsigned char c) | ||||
| { | ||||
|     if (c > 0) | ||||
|     { | ||||
| void I2C_WriteBit(unsigned char c) { | ||||
|     if (c > 0) { | ||||
|         I2C_DATA_HI(); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|     } else { | ||||
|         I2C_DATA_LO(); | ||||
|     } | ||||
| 
 | ||||
|  | @ -77,8 +73,7 @@ void I2C_WriteBit(unsigned char c) | |||
|     I2C_CLOCK_LO(); | ||||
|     _delay_us(I2C_DELAY); | ||||
| 
 | ||||
|     if (c > 0) | ||||
|     { | ||||
|     if (c > 0) { | ||||
|         I2C_DATA_LO(); | ||||
|     } | ||||
| 
 | ||||
|  | @ -87,9 +82,8 @@ void I2C_WriteBit(unsigned char c) | |||
| 
 | ||||
| // Inits bitbanging port, must be called before using the functions below
 | ||||
| //
 | ||||
| void I2C_Init(void) | ||||
| { | ||||
|     I2C_PORT &= ~ ((1 << I2C_DAT) | (1 << I2C_CLK)); | ||||
| void I2C_Init(void) { | ||||
|     I2C_PORT &= ~((1 << I2C_DAT) | (1 << I2C_CLK)); | ||||
| 
 | ||||
|     I2C_CLOCK_HI(); | ||||
|     I2C_DATA_HI(); | ||||
|  | @ -99,10 +93,9 @@ void I2C_Init(void) | |||
| 
 | ||||
| // Send a START Condition
 | ||||
| //
 | ||||
| void I2C_Start(void) | ||||
| { | ||||
| void I2C_Start(void) { | ||||
|     // set both to high at the same time
 | ||||
|     I2C_DDR &= ~ ((1 << I2C_DAT) | (1 << I2C_CLK)); | ||||
|     I2C_DDR &= ~((1 << I2C_DAT) | (1 << I2C_CLK)); | ||||
|     _delay_us(I2C_DELAY); | ||||
| 
 | ||||
|     I2C_DATA_LO(); | ||||
|  | @ -114,8 +107,7 @@ void I2C_Start(void) | |||
| 
 | ||||
| // Send a STOP Condition
 | ||||
| //
 | ||||
| void I2C_Stop(void) | ||||
| { | ||||
| void I2C_Stop(void) { | ||||
|     I2C_CLOCK_HI(); | ||||
|     _delay_us(I2C_DELAY); | ||||
| 
 | ||||
|  | @ -125,106 +117,91 @@ void I2C_Stop(void) | |||
| 
 | ||||
| // write a byte to the I2C slave device
 | ||||
| //
 | ||||
| unsigned char I2C_Write(unsigned char c) | ||||
| { | ||||
|     for (char i = 0; i < 8; i++) | ||||
|     { | ||||
| unsigned char I2C_Write(unsigned char c) { | ||||
|     for (char i = 0; i < 8; i++) { | ||||
|         I2C_WriteBit(c & 128); | ||||
| 
 | ||||
|         c <<= 1; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     I2C_WriteBit(0); | ||||
|     _delay_us(I2C_DELAY); | ||||
|     _delay_us(I2C_DELAY); | ||||
| 
 | ||||
|     // _delay_us(I2C_DELAY);
 | ||||
|     //return I2C_ReadBit();
 | ||||
|     // return I2C_ReadBit();
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #ifdef RGB_MATRIX_ENABLE | ||||
| // Set an led in the buffer to a color
 | ||||
| void inline ws2812_setled(int i, uint8_t r, uint8_t g, uint8_t b) | ||||
| { | ||||
| void inline ws2812_setled(int i, uint8_t r, uint8_t g, uint8_t b) { | ||||
|     led[i].r = r; | ||||
|     led[i].g = g; | ||||
|     led[i].b = b; | ||||
| } | ||||
| 
 | ||||
| void ws2812_setled_all  (uint8_t r, uint8_t g, uint8_t b) | ||||
| { | ||||
|   for (int i = 0; i < sizeof(led)/sizeof(led[0]); i++) { | ||||
|     led[i].r = r; | ||||
|     led[i].g = g; | ||||
|     led[i].b = b; | ||||
|   } | ||||
| void ws2812_setled_all(uint8_t r, uint8_t g, uint8_t b) { | ||||
|     for (int i = 0; i < sizeof(led) / sizeof(led[0]); i++) { | ||||
|         led[i].r = r; | ||||
|         led[i].g = g; | ||||
|         led[i].b = b; | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| // Setleds for standard RGB
 | ||||
| void inline ws2812_setleds(LED_TYPE *ledarray, uint16_t leds) | ||||
| { | ||||
|    // ws2812_setleds_pin(ledarray,leds, _BV(ws2812_pin));
 | ||||
|    ws2812_setleds_pin(ledarray,leds, _BV(RGB_DI_PIN & 0xF)); | ||||
| void inline ws2812_setleds(LED_TYPE *ledarray, uint16_t leds) { | ||||
|     // ws2812_setleds_pin(ledarray,leds, _BV(ws2812_pin));
 | ||||
|     ws2812_setleds_pin(ledarray, leds, _BV(RGB_DI_PIN & 0xF)); | ||||
| } | ||||
| 
 | ||||
| void inline ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmask) | ||||
| { | ||||
|   // ws2812_DDRREG |= pinmask; // Enable DDR
 | ||||
|   // new universal format (DDR)
 | ||||
|   _SFR_IO8((RGB_DI_PIN >> 4) + 1) |= pinmask; | ||||
| void inline ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmask) { | ||||
|     // ws2812_DDRREG |= pinmask; // Enable DDR
 | ||||
|     // new universal format (DDR)
 | ||||
|     _SFR_IO8((RGB_DI_PIN >> 4) + 1) |= pinmask; | ||||
| 
 | ||||
|   ws2812_sendarray_mask((uint8_t*)ledarray,leds+leds+leds,pinmask); | ||||
|   _delay_us(50); | ||||
|     ws2812_sendarray_mask((uint8_t *)ledarray, leds + leds + leds, pinmask); | ||||
|     _delay_us(50); | ||||
| } | ||||
| 
 | ||||
| // Setleds for SK6812RGBW
 | ||||
| void inline ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t leds) | ||||
| { | ||||
| 
 | ||||
|   #ifdef RGBW_BB_TWI | ||||
| void inline ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t leds) { | ||||
| #ifdef RGBW_BB_TWI | ||||
|     uint8_t sreg_prev, twcr_prev; | ||||
|     sreg_prev=SREG; | ||||
|     twcr_prev=TWCR; | ||||
|     sreg_prev = SREG; | ||||
|     twcr_prev = TWCR; | ||||
|     cli(); | ||||
|     TWCR &= ~(1<<TWEN); | ||||
|     TWCR &= ~(1 << TWEN); | ||||
|     I2C_Init(); | ||||
|     I2C_Start(); | ||||
|     I2C_Write(0x84); | ||||
|     uint16_t datlen = leds<<2; | ||||
|     uint8_t curbyte; | ||||
|     uint8_t * data = (uint8_t*)ledarray; | ||||
|     uint16_t datlen = leds << 2; | ||||
|     uint8_t  curbyte; | ||||
|     uint8_t *data = (uint8_t *)ledarray; | ||||
|     while (datlen--) { | ||||
|       curbyte=*data++; | ||||
|       I2C_Write(curbyte); | ||||
|         curbyte = *data++; | ||||
|         I2C_Write(curbyte); | ||||
|     } | ||||
|     I2C_Stop(); | ||||
|     SREG=sreg_prev; | ||||
|     TWCR=twcr_prev; | ||||
|   #endif | ||||
|     SREG = sreg_prev; | ||||
|     TWCR = twcr_prev; | ||||
| #endif | ||||
| 
 | ||||
|     // ws2812_DDRREG |= _BV(ws2812_pin); // Enable DDR
 | ||||
|     // new universal format (DDR)
 | ||||
|     _SFR_IO8((RGB_DI_PIN >> 4) + 1) |= _BV(RGB_DI_PIN & 0xF); | ||||
| 
 | ||||
|   // ws2812_DDRREG |= _BV(ws2812_pin); // Enable DDR
 | ||||
|   // new universal format (DDR)
 | ||||
|   _SFR_IO8((RGB_DI_PIN >> 4) + 1) |= _BV(RGB_DI_PIN & 0xF); | ||||
|     ws2812_sendarray_mask((uint8_t *)ledarray, leds << 2, _BV(RGB_DI_PIN & 0xF)); | ||||
| 
 | ||||
|   ws2812_sendarray_mask((uint8_t*)ledarray,leds<<2,_BV(RGB_DI_PIN & 0xF)); | ||||
| 
 | ||||
| 
 | ||||
|   #ifndef RGBW_BB_TWI | ||||
| #ifndef RGBW_BB_TWI | ||||
|     _delay_us(80); | ||||
|   #endif | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void ws2812_sendarray(uint8_t *data,uint16_t datlen) | ||||
| { | ||||
|   ws2812_sendarray_mask(data,datlen,_BV(RGB_DI_PIN & 0xF)); | ||||
| } | ||||
| void ws2812_sendarray(uint8_t *data, uint16_t datlen) { ws2812_sendarray_mask(data, datlen, _BV(RGB_DI_PIN & 0xF)); } | ||||
| 
 | ||||
| /*
 | ||||
|   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) | |||
| */ | ||||
| 
 | ||||
| // Timing in ns
 | ||||
| #define w_zeropulse   350 | ||||
| #define w_onepulse    900 | ||||
| #define w_zeropulse 350 | ||||
| #define w_onepulse 900 | ||||
| #define w_totalperiod 1250 | ||||
| 
 | ||||
| // Fixed cycles used by the inner loop
 | ||||
| #define w_fixedlow    2 | ||||
| #define w_fixedhigh   4 | ||||
| #define w_fixedtotal  8 | ||||
| #define w_fixedlow 2 | ||||
| #define w_fixedhigh 4 | ||||
| #define w_fixedtotal 8 | ||||
| 
 | ||||
| // Insert NOPs to match the timing, if possible
 | ||||
| #define w_zerocycles    (((F_CPU/1000)*w_zeropulse          )/1000000) | ||||
| #define w_onecycles     (((F_CPU/1000)*w_onepulse    +500000)/1000000) | ||||
| #define w_totalcycles   (((F_CPU/1000)*w_totalperiod +500000)/1000000) | ||||
| #define w_zerocycles (((F_CPU / 1000) * w_zeropulse) / 1000000) | ||||
| #define w_onecycles (((F_CPU / 1000) * w_onepulse + 500000) / 1000000) | ||||
| #define w_totalcycles (((F_CPU / 1000) * w_totalperiod + 500000) / 1000000) | ||||
| 
 | ||||
| // w1 - nops between rising edge and falling edge - low
 | ||||
| #define w1 (w_zerocycles-w_fixedlow) | ||||
| #define w1 (w_zerocycles - w_fixedlow) | ||||
| // w2   nops between fe low and fe high
 | ||||
| #define w2 (w_onecycles-w_fixedhigh-w1) | ||||
| #define w2 (w_onecycles - w_fixedhigh - w1) | ||||
| // w3   nops to complete loop
 | ||||
| #define w3 (w_totalcycles-w_fixedtotal-w1-w2) | ||||
| #define w3 (w_totalcycles - w_fixedtotal - w1 - w2) | ||||
| 
 | ||||
| #if w1>0 | ||||
|   #define w1_nops w1 | ||||
| #if w1 > 0 | ||||
| #    define w1_nops w1 | ||||
| #else | ||||
|   #define w1_nops  0 | ||||
| #    define w1_nops 0 | ||||
| #endif | ||||
| 
 | ||||
| // The only critical timing parameter is the minimum pulse length of the "0"
 | ||||
| // Warn or throw error if this timing can not be met with current F_CPU settings.
 | ||||
| #define w_lowtime ((w1_nops+w_fixedlow)*1000000)/(F_CPU/1000) | ||||
| #if w_lowtime>550 | ||||
|    #error "Light_ws2812: Sorry, the clock speed is too low. Did you set F_CPU correctly?" | ||||
| #elif w_lowtime>450 | ||||
|    #warning "Light_ws2812: The timing is critical and may only work on WS2812B, not on WS2812(S)." | ||||
|    #warning "Please consider a higher clockspeed, if possible" | ||||
| #define w_lowtime ((w1_nops + w_fixedlow) * 1000000) / (F_CPU / 1000) | ||||
| #if w_lowtime > 550 | ||||
| #    error "Light_ws2812: Sorry, the clock speed is too low. Did you set F_CPU correctly?" | ||||
| #elif w_lowtime > 450 | ||||
| #    warning "Light_ws2812: The timing is critical and may only work on WS2812B, not on WS2812(S)." | ||||
| #    warning "Please consider a higher clockspeed, if possible" | ||||
| #endif | ||||
| 
 | ||||
| #if w2>0 | ||||
| #define w2_nops w2 | ||||
| #if w2 > 0 | ||||
| #    define w2_nops w2 | ||||
| #else | ||||
| #define w2_nops  0 | ||||
| #    define w2_nops 0 | ||||
| #endif | ||||
| 
 | ||||
| #if w3>0 | ||||
| #define w3_nops w3 | ||||
| #if w3 > 0 | ||||
| #    define w3_nops w3 | ||||
| #else | ||||
| #define w3_nops  0 | ||||
| #    define w3_nops 0 | ||||
| #endif | ||||
| 
 | ||||
| #define w_nop1  "nop      \n\t" | ||||
| #define w_nop2  "rjmp .+0 \n\t" | ||||
| #define w_nop4  w_nop2 w_nop2 | ||||
| #define w_nop8  w_nop4 w_nop4 | ||||
| #define w_nop1 "nop      \n\t" | ||||
| #define w_nop2 "rjmp .+0 \n\t" | ||||
| #define w_nop4 w_nop2 w_nop2 | ||||
| #define w_nop8 w_nop4 w_nop4 | ||||
| #define w_nop16 w_nop8 w_nop8 | ||||
| 
 | ||||
| void inline ws2812_sendarray_mask(uint8_t *data,uint16_t datlen,uint8_t maskhi) | ||||
| { | ||||
|   uint8_t curbyte,ctr,masklo; | ||||
|   uint8_t sreg_prev; | ||||
| void inline ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t maskhi) { | ||||
|     uint8_t curbyte, ctr, masklo; | ||||
|     uint8_t sreg_prev; | ||||
| 
 | ||||
|   // masklo  =~maskhi&ws2812_PORTREG;
 | ||||
|   // maskhi |=        ws2812_PORTREG;
 | ||||
|   masklo  =~maskhi&_SFR_IO8((RGB_DI_PIN >> 4) + 2); | ||||
|   maskhi |=        _SFR_IO8((RGB_DI_PIN >> 4) + 2); | ||||
|   sreg_prev=SREG; | ||||
|   cli(); | ||||
|     // masklo  =~maskhi&ws2812_PORTREG;
 | ||||
|     // maskhi |=        ws2812_PORTREG;
 | ||||
|     masklo = ~maskhi & _SFR_IO8((RGB_DI_PIN >> 4) + 2); | ||||
|     maskhi |= _SFR_IO8((RGB_DI_PIN >> 4) + 2); | ||||
|     sreg_prev = SREG; | ||||
|     cli(); | ||||
| 
 | ||||
|   while (datlen--) { | ||||
|     curbyte=(*data++); | ||||
|     while (datlen--) { | ||||
|         curbyte = (*data++); | ||||
| 
 | ||||
|     asm volatile( | ||||
|     "       ldi   %0,8  \n\t" | ||||
|     "loop%=:            \n\t" | ||||
|     "       out   %2,%3 \n\t"    //  '1' [01] '0' [01] - re
 | ||||
| #if (w1_nops&1) | ||||
| w_nop1 | ||||
|         asm volatile("       ldi   %0,8  \n\t" | ||||
|                      "loop%=:            \n\t" | ||||
|                      "       out   %2,%3 \n\t"  //  '1' [01] '0' [01] - re
 | ||||
| #if (w1_nops & 1) | ||||
|                      w_nop1 | ||||
| #endif | ||||
| #if (w1_nops&2) | ||||
| w_nop2 | ||||
| #if (w1_nops & 2) | ||||
|                          w_nop2 | ||||
| #endif | ||||
| #if (w1_nops&4) | ||||
| w_nop4 | ||||
| #if (w1_nops & 4) | ||||
|                              w_nop4 | ||||
| #endif | ||||
| #if (w1_nops&8) | ||||
| w_nop8 | ||||
| #if (w1_nops & 8) | ||||
|                                  w_nop8 | ||||
| #endif | ||||
| #if (w1_nops&16) | ||||
| w_nop16 | ||||
| #if (w1_nops & 16) | ||||
|                                      w_nop16 | ||||
| #endif | ||||
|     "       sbrs  %1,7  \n\t"    //  '1' [03] '0' [02]
 | ||||
|     "       out   %2,%4 \n\t"    //  '1' [--] '0' [03] - fe-low
 | ||||
|     "       lsl   %1    \n\t"    //  '1' [04] '0' [04]
 | ||||
| #if (w2_nops&1) | ||||
|   w_nop1 | ||||
|                      "       sbrs  %1,7  \n\t"  //  '1' [03] '0' [02]
 | ||||
|                      "       out   %2,%4 \n\t"  //  '1' [--] '0' [03] - fe-low
 | ||||
|                      "       lsl   %1    \n\t"  //  '1' [04] '0' [04]
 | ||||
| #if (w2_nops & 1) | ||||
|                      w_nop1 | ||||
| #endif | ||||
| #if (w2_nops&2) | ||||
|   w_nop2 | ||||
| #if (w2_nops & 2) | ||||
|                          w_nop2 | ||||
| #endif | ||||
| #if (w2_nops&4) | ||||
|   w_nop4 | ||||
| #if (w2_nops & 4) | ||||
|                              w_nop4 | ||||
| #endif | ||||
| #if (w2_nops&8) | ||||
|   w_nop8 | ||||
| #if (w2_nops & 8) | ||||
|                                  w_nop8 | ||||
| #endif | ||||
| #if (w2_nops&16) | ||||
|   w_nop16 | ||||
| #if (w2_nops & 16) | ||||
|                                      w_nop16 | ||||
| #endif | ||||
|     "       out   %2,%4 \n\t"    //  '1' [+1] '0' [+1] - fe-high
 | ||||
| #if (w3_nops&1) | ||||
| w_nop1 | ||||
|                      "       out   %2,%4 \n\t"  //  '1' [+1] '0' [+1] - fe-high
 | ||||
| #if (w3_nops & 1) | ||||
|                      w_nop1 | ||||
| #endif | ||||
| #if (w3_nops&2) | ||||
| w_nop2 | ||||
| #if (w3_nops & 2) | ||||
|                          w_nop2 | ||||
| #endif | ||||
| #if (w3_nops&4) | ||||
| w_nop4 | ||||
| #if (w3_nops & 4) | ||||
|                              w_nop4 | ||||
| #endif | ||||
| #if (w3_nops&8) | ||||
| w_nop8 | ||||
| #if (w3_nops & 8) | ||||
|                                  w_nop8 | ||||
| #endif | ||||
| #if (w3_nops&16) | ||||
| w_nop16 | ||||
| #if (w3_nops & 16) | ||||
|                                      w_nop16 | ||||
| #endif | ||||
| 
 | ||||
|     "       dec   %0    \n\t"    //  '1' [+2] '0' [+2]
 | ||||
|     "       brne  loop%=\n\t"    //  '1' [+3] '0' [+4]
 | ||||
|     :	"=&d" (ctr) | ||||
|     :	"r" (curbyte), "I" (_SFR_IO_ADDR(_SFR_IO8((RGB_DI_PIN >> 4) + 2))), "r" (maskhi), "r" (masklo) | ||||
|     ); | ||||
|   } | ||||
|                      "       dec   %0    \n\t"  //  '1' [+2] '0' [+2]
 | ||||
|                      "       brne  loop%=\n\t"  //  '1' [+3] '0' [+4]
 | ||||
|                      : "=&d"(ctr) | ||||
|                      : "r"(curbyte), "I"(_SFR_IO_ADDR(_SFR_IO8((RGB_DI_PIN >> 4) + 2))), "r"(maskhi), "r"(masklo)); | ||||
|     } | ||||
| 
 | ||||
|   SREG=sreg_prev; | ||||
|     SREG = sreg_prev; | ||||
| } | ||||
|  |  | |||
|  | @ -43,12 +43,12 @@ | |||
|  *         - Wait 50<EFBFBD>s to reset the LEDs | ||||
|  */ | ||||
| #ifdef RGB_MATRIX_ENABLE | ||||
| void ws2812_setled      (int index, uint8_t r, uint8_t g, uint8_t b); | ||||
| void ws2812_setled_all  (uint8_t r, uint8_t g, uint8_t b); | ||||
| void ws2812_setled(int index, uint8_t r, uint8_t g, uint8_t b); | ||||
| void ws2812_setled_all(uint8_t r, uint8_t g, uint8_t b); | ||||
| #endif | ||||
| 
 | ||||
| void ws2812_setleds     (LED_TYPE *ledarray, uint16_t number_of_leds); | ||||
| void ws2812_setleds_pin (LED_TYPE *ledarray, uint16_t number_of_leds,uint8_t pinmask); | ||||
| void ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds); | ||||
| void ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t number_of_leds, uint8_t pinmask); | ||||
| void ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t number_of_leds); | ||||
| 
 | ||||
| /*
 | ||||
|  | @ -58,18 +58,17 @@ void ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t number_of_leds); | |||
|  * The length is the number of bytes to send - three per LED. | ||||
|  */ | ||||
| 
 | ||||
| void ws2812_sendarray     (uint8_t *array,uint16_t length); | ||||
| void ws2812_sendarray_mask(uint8_t *array,uint16_t length, uint8_t pinmask); | ||||
| 
 | ||||
| void ws2812_sendarray(uint8_t *array, uint16_t length); | ||||
| void ws2812_sendarray_mask(uint8_t *array, uint16_t length, uint8_t pinmask); | ||||
| 
 | ||||
| /*
 | ||||
|  * Internal defines | ||||
|  */ | ||||
| #ifndef CONCAT | ||||
| #define CONCAT(a, b)            a ## b | ||||
| #    define CONCAT(a, b) a##b | ||||
| #endif | ||||
| #ifndef CONCAT_EXP | ||||
| #define CONCAT_EXP(a, b)   CONCAT(a, b) | ||||
| #    define CONCAT_EXP(a, b) CONCAT(a, b) | ||||
| #endif | ||||
| 
 | ||||
| #endif /* LIGHT_WS2812_H_ */ | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 skullY
						skullY