aboutsummaryrefslogtreecommitdiff
path: root/drivers/avr
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/avr')
-rw-r--r--drivers/avr/analog.c69
-rw-r--r--drivers/avr/analog.h52
-rw-r--r--drivers/avr/glcdfont.c276
-rw-r--r--drivers/avr/pro_micro.h362
-rw-r--r--drivers/avr/ssd1306.c325
-rw-r--r--drivers/avr/ssd1306.h93
-rw-r--r--drivers/avr/ws2812.c342
-rw-r--r--drivers/avr/ws2812.h75
8 files changed, 1594 insertions, 0 deletions
diff --git a/drivers/avr/analog.c b/drivers/avr/analog.c
new file mode 100644
index 000000000..1ec38df75
--- /dev/null
+++ b/drivers/avr/analog.c
@@ -0,0 +1,69 @@
1/* Copyright 2015 Jack Humbert
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17// Simple analog to digitial conversion
18
19#include <avr/io.h>
20#include <avr/pgmspace.h>
21#include <stdint.h>
22#include "analog.h"
23
24
25static uint8_t aref = (1<<REFS0); // default to AREF = Vcc
26
27
28void analogReference(uint8_t mode)
29{
30 aref = mode & 0xC0;
31}
32
33
34// Arduino compatible pin input
35int16_t analogRead(uint8_t pin)
36{
37#if defined(__AVR_ATmega32U4__)
38 static const uint8_t PROGMEM pin_to_mux[] = {
39 0x00, 0x01, 0x04, 0x05, 0x06, 0x07,
40 0x25, 0x24, 0x23, 0x22, 0x21, 0x20};
41 if (pin >= 12) return 0;
42 return adc_read(pgm_read_byte(pin_to_mux + pin));
43#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
44 if (pin >= 8) return 0;
45 return adc_read(pin);
46#else
47 return 0;
48#endif
49}
50
51// Mux input
52int16_t adc_read(uint8_t mux)
53{
54#if defined(__AVR_AT90USB162__)
55 return 0;
56#else
57 uint8_t low;
58
59 ADCSRA = (1<<ADEN) | ADC_PRESCALER; // enable ADC
60 ADCSRB = (1<<ADHSM) | (mux & 0x20); // high speed mode
61 ADMUX = aref | (mux & 0x1F); // configure mux input
62 ADCSRA = (1<<ADEN) | ADC_PRESCALER | (1<<ADSC); // start the conversion
63 while (ADCSRA & (1<<ADSC)) ; // wait for result
64 low = ADCL; // must read LSB first
65 return (ADCH << 8) | low; // must read MSB only once!
66#endif
67}
68
69
diff --git a/drivers/avr/analog.h b/drivers/avr/analog.h
new file mode 100644
index 000000000..8d93de7dc
--- /dev/null
+++ b/drivers/avr/analog.h
@@ -0,0 +1,52 @@
1/* Copyright 2015 Jack Humbert
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef _analog_h_included__
18#define _analog_h_included__
19
20#include <stdint.h>
21
22void analogReference(uint8_t mode);
23int16_t analogRead(uint8_t pin);
24int16_t adc_read(uint8_t mux);
25
26#define ADC_REF_POWER (1<<REFS0)
27#define ADC_REF_INTERNAL ((1<<REFS1) | (1<<REFS0))
28#define ADC_REF_EXTERNAL (0)
29
30// These prescaler values are for high speed mode, ADHSM = 1
31#if F_CPU == 16000000L
32#define ADC_PRESCALER ((1<<ADPS2) | (1<<ADPS1))
33#elif F_CPU == 8000000L
34#define ADC_PRESCALER ((1<<ADPS2) | (1<<ADPS0))
35#elif F_CPU == 4000000L
36#define ADC_PRESCALER ((1<<ADPS2))
37#elif F_CPU == 2000000L
38#define ADC_PRESCALER ((1<<ADPS1) | (1<<ADPS0))
39#elif F_CPU == 1000000L
40#define ADC_PRESCALER ((1<<ADPS1))
41#else
42#define ADC_PRESCALER ((1<<ADPS0))
43#endif
44
45// some avr-libc versions do not properly define ADHSM
46#if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
47#if !defined(ADHSM)
48#define ADHSM (7)
49#endif
50#endif
51
52#endif
diff --git a/drivers/avr/glcdfont.c b/drivers/avr/glcdfont.c
new file mode 100644
index 000000000..6f88bd23a
--- /dev/null
+++ b/drivers/avr/glcdfont.c
@@ -0,0 +1,276 @@
1// This is the 'classic' fixed-space bitmap font for Adafruit_GFX since 1.0.
2// See gfxfont.h for newer custom bitmap font info.
3
4#ifndef FONT5X7_H
5#define FONT5X7_H
6
7#ifdef __AVR__
8 #include <avr/io.h>
9 #include <avr/pgmspace.h>
10#elif defined(ESP8266)
11 #include <pgmspace.h>
12#else
13 #define PROGMEM
14#endif
15
16// Standard ASCII 5x7 font
17
18static const unsigned char font[] PROGMEM = {
19 0x00, 0x00, 0x00, 0x00, 0x00,
20 0x3E, 0x5B, 0x4F, 0x5B, 0x3E,
21 0x3E, 0x6B, 0x4F, 0x6B, 0x3E,
22 0x1C, 0x3E, 0x7C, 0x3E, 0x1C,
23 0x18, 0x3C, 0x7E, 0x3C, 0x18,
24 0x1C, 0x57, 0x7D, 0x57, 0x1C,
25 0x1C, 0x5E, 0x7F, 0x5E, 0x1C,
26 0x00, 0x18, 0x3C, 0x18, 0x00,
27 0xFF, 0xE7, 0xC3, 0xE7, 0xFF,
28 0x00, 0x18, 0x24, 0x18, 0x00,
29 0xFF, 0xE7, 0xDB, 0xE7, 0xFF,
30 0x30, 0x48, 0x3A, 0x06, 0x0E,
31 0x26, 0x29, 0x79, 0x29, 0x26,
32 0x40, 0x7F, 0x05, 0x05, 0x07,
33 0x40, 0x7F, 0x05, 0x25, 0x3F,
34 0x5A, 0x3C, 0xE7, 0x3C, 0x5A,
35 0x7F, 0x3E, 0x1C, 0x1C, 0x08,
36 0x08, 0x1C, 0x1C, 0x3E, 0x7F,
37 0x14, 0x22, 0x7F, 0x22, 0x14,
38 0x5F, 0x5F, 0x00, 0x5F, 0x5F,
39 0x06, 0x09, 0x7F, 0x01, 0x7F,
40 0x00, 0x66, 0x89, 0x95, 0x6A,
41 0x60, 0x60, 0x60, 0x60, 0x60,
42 0x94, 0xA2, 0xFF, 0xA2, 0x94,
43 0x08, 0x04, 0x7E, 0x04, 0x08,
44 0x10, 0x20, 0x7E, 0x20, 0x10,
45 0x08, 0x08, 0x2A, 0x1C, 0x08,
46 0x08, 0x1C, 0x2A, 0x08, 0x08,
47 0x1E, 0x10, 0x10, 0x10, 0x10,
48 0x0C, 0x1E, 0x0C, 0x1E, 0x0C,
49 0x30, 0x38, 0x3E, 0x38, 0x30,
50 0x06, 0x0E, 0x3E, 0x0E, 0x06,
51 0x00, 0x00, 0x00, 0x00, 0x00,
52 0x00, 0x00, 0x5F, 0x00, 0x00,
53 0x00, 0x07, 0x00, 0x07, 0x00,
54 0x14, 0x7F, 0x14, 0x7F, 0x14,
55 0x24, 0x2A, 0x7F, 0x2A, 0x12,
56 0x23, 0x13, 0x08, 0x64, 0x62,
57 0x36, 0x49, 0x56, 0x20, 0x50,
58 0x00, 0x08, 0x07, 0x03, 0x00,
59 0x00, 0x1C, 0x22, 0x41, 0x00,
60 0x00, 0x41, 0x22, 0x1C, 0x00,
61 0x2A, 0x1C, 0x7F, 0x1C, 0x2A,
62 0x08, 0x08, 0x3E, 0x08, 0x08,
63 0x00, 0x80, 0x70, 0x30, 0x00,
64 0x08, 0x08, 0x08, 0x08, 0x08,
65 0x00, 0x00, 0x60, 0x60, 0x00,
66 0x20, 0x10, 0x08, 0x04, 0x02,
67 0x3E, 0x51, 0x49, 0x45, 0x3E,
68 0x00, 0x42, 0x7F, 0x40, 0x00,
69 0x72, 0x49, 0x49, 0x49, 0x46,
70 0x21, 0x41, 0x49, 0x4D, 0x33,
71 0x18, 0x14, 0x12, 0x7F, 0x10,
72 0x27, 0x45, 0x45, 0x45, 0x39,
73 0x3C, 0x4A, 0x49, 0x49, 0x31,
74 0x41, 0x21, 0x11, 0x09, 0x07,
75 0x36, 0x49, 0x49, 0x49, 0x36,
76 0x46, 0x49, 0x49, 0x29, 0x1E,
77 0x00, 0x00, 0x14, 0x00, 0x00,
78 0x00, 0x40, 0x34, 0x00, 0x00,
79 0x00, 0x08, 0x14, 0x22, 0x41,
80 0x14, 0x14, 0x14, 0x14, 0x14,
81 0x00, 0x41, 0x22, 0x14, 0x08,
82 0x02, 0x01, 0x59, 0x09, 0x06,
83 0x3E, 0x41, 0x5D, 0x59, 0x4E,
84 0x7C, 0x12, 0x11, 0x12, 0x7C,
85 0x7F, 0x49, 0x49, 0x49, 0x36,
86 0x3E, 0x41, 0x41, 0x41, 0x22,
87 0x7F, 0x41, 0x41, 0x41, 0x3E,
88 0x7F, 0x49, 0x49, 0x49, 0x41,
89 0x7F, 0x09, 0x09, 0x09, 0x01,
90 0x3E, 0x41, 0x41, 0x51, 0x73,
91 0x7F, 0x08, 0x08, 0x08, 0x7F,
92 0x00, 0x41, 0x7F, 0x41, 0x00,
93 0x20, 0x40, 0x41, 0x3F, 0x01,
94 0x7F, 0x08, 0x14, 0x22, 0x41,
95 0x7F, 0x40, 0x40, 0x40, 0x40,
96 0x7F, 0x02, 0x1C, 0x02, 0x7F,
97 0x7F, 0x04, 0x08, 0x10, 0x7F,
98 0x3E, 0x41, 0x41, 0x41, 0x3E,
99 0x7F, 0x09, 0x09, 0x09, 0x06,
100 0x3E, 0x41, 0x51, 0x21, 0x5E,
101 0x7F, 0x09, 0x19, 0x29, 0x46,
102 0x26, 0x49, 0x49, 0x49, 0x32,
103 0x03, 0x01, 0x7F, 0x01, 0x03,
104 0x3F, 0x40, 0x40, 0x40, 0x3F,
105 0x1F, 0x20, 0x40, 0x20, 0x1F,
106 0x3F, 0x40, 0x38, 0x40, 0x3F,
107 0x63, 0x14, 0x08, 0x14, 0x63,
108 0x03, 0x04, 0x78, 0x04, 0x03,
109 0x61, 0x59, 0x49, 0x4D, 0x43,
110 0x00, 0x7F, 0x41, 0x41, 0x41,
111 0x02, 0x04, 0x08, 0x10, 0x20,
112 0x00, 0x41, 0x41, 0x41, 0x7F,
113 0x04, 0x02, 0x01, 0x02, 0x04,
114 0x40, 0x40, 0x40, 0x40, 0x40,
115 0x00, 0x03, 0x07, 0x08, 0x00,
116 0x20, 0x54, 0x54, 0x78, 0x40,
117 0x7F, 0x28, 0x44, 0x44, 0x38,
118 0x38, 0x44, 0x44, 0x44, 0x28,
119 0x38, 0x44, 0x44, 0x28, 0x7F,
120 0x38, 0x54, 0x54, 0x54, 0x18,
121 0x00, 0x08, 0x7E, 0x09, 0x02,
122 0x18, 0xA4, 0xA4, 0x9C, 0x78,
123 0x7F, 0x08, 0x04, 0x04, 0x78,
124 0x00, 0x44, 0x7D, 0x40, 0x00,
125 0x20, 0x40, 0x40, 0x3D, 0x00,
126 0x7F, 0x10, 0x28, 0x44, 0x00,
127 0x00, 0x41, 0x7F, 0x40, 0x00,
128 0x7C, 0x04, 0x78, 0x04, 0x78,
129 0x7C, 0x08, 0x04, 0x04, 0x78,
130 0x38, 0x44, 0x44, 0x44, 0x38,
131 0xFC, 0x18, 0x24, 0x24, 0x18,
132 0x18, 0x24, 0x24, 0x18, 0xFC,
133 0x7C, 0x08, 0x04, 0x04, 0x08,
134 0x48, 0x54, 0x54, 0x54, 0x24,
135 0x04, 0x04, 0x3F, 0x44, 0x24,
136 0x3C, 0x40, 0x40, 0x20, 0x7C,
137 0x1C, 0x20, 0x40, 0x20, 0x1C,
138 0x3C, 0x40, 0x30, 0x40, 0x3C,
139 0x44, 0x28, 0x10, 0x28, 0x44,
140 0x4C, 0x90, 0x90, 0x90, 0x7C,
141 0x44, 0x64, 0x54, 0x4C, 0x44,
142 0x00, 0x08, 0x36, 0x41, 0x00,
143 0x00, 0x00, 0x77, 0x00, 0x00,
144 0x00, 0x41, 0x36, 0x08, 0x00,
145 0x02, 0x01, 0x02, 0x04, 0x02,
146 0x3C, 0x26, 0x23, 0x26, 0x3C,
147 0x1E, 0xA1, 0xA1, 0x61, 0x12,
148 0x3A, 0x40, 0x40, 0x20, 0x7A,
149 0x38, 0x54, 0x54, 0x55, 0x59,
150 0x21, 0x55, 0x55, 0x79, 0x41,
151 0x22, 0x54, 0x54, 0x78, 0x42, // a-umlaut
152 0x21, 0x55, 0x54, 0x78, 0x40,
153 0x20, 0x54, 0x55, 0x79, 0x40,
154 0x0C, 0x1E, 0x52, 0x72, 0x12,
155 0x39, 0x55, 0x55, 0x55, 0x59,
156 0x39, 0x54, 0x54, 0x54, 0x59,
157 0x39, 0x55, 0x54, 0x54, 0x58,
158 0x00, 0x00, 0x45, 0x7C, 0x41,
159 0x00, 0x02, 0x45, 0x7D, 0x42,
160 0x00, 0x01, 0x45, 0x7C, 0x40,
161 0x7D, 0x12, 0x11, 0x12, 0x7D, // A-umlaut
162 0xF0, 0x28, 0x25, 0x28, 0xF0,
163 0x7C, 0x54, 0x55, 0x45, 0x00,
164 0x20, 0x54, 0x54, 0x7C, 0x54,
165 0x7C, 0x0A, 0x09, 0x7F, 0x49,
166 0x32, 0x49, 0x49, 0x49, 0x32,
167 0x3A, 0x44, 0x44, 0x44, 0x3A, // o-umlaut
168 0x32, 0x4A, 0x48, 0x48, 0x30,
169 0x3A, 0x41, 0x41, 0x21, 0x7A,
170 0x3A, 0x42, 0x40, 0x20, 0x78,
171 0x00, 0x9D, 0xA0, 0xA0, 0x7D,
172 0x3D, 0x42, 0x42, 0x42, 0x3D, // O-umlaut
173 0x3D, 0x40, 0x40, 0x40, 0x3D,
174 0x3C, 0x24, 0xFF, 0x24, 0x24,
175 0x48, 0x7E, 0x49, 0x43, 0x66,
176 0x2B, 0x2F, 0xFC, 0x2F, 0x2B,
177 0xFF, 0x09, 0x29, 0xF6, 0x20,
178 0xC0, 0x88, 0x7E, 0x09, 0x03,
179 0x20, 0x54, 0x54, 0x79, 0x41,
180 0x00, 0x00, 0x44, 0x7D, 0x41,
181 0x30, 0x48, 0x48, 0x4A, 0x32,
182 0x38, 0x40, 0x40, 0x22, 0x7A,
183 0x00, 0x7A, 0x0A, 0x0A, 0x72,
184 0x7D, 0x0D, 0x19, 0x31, 0x7D,
185 0x26, 0x29, 0x29, 0x2F, 0x28,
186 0x26, 0x29, 0x29, 0x29, 0x26,
187 0x30, 0x48, 0x4D, 0x40, 0x20,
188 0x38, 0x08, 0x08, 0x08, 0x08,
189 0x08, 0x08, 0x08, 0x08, 0x38,
190 0x2F, 0x10, 0xC8, 0xAC, 0xBA,
191 0x2F, 0x10, 0x28, 0x34, 0xFA,
192 0x00, 0x00, 0x7B, 0x00, 0x00,
193 0x08, 0x14, 0x2A, 0x14, 0x22,
194 0x22, 0x14, 0x2A, 0x14, 0x08,
195 0x55, 0x00, 0x55, 0x00, 0x55, // #176 (25% block) missing in old code
196 0xAA, 0x55, 0xAA, 0x55, 0xAA, // 50% block
197 0xFF, 0x55, 0xFF, 0x55, 0xFF, // 75% block
198 0x00, 0x00, 0x00, 0xFF, 0x00,
199 0x10, 0x10, 0x10, 0xFF, 0x00,
200 0x14, 0x14, 0x14, 0xFF, 0x00,
201 0x10, 0x10, 0xFF, 0x00, 0xFF,
202 0x10, 0x10, 0xF0, 0x10, 0xF0,
203 0x14, 0x14, 0x14, 0xFC, 0x00,
204 0x14, 0x14, 0xF7, 0x00, 0xFF,
205 0x00, 0x00, 0xFF, 0x00, 0xFF,
206 0x14, 0x14, 0xF4, 0x04, 0xFC,
207 0x14, 0x14, 0x17, 0x10, 0x1F,
208 0x10, 0x10, 0x1F, 0x10, 0x1F,
209 0x14, 0x14, 0x14, 0x1F, 0x00,
210 0x10, 0x10, 0x10, 0xF0, 0x00,
211 0x00, 0x00, 0x00, 0x1F, 0x10,
212 0x10, 0x10, 0x10, 0x1F, 0x10,
213 0x10, 0x10, 0x10, 0xF0, 0x10,
214 0x00, 0x00, 0x00, 0xFF, 0x10,
215 0x10, 0x10, 0x10, 0x10, 0x10,
216 0x10, 0x10, 0x10, 0xFF, 0x10,
217 0x00, 0x00, 0x00, 0xFF, 0x14,
218 0x00, 0x00, 0xFF, 0x00, 0xFF,
219 0x00, 0x00, 0x1F, 0x10, 0x17,
220 0x00, 0x00, 0xFC, 0x04, 0xF4,
221 0x14, 0x14, 0x17, 0x10, 0x17,
222 0x14, 0x14, 0xF4, 0x04, 0xF4,
223 0x00, 0x00, 0xFF, 0x00, 0xF7,
224 0x14, 0x14, 0x14, 0x14, 0x14,
225 0x14, 0x14, 0xF7, 0x00, 0xF7,
226 0x14, 0x14, 0x14, 0x17, 0x14,
227 0x10, 0x10, 0x1F, 0x10, 0x1F,
228 0x14, 0x14, 0x14, 0xF4, 0x14,
229 0x10, 0x10, 0xF0, 0x10, 0xF0,
230 0x00, 0x00, 0x1F, 0x10, 0x1F,
231 0x00, 0x00, 0x00, 0x1F, 0x14,
232 0x00, 0x00, 0x00, 0xFC, 0x14,
233 0x00, 0x00, 0xF0, 0x10, 0xF0,
234 0x10, 0x10, 0xFF, 0x10, 0xFF,
235 0x14, 0x14, 0x14, 0xFF, 0x14,
236 0x10, 0x10, 0x10, 0x1F, 0x00,
237 0x00, 0x00, 0x00, 0xF0, 0x10,
238 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
239 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
240 0xFF, 0xFF, 0xFF, 0x00, 0x00,
241 0x00, 0x00, 0x00, 0xFF, 0xFF,
242 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
243 0x38, 0x44, 0x44, 0x38, 0x44,
244 0xFC, 0x4A, 0x4A, 0x4A, 0x34, // sharp-s or beta
245 0x7E, 0x02, 0x02, 0x06, 0x06,
246 0x02, 0x7E, 0x02, 0x7E, 0x02,
247 0x63, 0x55, 0x49, 0x41, 0x63,
248 0x38, 0x44, 0x44, 0x3C, 0x04,
249 0x40, 0x7E, 0x20, 0x1E, 0x20,
250 0x06, 0x02, 0x7E, 0x02, 0x02,
251 0x99, 0xA5, 0xE7, 0xA5, 0x99,
252 0x1C, 0x2A, 0x49, 0x2A, 0x1C,
253 0x4C, 0x72, 0x01, 0x72, 0x4C,
254 0x30, 0x4A, 0x4D, 0x4D, 0x30,
255 0x30, 0x48, 0x78, 0x48, 0x30,
256 0xBC, 0x62, 0x5A, 0x46, 0x3D,
257 0x3E, 0x49, 0x49, 0x49, 0x00,
258 0x7E, 0x01, 0x01, 0x01, 0x7E,
259 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
260 0x44, 0x44, 0x5F, 0x44, 0x44,
261 0x40, 0x51, 0x4A, 0x44, 0x40,
262 0x40, 0x44, 0x4A, 0x51, 0x40,
263 0x00, 0x00, 0xFF, 0x01, 0x03,
264 0xE0, 0x80, 0xFF, 0x00, 0x00,
265 0x08, 0x08, 0x6B, 0x6B, 0x08,
266 0x36, 0x12, 0x36, 0x24, 0x36,
267 0x06, 0x0F, 0x09, 0x0F, 0x06,
268 0x00, 0x00, 0x18, 0x18, 0x00,
269 0x00, 0x00, 0x10, 0x10, 0x00,
270 0x30, 0x40, 0xFF, 0x01, 0x01,
271 0x00, 0x1F, 0x01, 0x01, 0x1E,
272 0x00, 0x19, 0x1D, 0x17, 0x12,
273 0x00, 0x3C, 0x3C, 0x3C, 0x3C,
274 0x00, 0x00, 0x00, 0x00, 0x00 // #255 NBSP
275};
276#endif // FONT5X7_H
diff --git a/drivers/avr/pro_micro.h b/drivers/avr/pro_micro.h
new file mode 100644
index 000000000..f9e7ed75d
--- /dev/null
+++ b/drivers/avr/pro_micro.h
@@ -0,0 +1,362 @@
1/*
2 pins_arduino.h - Pin definition functions for Arduino
3 Part of Arduino - http://www.arduino.cc/
4
5 Copyright (c) 2007 David A. Mellis
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General
18 Public License along with this library; if not, write to the
19 Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20 Boston, MA 02111-1307 USA
21
22 $Id: wiring.h 249 2007-02-03 16:52:51Z mellis $
23*/
24
25#ifndef Pins_Arduino_h
26#define Pins_Arduino_h
27
28#include <avr/pgmspace.h>
29
30// Workaround for wrong definitions in "iom32u4.h".
31// This should be fixed in the AVR toolchain.
32#undef UHCON
33#undef UHINT
34#undef UHIEN
35#undef UHADDR
36#undef UHFNUM
37#undef UHFNUML
38#undef UHFNUMH
39#undef UHFLEN
40#undef UPINRQX
41#undef UPINTX
42#undef UPNUM
43#undef UPRST
44#undef UPCONX
45#undef UPCFG0X
46#undef UPCFG1X
47#undef UPSTAX
48#undef UPCFG2X
49#undef UPIENX
50#undef UPDATX
51#undef TCCR2A
52#undef WGM20
53#undef WGM21
54#undef COM2B0
55#undef COM2B1
56#undef COM2A0
57#undef COM2A1
58#undef TCCR2B
59#undef CS20
60#undef CS21
61#undef CS22
62#undef WGM22
63#undef FOC2B
64#undef FOC2A
65#undef TCNT2
66#undef TCNT2_0
67#undef TCNT2_1
68#undef TCNT2_2
69#undef TCNT2_3
70#undef TCNT2_4
71#undef TCNT2_5
72#undef TCNT2_6
73#undef TCNT2_7
74#undef OCR2A
75#undef OCR2_0
76#undef OCR2_1
77#undef OCR2_2
78#undef OCR2_3
79#undef OCR2_4
80#undef OCR2_5
81#undef OCR2_6
82#undef OCR2_7
83#undef OCR2B
84#undef OCR2_0
85#undef OCR2_1
86#undef OCR2_2
87#undef OCR2_3
88#undef OCR2_4
89#undef OCR2_5
90#undef OCR2_6
91#undef OCR2_7
92
93#define NUM_DIGITAL_PINS 30
94#define NUM_ANALOG_INPUTS 12
95
96#define TX_RX_LED_INIT DDRD |= (1<<5), DDRB |= (1<<0)
97#define TXLED0 PORTD |= (1<<5)
98#define TXLED1 PORTD &= ~(1<<5)
99#define RXLED0 PORTB |= (1<<0)
100#define RXLED1 PORTB &= ~(1<<0)
101
102static const uint8_t SDA = 2;
103static const uint8_t SCL = 3;
104#define LED_BUILTIN 13
105
106// Map SPI port to 'new' pins D14..D17
107static const uint8_t SS = 17;
108static const uint8_t MOSI = 16;
109static const uint8_t MISO = 14;
110static const uint8_t SCK = 15;
111
112// Mapping of analog pins as digital I/O
113// A6-A11 share with digital pins
114static const uint8_t ADC0 = 18;
115static const uint8_t ADC1 = 19;
116static const uint8_t ADC2 = 20;
117static const uint8_t ADC3 = 21;
118static const uint8_t ADC4 = 22;
119static const uint8_t ADC5 = 23;
120static const uint8_t ADC6 = 24; // D4
121static const uint8_t ADC7 = 25; // D6
122static const uint8_t ADC8 = 26; // D8
123static const uint8_t ADC9 = 27; // D9
124static const uint8_t ADC10 = 28; // D10
125static const uint8_t ADC11 = 29; // D12
126
127#define digitalPinToPCICR(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCICR) : ((uint8_t *)0))
128#define digitalPinToPCICRbit(p) 0
129#define digitalPinToPCMSK(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCMSK0) : ((uint8_t *)0))
130#define digitalPinToPCMSKbit(p) ( ((p) >= 8 && (p) <= 11) ? (p) - 4 : ((p) == 14 ? 3 : ((p) == 15 ? 1 : ((p) == 16 ? 2 : ((p) == 17 ? 0 : (p - A8 + 4))))))
131
132// __AVR_ATmega32U4__ has an unusual mapping of pins to channels
133extern const uint8_t PROGMEM analog_pin_to_channel_PGM[];
134#define analogPinToChannel(P) ( pgm_read_byte( analog_pin_to_channel_PGM + (P) ) )
135
136#define digitalPinToInterrupt(p) ((p) == 0 ? 2 : ((p) == 1 ? 3 : ((p) == 2 ? 1 : ((p) == 3 ? 0 : ((p) == 7 ? 4 : NOT_AN_INTERRUPT)))))
137
138#ifdef ARDUINO_MAIN
139
140// On the Arduino board, digital pins are also used
141// for the analog output (software PWM). Analog input
142// pins are a separate set.
143
144// ATMEL ATMEGA32U4 / ARDUINO LEONARDO
145//
146// D0 PD2 RXD1/INT2
147// D1 PD3 TXD1/INT3
148// D2 PD1 SDA SDA/INT1
149// D3# PD0 PWM8/SCL OC0B/SCL/INT0
150// D4 A6 PD4 ADC8
151// D5# PC6 ??? OC3A/#OC4A
152// D6# A7 PD7 FastPWM #OC4D/ADC10
153// D7 PE6 INT6/AIN0
154//
155// D8 A8 PB4 ADC11/PCINT4
156// D9# A9 PB5 PWM16 OC1A/#OC4B/ADC12/PCINT5
157// D10# A10 PB6 PWM16 OC1B/0c4B/ADC13/PCINT6
158// D11# PB7 PWM8/16 0C0A/OC1C/#RTS/PCINT7
159// D12 A11 PD6 T1/#OC4D/ADC9
160// D13# PC7 PWM10 CLK0/OC4A
161//
162// A0 D18 PF7 ADC7
163// A1 D19 PF6 ADC6
164// A2 D20 PF5 ADC5
165// A3 D21 PF4 ADC4
166// A4 D22 PF1 ADC1
167// A5 D23 PF0 ADC0
168//
169// New pins D14..D17 to map SPI port to digital pins
170//
171// MISO D14 PB3 MISO,PCINT3
172// SCK D15 PB1 SCK,PCINT1
173// MOSI D16 PB2 MOSI,PCINT2
174// SS D17 PB0 RXLED,SS/PCINT0
175//
176// Connected LEDs on board for TX and RX
177// TXLED D24 PD5 XCK1
178// RXLED D17 PB0
179// HWB PE2 HWB
180
181// these arrays map port names (e.g. port B) to the
182// appropriate addresses for various functions (e.g. reading
183// and writing)
184const uint16_t PROGMEM port_to_mode_PGM[] = {
185 NOT_A_PORT,
186 NOT_A_PORT,
187 (uint16_t) &DDRB,
188 (uint16_t) &DDRC,
189 (uint16_t) &DDRD,
190 (uint16_t) &DDRE,
191 (uint16_t) &DDRF,
192};
193
194const uint16_t PROGMEM port_to_output_PGM[] = {
195 NOT_A_PORT,
196 NOT_A_PORT,
197 (uint16_t) &PORTB,
198 (uint16_t) &PORTC,
199 (uint16_t) &PORTD,
200 (uint16_t) &PORTE,
201 (uint16_t) &PORTF,
202};
203
204const uint16_t PROGMEM port_to_input_PGM[] = {
205 NOT_A_PORT,
206 NOT_A_PORT,
207 (uint16_t) &PINB,
208 (uint16_t) &PINC,
209 (uint16_t) &PIND,
210 (uint16_t) &PINE,
211 (uint16_t) &PINF,
212};
213
214const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
215 PD, // D0 - PD2
216 PD, // D1 - PD3
217 PD, // D2 - PD1
218 PD, // D3 - PD0
219 PD, // D4 - PD4
220 PC, // D5 - PC6
221 PD, // D6 - PD7
222 PE, // D7 - PE6
223
224 PB, // D8 - PB4
225 PB, // D9 - PB5
226 PB, // D10 - PB6
227 PB, // D11 - PB7
228 PD, // D12 - PD6
229 PC, // D13 - PC7
230
231 PB, // D14 - MISO - PB3
232 PB, // D15 - SCK - PB1
233 PB, // D16 - MOSI - PB2
234 PB, // D17 - SS - PB0
235
236 PF, // D18 - A0 - PF7
237 PF, // D19 - A1 - PF6
238 PF, // D20 - A2 - PF5
239 PF, // D21 - A3 - PF4
240 PF, // D22 - A4 - PF1
241 PF, // D23 - A5 - PF0
242
243 PD, // D24 - PD5
244 PD, // D25 / D6 - A7 - PD7
245 PB, // D26 / D8 - A8 - PB4
246 PB, // D27 / D9 - A9 - PB5
247 PB, // D28 / D10 - A10 - PB6
248 PD, // D29 / D12 - A11 - PD6
249};
250
251const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = {
252 _BV(2), // D0 - PD2
253 _BV(3), // D1 - PD3
254 _BV(1), // D2 - PD1
255 _BV(0), // D3 - PD0
256 _BV(4), // D4 - PD4
257 _BV(6), // D5 - PC6
258 _BV(7), // D6 - PD7
259 _BV(6), // D7 - PE6
260
261 _BV(4), // D8 - PB4
262 _BV(5), // D9 - PB5
263 _BV(6), // D10 - PB6
264 _BV(7), // D11 - PB7
265 _BV(6), // D12 - PD6
266 _BV(7), // D13 - PC7
267
268 _BV(3), // D14 - MISO - PB3
269 _BV(1), // D15 - SCK - PB1
270 _BV(2), // D16 - MOSI - PB2
271 _BV(0), // D17 - SS - PB0
272
273 _BV(7), // D18 - A0 - PF7
274 _BV(6), // D19 - A1 - PF6
275 _BV(5), // D20 - A2 - PF5
276 _BV(4), // D21 - A3 - PF4
277 _BV(1), // D22 - A4 - PF1
278 _BV(0), // D23 - A5 - PF0
279
280 _BV(5), // D24 - PD5
281 _BV(7), // D25 / D6 - A7 - PD7
282 _BV(4), // D26 / D8 - A8 - PB4
283 _BV(5), // D27 / D9 - A9 - PB5
284 _BV(6), // D28 / D10 - A10 - PB6
285 _BV(6), // D29 / D12 - A11 - PD6
286};
287
288const uint8_t PROGMEM digital_pin_to_timer_PGM[] = {
289 NOT_ON_TIMER,
290 NOT_ON_TIMER,
291 NOT_ON_TIMER,
292 TIMER0B, /* 3 */
293 NOT_ON_TIMER,
294 TIMER3A, /* 5 */
295 TIMER4D, /* 6 */
296 NOT_ON_TIMER,
297
298 NOT_ON_TIMER,
299 TIMER1A, /* 9 */
300 TIMER1B, /* 10 */
301 TIMER0A, /* 11 */
302
303 NOT_ON_TIMER,
304 TIMER4A, /* 13 */
305
306 NOT_ON_TIMER,
307 NOT_ON_TIMER,
308 NOT_ON_TIMER,
309 NOT_ON_TIMER,
310 NOT_ON_TIMER,
311 NOT_ON_TIMER,
312
313 NOT_ON_TIMER,
314 NOT_ON_TIMER,
315 NOT_ON_TIMER,
316 NOT_ON_TIMER,
317 NOT_ON_TIMER,
318 NOT_ON_TIMER,
319 NOT_ON_TIMER,
320 NOT_ON_TIMER,
321 NOT_ON_TIMER,
322 NOT_ON_TIMER,
323};
324
325const uint8_t PROGMEM analog_pin_to_channel_PGM[] = {
326 7, // A0 PF7 ADC7
327 6, // A1 PF6 ADC6
328 5, // A2 PF5 ADC5
329 4, // A3 PF4 ADC4
330 1, // A4 PF1 ADC1
331 0, // A5 PF0 ADC0
332 8, // A6 D4 PD4 ADC8
333 10, // A7 D6 PD7 ADC10
334 11, // A8 D8 PB4 ADC11
335 12, // A9 D9 PB5 ADC12
336 13, // A10 D10 PB6 ADC13
337 9 // A11 D12 PD6 ADC9
338};
339
340#endif /* ARDUINO_MAIN */
341
342// These serial port names are intended to allow libraries and architecture-neutral
343// sketches to automatically default to the correct port name for a particular type
344// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
345// the first hardware serial port whose RX/TX pins are not dedicated to another use.
346//
347// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor
348//
349// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial
350//
351// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library
352//
353// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins.
354//
355// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX
356// pins are NOT connected to anything by default.
357#define SERIAL_PORT_MONITOR Serial
358#define SERIAL_PORT_USBVIRTUAL Serial
359#define SERIAL_PORT_HARDWARE Serial1
360#define SERIAL_PORT_HARDWARE_OPEN Serial1
361
362#endif /* Pins_Arduino_h */
diff --git a/drivers/avr/ssd1306.c b/drivers/avr/ssd1306.c
new file mode 100644
index 000000000..bb8938bba
--- /dev/null
+++ b/drivers/avr/ssd1306.c
@@ -0,0 +1,325 @@
1#ifdef SSD1306OLED
2
3#include "ssd1306.h"
4#include "i2c.h"
5#include <string.h>
6#include "print.h"
7#include "glcdfont.c"
8#ifdef ADAFRUIT_BLE_ENABLE
9#include "adafruit_ble.h"
10#endif
11#ifdef PROTOCOL_LUFA
12#include "lufa.h"
13#endif
14#include "sendchar.h"
15#include "timer.h"
16
17// Set this to 1 to help diagnose early startup problems
18// when testing power-on with ble. Turn it off otherwise,
19// as the latency of printing most of the debug info messes
20// with the matrix scan, causing keys to drop.
21#define DEBUG_TO_SCREEN 0
22
23//static uint16_t last_battery_update;
24//static uint32_t vbat;
25//#define BatteryUpdateInterval 10000 /* milliseconds */
26#define ScreenOffInterval 300000 /* milliseconds */
27#if DEBUG_TO_SCREEN
28static uint8_t displaying;
29#endif
30static uint16_t last_flush;
31
32// Write command sequence.
33// Returns true on success.
34static inline bool _send_cmd1(uint8_t cmd) {
35 bool res = false;
36
37 if (i2c_start_write(SSD1306_ADDRESS)) {
38 xprintf("failed to start write to %d\n", SSD1306_ADDRESS);
39 goto done;
40 }
41
42 if (i2c_master_write(0x0 /* command byte follows */)) {
43 print("failed to write control byte\n");
44
45 goto done;
46 }
47
48 if (i2c_master_write(cmd)) {
49 xprintf("failed to write command %d\n", cmd);
50 goto done;
51 }
52 res = true;
53done:
54 i2c_master_stop();
55 return res;
56}
57
58// Write 2-byte command sequence.
59// Returns true on success
60static inline bool _send_cmd2(uint8_t cmd, uint8_t opr) {
61 if (!_send_cmd1(cmd)) {
62 return false;
63 }
64 return _send_cmd1(opr);
65}
66
67// Write 3-byte command sequence.
68// Returns true on success
69static inline bool _send_cmd3(uint8_t cmd, uint8_t opr1, uint8_t opr2) {
70 if (!_send_cmd1(cmd)) {
71 return false;
72 }
73 if (!_send_cmd1(opr1)) {
74 return false;
75 }
76 return _send_cmd1(opr2);
77}
78
79#define send_cmd1(c) if (!_send_cmd1(c)) {goto done;}
80#define send_cmd2(c,o) if (!_send_cmd2(c,o)) {goto done;}
81#define send_cmd3(c,o1,o2) if (!_send_cmd3(c,o1,o2)) {goto done;}
82
83static void clear_display(void) {
84 matrix_clear(&display);
85
86 // Clear all of the display bits (there can be random noise
87 // in the RAM on startup)
88 send_cmd3(PageAddr, 0, (DisplayHeight / 8) - 1);
89 send_cmd3(ColumnAddr, 0, DisplayWidth - 1);
90
91 if (i2c_start_write(SSD1306_ADDRESS)) {
92 goto done;
93 }
94 if (i2c_master_write(0x40)) {
95 // Data mode
96 goto done;
97 }
98 for (uint8_t row = 0; row < MatrixRows; ++row) {
99 for (uint8_t col = 0; col < DisplayWidth; ++col) {
100 i2c_master_write(0);
101 }
102 }
103
104 display.dirty = false;
105
106done:
107 i2c_master_stop();
108}
109
110#if DEBUG_TO_SCREEN
111#undef sendchar
112static int8_t capture_sendchar(uint8_t c) {
113 sendchar(c);
114 iota_gfx_write_char(c);
115
116 if (!displaying) {
117 iota_gfx_flush();
118 }
119 return 0;
120}
121#endif
122
123bool iota_gfx_init(void) {
124 bool success = false;
125
126 send_cmd1(DisplayOff);
127 send_cmd2(SetDisplayClockDiv, 0x80);
128 send_cmd2(SetMultiPlex, DisplayHeight - 1);
129
130 send_cmd2(SetDisplayOffset, 0);
131
132
133 send_cmd1(SetStartLine | 0x0);
134 send_cmd2(SetChargePump, 0x14 /* Enable */);
135 send_cmd2(SetMemoryMode, 0 /* horizontal addressing */);
136
137#ifdef OLED_ROTATE180
138// the following Flip the display orientation 180 degrees
139 send_cmd1(SegRemap);
140 send_cmd1(ComScanInc);
141#endif
142#ifndef OLED_ROTATE180
143// Flips the display orientation 0 degrees
144 send_cmd1(SegRemap | 0x1);
145 send_cmd1(ComScanDec);
146#endif
147
148 send_cmd2(SetComPins, 0x2);
149 send_cmd2(SetContrast, 0x8f);
150 send_cmd2(SetPreCharge, 0xf1);
151 send_cmd2(SetVComDetect, 0x40);
152 send_cmd1(DisplayAllOnResume);
153 send_cmd1(NormalDisplay);
154 send_cmd1(DeActivateScroll);
155 send_cmd1(DisplayOn);
156
157 send_cmd2(SetContrast, 0); // Dim
158
159 clear_display();
160
161 success = true;
162
163 iota_gfx_flush();
164
165#if DEBUG_TO_SCREEN
166 print_set_sendchar(capture_sendchar);
167#endif
168
169done:
170 return success;
171}
172
173bool iota_gfx_off(void) {
174 bool success = false;
175
176 send_cmd1(DisplayOff);
177 success = true;
178
179done:
180 return success;
181}
182
183bool iota_gfx_on(void) {
184 bool success = false;
185
186 send_cmd1(DisplayOn);
187 success = true;
188
189done:
190 return success;
191}
192
193void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c) {
194 *matrix->cursor = c;
195 ++matrix->cursor;
196
197 if (matrix->cursor - &matrix->display[0][0] == sizeof(matrix->display)) {
198 // We went off the end; scroll the display upwards by one line
199 memmove(&matrix->display[0], &matrix->display[1],
200 MatrixCols * (MatrixRows - 1));
201 matrix->cursor = &matrix->display[MatrixRows - 1][0];
202 memset(matrix->cursor, ' ', MatrixCols);
203 }
204}
205
206void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c) {
207 matrix->dirty = true;
208
209 if (c == '\n') {
210 // Clear to end of line from the cursor and then move to the
211 // start of the next line
212 uint8_t cursor_col = (matrix->cursor - &matrix->display[0][0]) % MatrixCols;
213
214 while (cursor_col++ < MatrixCols) {
215 matrix_write_char_inner(matrix, ' ');
216 }
217 return;
218 }
219
220 matrix_write_char_inner(matrix, c);
221}
222
223void iota_gfx_write_char(uint8_t c) {
224 matrix_write_char(&display, c);
225}
226
227void matrix_write(struct CharacterMatrix *matrix, const char *data) {
228 const char *end = data + strlen(data);
229 while (data < end) {
230 matrix_write_char(matrix, *data);
231 ++data;
232 }
233}
234
235void iota_gfx_write(const char *data) {
236 matrix_write(&display, data);
237}
238
239void matrix_write_P(struct CharacterMatrix *matrix, const char *data) {
240 while (true) {
241 uint8_t c = pgm_read_byte(data);
242 if (c == 0) {
243 return;
244 }
245 matrix_write_char(matrix, c);
246 ++data;
247 }
248}
249
250void iota_gfx_write_P(const char *data) {
251 matrix_write_P(&display, data);
252}
253
254void matrix_clear(struct CharacterMatrix *matrix) {
255 memset(matrix->display, ' ', sizeof(matrix->display));
256 matrix->cursor = &matrix->display[0][0];
257 matrix->dirty = true;
258}
259
260void iota_gfx_clear_screen(void) {
261 matrix_clear(&display);
262}
263
264void matrix_render(struct CharacterMatrix *matrix) {
265 last_flush = timer_read();
266 iota_gfx_on();
267#if DEBUG_TO_SCREEN
268 ++displaying;
269#endif
270
271 // Move to the home position
272 send_cmd3(PageAddr, 0, MatrixRows - 1);
273 send_cmd3(ColumnAddr, 0, (MatrixCols * FontWidth) - 1);
274
275 if (i2c_start_write(SSD1306_ADDRESS)) {
276 goto done;
277 }
278 if (i2c_master_write(0x40)) {
279 // Data mode
280 goto done;
281 }
282
283 for (uint8_t row = 0; row < MatrixRows; ++row) {
284 for (uint8_t col = 0; col < MatrixCols; ++col) {
285 const uint8_t *glyph = font + (matrix->display[row][col] * (FontWidth - 1));
286
287 for (uint8_t glyphCol = 0; glyphCol < FontWidth - 1; ++glyphCol) {
288 uint8_t colBits = pgm_read_byte(glyph + glyphCol);
289 i2c_master_write(colBits);
290 }
291
292 // 1 column of space between chars (it's not included in the glyph)
293 i2c_master_write(0);
294 }
295 }
296
297 matrix->dirty = false;
298
299done:
300 i2c_master_stop();
301#if DEBUG_TO_SCREEN
302 --displaying;
303#endif
304}
305
306void iota_gfx_flush(void) {
307 matrix_render(&display);
308}
309
310__attribute__ ((weak))
311void iota_gfx_task_user(void) {
312}
313
314void iota_gfx_task(void) {
315 iota_gfx_task_user();
316
317 if (display.dirty) {
318 iota_gfx_flush();
319 }
320
321 if (timer_elapsed(last_flush) > ScreenOffInterval) {
322 iota_gfx_off();
323 }
324}
325#endif
diff --git a/drivers/avr/ssd1306.h b/drivers/avr/ssd1306.h
new file mode 100644
index 000000000..df6a75359
--- /dev/null
+++ b/drivers/avr/ssd1306.h
@@ -0,0 +1,93 @@
1#ifndef SSD1306_H
2#define SSD1306_H
3
4#include <stdbool.h>
5#include <stdio.h>
6#include "pincontrol.h"
7#include "config.h"
8
9enum ssd1306_cmds {
10 DisplayOff = 0xAE,
11 DisplayOn = 0xAF,
12
13 SetContrast = 0x81,
14 DisplayAllOnResume = 0xA4,
15
16 DisplayAllOn = 0xA5,
17 NormalDisplay = 0xA6,
18 InvertDisplay = 0xA7,
19 SetDisplayOffset = 0xD3,
20 SetComPins = 0xda,
21 SetVComDetect = 0xdb,
22 SetDisplayClockDiv = 0xD5,
23 SetPreCharge = 0xd9,
24 SetMultiPlex = 0xa8,
25 SetLowColumn = 0x00,
26 SetHighColumn = 0x10,
27 SetStartLine = 0x40,
28
29 SetMemoryMode = 0x20,
30 ColumnAddr = 0x21,
31 PageAddr = 0x22,
32
33 ComScanInc = 0xc0,
34 ComScanDec = 0xc8,
35 SegRemap = 0xa0,
36 SetChargePump = 0x8d,
37 ExternalVcc = 0x01,
38 SwitchCapVcc = 0x02,
39
40 ActivateScroll = 0x2f,
41 DeActivateScroll = 0x2e,
42 SetVerticalScrollArea = 0xa3,
43 RightHorizontalScroll = 0x26,
44 LeftHorizontalScroll = 0x27,
45 VerticalAndRightHorizontalScroll = 0x29,
46 VerticalAndLeftHorizontalScroll = 0x2a,
47};
48
49// Controls the SSD1306 128x32 OLED display via i2c
50
51#ifndef SSD1306_ADDRESS
52#define SSD1306_ADDRESS 0x3C
53#endif
54
55#define DisplayHeight 32
56#define DisplayWidth 128
57
58#define FontHeight 8
59#define FontWidth 6
60
61#define MatrixRows (DisplayHeight / FontHeight)
62#define MatrixCols (DisplayWidth / FontWidth)
63
64struct CharacterMatrix {
65 uint8_t display[MatrixRows][MatrixCols];
66 uint8_t *cursor;
67 bool dirty;
68};
69
70struct CharacterMatrix display;
71
72bool iota_gfx_init(void);
73void iota_gfx_task(void);
74bool iota_gfx_off(void);
75bool iota_gfx_on(void);
76void iota_gfx_flush(void);
77void iota_gfx_write_char(uint8_t c);
78void iota_gfx_write(const char *data);
79void iota_gfx_write_P(const char *data);
80void iota_gfx_clear_screen(void);
81
82void iota_gfx_task_user(void);
83
84void matrix_clear(struct CharacterMatrix *matrix);
85void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c);
86void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c);
87void matrix_write(struct CharacterMatrix *matrix, const char *data);
88void matrix_write_P(struct CharacterMatrix *matrix, const char *data);
89void matrix_render(struct CharacterMatrix *matrix);
90
91
92
93#endif
diff --git a/drivers/avr/ws2812.c b/drivers/avr/ws2812.c
new file mode 100644
index 000000000..59e032bf7
--- /dev/null
+++ b/drivers/avr/ws2812.c
@@ -0,0 +1,342 @@
1/*
2* light weight WS2812 lib V2.0b
3*
4* Controls WS2811/WS2812/WS2812B RGB-LEDs
5* Author: Tim (cpldcpu@gmail.com)
6*
7* Jan 18th, 2014 v2.0b Initial Version
8* Nov 29th, 2015 v2.3 Added SK6812RGBW support
9*
10* This program is free software: you can redistribute it and/or modify
11* it under the terms of the GNU General Public License as published by
12* the Free Software Foundation, either version 2 of the License, or
13* (at your option) any later version.
14*
15* This program is distributed in the hope that it will be useful,
16* but WITHOUT ANY WARRANTY; without even the implied warranty of
17* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18* GNU General Public License for more details.
19*
20* You should have received a copy of the GNU General Public License
21* along with this program. If not, see <http://www.gnu.org/licenses/>.
22*/
23
24#include "ws2812.h"
25#include <avr/interrupt.h>
26#include <avr/io.h>
27#include <util/delay.h>
28#include "debug.h"
29
30#ifdef RGBW_BB_TWI
31
32// Port for the I2C
33#define I2C_DDR DDRD
34#define I2C_PIN PIND
35#define I2C_PORT PORTD
36
37// Pins to be used in the bit banging
38#define I2C_CLK 0
39#define I2C_DAT 1
40
41#define I2C_DATA_HI()\
42I2C_DDR &= ~ (1 << I2C_DAT);\
43I2C_PORT |= (1 << I2C_DAT);
44#define I2C_DATA_LO()\
45I2C_DDR |= (1 << I2C_DAT);\
46I2C_PORT &= ~ (1 << I2C_DAT);
47
48#define I2C_CLOCK_HI()\
49I2C_DDR &= ~ (1 << I2C_CLK);\
50I2C_PORT |= (1 << I2C_CLK);
51#define I2C_CLOCK_LO()\
52I2C_DDR |= (1 << I2C_CLK);\
53I2C_PORT &= ~ (1 << I2C_CLK);
54
55#define I2C_DELAY 1
56
57void I2C_WriteBit(unsigned char c)
58{
59 if (c > 0)
60 {
61 I2C_DATA_HI();
62 }
63 else
64 {
65 I2C_DATA_LO();
66 }
67
68 I2C_CLOCK_HI();
69 _delay_us(I2C_DELAY);
70
71 I2C_CLOCK_LO();
72 _delay_us(I2C_DELAY);
73
74 if (c > 0)
75 {
76 I2C_DATA_LO();
77 }
78
79 _delay_us(I2C_DELAY);
80}
81
82// Inits bitbanging port, must be called before using the functions below
83//
84void I2C_Init(void)
85{
86 I2C_PORT &= ~ ((1 << I2C_DAT) | (1 << I2C_CLK));
87
88 I2C_CLOCK_HI();
89 I2C_DATA_HI();
90
91 _delay_us(I2C_DELAY);
92}
93
94// Send a START Condition
95//
96void I2C_Start(void)
97{
98 // set both to high at the same time
99 I2C_DDR &= ~ ((1 << I2C_DAT) | (1 << I2C_CLK));
100 _delay_us(I2C_DELAY);
101
102 I2C_DATA_LO();
103 _delay_us(I2C_DELAY);
104
105 I2C_CLOCK_LO();
106 _delay_us(I2C_DELAY);
107}
108
109// Send a STOP Condition
110//
111void I2C_Stop(void)
112{
113 I2C_CLOCK_HI();
114 _delay_us(I2C_DELAY);
115
116 I2C_DATA_HI();
117 _delay_us(I2C_DELAY);
118}
119
120// write a byte to the I2C slave device
121//
122unsigned char I2C_Write(unsigned char c)
123{
124 for (char i = 0; i < 8; i++)
125 {
126 I2C_WriteBit(c & 128);
127
128 c <<= 1;
129 }
130
131
132 I2C_WriteBit(0);
133 _delay_us(I2C_DELAY);
134 _delay_us(I2C_DELAY);
135
136 // _delay_us(I2C_DELAY);
137 //return I2C_ReadBit();
138 return 0;
139}
140
141
142#endif
143
144// Setleds for standard RGB
145void inline ws2812_setleds(LED_TYPE *ledarray, uint16_t leds)
146{
147 // ws2812_setleds_pin(ledarray,leds, _BV(ws2812_pin));
148 ws2812_setleds_pin(ledarray,leds, _BV(RGB_DI_PIN & 0xF));
149}
150
151void inline ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmask)
152{
153 // ws2812_DDRREG |= pinmask; // Enable DDR
154 // new universal format (DDR)
155 _SFR_IO8((RGB_DI_PIN >> 4) + 1) |= pinmask;
156
157 ws2812_sendarray_mask((uint8_t*)ledarray,leds+leds+leds,pinmask);
158 _delay_us(50);
159}
160
161// Setleds for SK6812RGBW
162void inline ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t leds)
163{
164
165 #ifdef RGBW_BB_TWI
166 uint8_t sreg_prev, twcr_prev;
167 sreg_prev=SREG;
168 twcr_prev=TWCR;
169 cli();
170 TWCR &= ~(1<<TWEN);
171 I2C_Init();
172 I2C_Start();
173 I2C_Write(0x84);
174 uint16_t datlen = leds<<2;
175 uint8_t curbyte;
176 uint8_t * data = (uint8_t*)ledarray;
177 while (datlen--) {
178 curbyte=*data++;
179 I2C_Write(curbyte);
180 }
181 I2C_Stop();
182 SREG=sreg_prev;
183 TWCR=twcr_prev;
184 #endif
185
186
187 // ws2812_DDRREG |= _BV(ws2812_pin); // Enable DDR
188 // new universal format (DDR)
189 _SFR_IO8((RGB_DI_PIN >> 4) + 1) |= _BV(RGB_DI_PIN & 0xF);
190
191 ws2812_sendarray_mask((uint8_t*)ledarray,leds<<2,_BV(RGB_DI_PIN & 0xF));
192
193
194 #ifndef RGBW_BB_TWI
195 _delay_us(80);
196 #endif
197}
198
199void ws2812_sendarray(uint8_t *data,uint16_t datlen)
200{
201 ws2812_sendarray_mask(data,datlen,_BV(RGB_DI_PIN & 0xF));
202}
203
204/*
205 This routine writes an array of bytes with RGB values to the Dataout pin
206 using the fast 800kHz clockless WS2811/2812 protocol.
207*/
208
209// Timing in ns
210#define w_zeropulse 350
211#define w_onepulse 900
212#define w_totalperiod 1250
213
214// Fixed cycles used by the inner loop
215#define w_fixedlow 2
216#define w_fixedhigh 4
217#define w_fixedtotal 8
218
219// Insert NOPs to match the timing, if possible
220#define w_zerocycles (((F_CPU/1000)*w_zeropulse )/1000000)
221#define w_onecycles (((F_CPU/1000)*w_onepulse +500000)/1000000)
222#define w_totalcycles (((F_CPU/1000)*w_totalperiod +500000)/1000000)
223
224// w1 - nops between rising edge and falling edge - low
225#define w1 (w_zerocycles-w_fixedlow)
226// w2 nops between fe low and fe high
227#define w2 (w_onecycles-w_fixedhigh-w1)
228// w3 nops to complete loop
229#define w3 (w_totalcycles-w_fixedtotal-w1-w2)
230
231#if w1>0
232 #define w1_nops w1
233#else
234 #define w1_nops 0
235#endif
236
237// The only critical timing parameter is the minimum pulse length of the "0"
238// Warn or throw error if this timing can not be met with current F_CPU settings.
239#define w_lowtime ((w1_nops+w_fixedlow)*1000000)/(F_CPU/1000)
240#if w_lowtime>550
241 #error "Light_ws2812: Sorry, the clock speed is too low. Did you set F_CPU correctly?"
242#elif w_lowtime>450
243 #warning "Light_ws2812: The timing is critical and may only work on WS2812B, not on WS2812(S)."
244 #warning "Please consider a higher clockspeed, if possible"
245#endif
246
247#if w2>0
248#define w2_nops w2
249#else
250#define w2_nops 0
251#endif
252
253#if w3>0
254#define w3_nops w3
255#else
256#define w3_nops 0
257#endif
258
259#define w_nop1 "nop \n\t"
260#define w_nop2 "rjmp .+0 \n\t"
261#define w_nop4 w_nop2 w_nop2
262#define w_nop8 w_nop4 w_nop4
263#define w_nop16 w_nop8 w_nop8
264
265void inline ws2812_sendarray_mask(uint8_t *data,uint16_t datlen,uint8_t maskhi)
266{
267 uint8_t curbyte,ctr,masklo;
268 uint8_t sreg_prev;
269
270 // masklo =~maskhi&ws2812_PORTREG;
271 // maskhi |= ws2812_PORTREG;
272 masklo =~maskhi&_SFR_IO8((RGB_DI_PIN >> 4) + 2);
273 maskhi |= _SFR_IO8((RGB_DI_PIN >> 4) + 2);
274 sreg_prev=SREG;
275 cli();
276
277 while (datlen--) {
278 curbyte=(*data++);
279
280 asm volatile(
281 " ldi %0,8 \n\t"
282 "loop%=: \n\t"
283 " out %2,%3 \n\t" // '1' [01] '0' [01] - re
284#if (w1_nops&1)
285w_nop1
286#endif
287#if (w1_nops&2)
288w_nop2
289#endif
290#if (w1_nops&4)
291w_nop4
292#endif
293#if (w1_nops&8)
294w_nop8
295#endif
296#if (w1_nops&16)
297w_nop16
298#endif
299 " sbrs %1,7 \n\t" // '1' [03] '0' [02]
300 " out %2,%4 \n\t" // '1' [--] '0' [03] - fe-low
301 " lsl %1 \n\t" // '1' [04] '0' [04]
302#if (w2_nops&1)
303 w_nop1
304#endif
305#if (w2_nops&2)
306 w_nop2
307#endif
308#if (w2_nops&4)
309 w_nop4
310#endif
311#if (w2_nops&8)
312 w_nop8
313#endif
314#if (w2_nops&16)
315 w_nop16
316#endif
317 " out %2,%4 \n\t" // '1' [+1] '0' [+1] - fe-high
318#if (w3_nops&1)
319w_nop1
320#endif
321#if (w3_nops&2)
322w_nop2
323#endif
324#if (w3_nops&4)
325w_nop4
326#endif
327#if (w3_nops&8)
328w_nop8
329#endif
330#if (w3_nops&16)
331w_nop16
332#endif
333
334 " dec %0 \n\t" // '1' [+2] '0' [+2]
335 " brne loop%=\n\t" // '1' [+3] '0' [+4]
336 : "=&d" (ctr)
337 : "r" (curbyte), "I" (_SFR_IO_ADDR(_SFR_IO8((RGB_DI_PIN >> 4) + 2))), "r" (maskhi), "r" (masklo)
338 );
339 }
340
341 SREG=sreg_prev;
342}
diff --git a/drivers/avr/ws2812.h b/drivers/avr/ws2812.h
new file mode 100644
index 000000000..f7e0c3144
--- /dev/null
+++ b/drivers/avr/ws2812.h
@@ -0,0 +1,75 @@
1/*
2 * light weight WS2812 lib include
3 *
4 * Version 2.3 - Nev 29th 2015
5 * Author: Tim (cpldcpu@gmail.com)
6 *
7 * Please do not change this file! All configuration is handled in "ws2812_config.h"
8 *
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#ifndef LIGHT_WS2812_H_
24#define LIGHT_WS2812_H_
25
26#include <avr/io.h>
27#include <avr/interrupt.h>
28//#include "ws2812_config.h"
29//#include "i2cmaster.h"
30
31#include "rgblight_types.h"
32
33
34/* User Interface
35 *
36 * Input:
37 * ledarray: An array of GRB data describing the LED colors
38 * number_of_leds: The number of LEDs to write
39 * pinmask (optional): Bitmask describing the output bin. e.g. _BV(PB0)
40 *
41 * The functions will perform the following actions:
42 * - Set the data-out pin as output
43 * - Send out the LED data
44 * - Wait 50�s to reset the LEDs
45 */
46
47void ws2812_setleds (LED_TYPE *ledarray, uint16_t number_of_leds);
48void ws2812_setleds_pin (LED_TYPE *ledarray, uint16_t number_of_leds,uint8_t pinmask);
49void ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t number_of_leds);
50
51/*
52 * Old interface / Internal functions
53 *
54 * The functions take a byte-array and send to the data output as WS2812 bitstream.
55 * The length is the number of bytes to send - three per LED.
56 */
57
58void ws2812_sendarray (uint8_t *array,uint16_t length);
59void ws2812_sendarray_mask(uint8_t *array,uint16_t length, uint8_t pinmask);
60
61
62/*
63 * Internal defines
64 */
65#ifndef CONCAT
66#define CONCAT(a, b) a ## b
67#endif
68#ifndef CONCAT_EXP
69#define CONCAT_EXP(a, b) CONCAT(a, b)
70#endif
71
72// #define ws2812_PORTREG CONCAT_EXP(PORT,ws2812_port)
73// #define ws2812_DDRREG CONCAT_EXP(DDR,ws2812_port)
74
75#endif /* LIGHT_WS2812_H_ */