Browse code

Add invert option

Nils Faerber authored on 06/07/2013 21:17:34
Showing 1 changed files
... ...
@@ -197,12 +197,21 @@ __interrupt void DMA_ISR (void)
197 197
 /* writes the complete internal framebuffer to the LCD */
198 198
 void mw_lcd_update_screen(void)
199 199
 {
200
-#ifndef LCD_DMA
200
+//#ifndef LCD_DMA
201 201
 	unsigned int i,j;
202
-#endif
202
+//#endif
203 203
 
204 204
 //	debug_uart_tx("uscr1\n");
205 205
 
206
+	// invert the buffer
207
+	if (0) {
208
+		for (i=0; i<96; i++) {
209
+			for ( j = 0; j < 12; j++ ) {
210
+				lcd_buf[i].Data[j] = ~lcd_buf[i].Data[j];
211
+			}
212
+		}
213
+	}
214
+
206 215
 	LCD_CS_ASSERT();
207 216
 
208 217
 	/* send WRITE command */
... ...
@@ -267,7 +276,7 @@ void mw_lcd_update_screen(void)
267 276
 	mw_lcd_static_mode();
268 277
 }
269 278
 
270
-void mw_lcd_draw_pixel(unsigned char x, unsigned char y, unsigned char color)
279
+void mw_lcd_draw_pixel(const uint8_t x, const uint8_t y, const uint8_t color)
271 280
 {
272 281
 	switch (color) {
273 282
 		case 1:
Browse code

Here we are! MetaWatch support in Oswald!

Nils Faerber authored on 27/04/2013 20:22:32
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,284 @@
1
+#include <msp430.h>
2
+#include <stdint.h>
3
+
4
+#include "mw_main.h"
5
+
6
+#include "mw_lcd.h"
7
+#include "mw_uart.h"
8
+
9
+// SMCLK = 16MHz -> divide by 16 to get 1 MHz SPI clock,
10
+// 1MHz maximum according to LCD spec
11
+//#define SPI_PRESCALE_L		0x10
12
+// currently we only run @1MHz
13
+#define SPI_PRESCALE_L		0x10
14
+#define SPI_PRESCALE_H		0x00
15
+
16
+#define LCD_STATIC_CMD		0x00
17
+#define LCD_WRITE_CMD		0x01
18
+#define LCD_CLEAR_CMD		0x04     
19
+
20
+static const unsigned char LCD_CLEAR_COMMAND[] = {LCD_CLEAR_CMD, 0x00};
21
+#define LCD_CLEAR_CMD_SIZE	0x02
22
+static const unsigned char LCD_STATIC_COMMAND[] = {LCD_STATIC_CMD, 0x00};
23
+#define LCD_STATIC_CMD_SIZE	0x02
24
+
25
+
26
+/* the LCD frame buffer, 96 lines */
27
+tLcdLine lcd_buf[96];
28
+
29
+
30
+#define LCD_DMA
31
+/* errata - DMA variables cannot be function scope */
32
+#ifdef LCD_DMA
33
+static unsigned char LcdDmaBusy = 0;
34
+#endif
35
+
36
+
37
+void memfill(void *target, unsigned char val, unsigned int count)
38
+{
39
+	while (count--) {
40
+		*(unsigned char *)(target+count) = val;
41
+	}
42
+}
43
+
44
+void mw_lcd_init(void)
45
+{
46
+	int i;
47
+
48
+	/* basic I/O setup */
49
+	ENABLE_LCD_POWER();
50
+	CONFIG_LCD_PINS();
51
+
52
+	// DISABLE_LCD_ENABLE();
53
+	ENABLE_LCD_ENABLE();
54
+
55
+	/* Put state machine in reset while it is configured */
56
+	LCD_SPI_UCBxCTL1 |= UCSWRST;
57
+
58
+	/* 
59
+	 * 3-pin, 8-bit SPI master, Clock polarity low
60
+	 * Clock phase set, least sig bit first
61
+	 * SMCLK is the clock source
62
+	 * set the clock prescaler
63
+	 */
64
+	LCD_SPI_UCBxCTL0 |= UCMST+ UCCKPH + UCSYNC;      
65
+
66
+	LCD_SPI_UCBxCTL1 |= UCSSEL_2;                    
67
+	LCD_SPI_UCBxBR0 = SPI_PRESCALE_L;               
68
+	LCD_SPI_UCBxBR1 = SPI_PRESCALE_H;               
69
+
70
+	/* remove reset */
71
+	LCD_SPI_UCBxCTL1 &= ~UCSWRST;
72
+
73
+	/* pre-fill the frame-buffer */
74
+	for (i=0; i<96; i++) {
75
+		lcd_buf[i].Row = i+1;
76
+		memfill(lcd_buf[i].Data, 0xff, 12);
77
+		// lcd_buf[i].Data[0] = i;
78
+		lcd_buf[i].Dummy = 0x00;
79
+	};
80
+}
81
+
82
+static void mw_lcd_write_line(const void *pData, unsigned char Size)
83
+{
84
+#ifndef xLCD_DMA
85
+	unsigned char Index;
86
+#endif
87
+
88
+	LCD_CS_ASSERT();
89
+  
90
+#ifdef xLCD_DMA
91
+	LcdDmaBusy = 1;
92
+
93
+	/* USCIB0 TXIFG is the DMA trigger
94
+	 * DMACTL1 controls dma2 and [dma3]
95
+	 */
96
+	DMACTL1 = DMA2TSEL_19;    
97
+    
98
+	DMA2SA = (unsigned int) pData;
99
+	DMA2DA = (unsigned int) &LCD_SPI_UCBxTXBUF;
100
+            
101
+	DMA2SZ = (unsigned int)Size;
102
+  
103
+	/* 
104
+	 * single transfer, increment source address, source byte and dest byte,
105
+	 * level sensitive, enable interrupt, clear interrupt flag
106
+	 */
107
+	DMA2CTL = DMADT_0 + DMASRCINCR_3 + DMASBDB + DMALEVEL + DMAIE;  
108
+  
109
+	/* start the transfer */
110
+	DMA2CTL |= DMAEN;
111
+  
112
+	while (LcdDmaBusy)
113
+		nop();
114
+#else
115
+//	debug_uart_tx("+wl1");
116
+	for ( Index = 0; Index < Size; Index++ ) {
117
+		LCD_SPI_UCBxTXBUF = ((unsigned char *)pData)[Index];
118
+//		debug_uart_tx(".");
119
+		while (!(LCD_SPI_UCBxIFG & UCTXIFG)) {
120
+//			debug_uart_tx("+");
121
+			nop();
122
+		}
123
+	}
124
+//	debug_uart_tx("\n+wl2\n");
125
+#endif
126
+    
127
+	/* wait for shift to complete ( ~3 us ) */
128
+	while (LCD_SPI_UCBxSTAT & 0x01) {
129
+		nop();
130
+//		debug_uart_tx(".");
131
+	};
132
+
133
+	/* now the chip select can be deasserted */
134
+	LCD_CS_DEASSERT();
135
+//	debug_uart_tx("\n-wl\n");
136
+}
137
+
138
+
139
+void mw_lcd_static_mode(void)
140
+{
141
+	mw_lcd_write_line(LCD_STATIC_COMMAND, LCD_STATIC_CMD_SIZE);   
142
+}
143
+
144
+void mw_lcd_clear(void)
145
+{
146
+	unsigned char i;
147
+
148
+	mw_lcd_write_line(LCD_CLEAR_COMMAND, LCD_CLEAR_CMD_SIZE);
149
+
150
+	/* pre-fill the frame-buffer */
151
+	for (i=0; i<96; i++) {
152
+		memfill(lcd_buf[i].Data, 0xff, 12);
153
+	};
154
+}
155
+
156
+void mw_lcd_clear_fb(void)
157
+{
158
+	unsigned char i;
159
+
160
+	/* pre-fill the frame-buffer */
161
+	for (i=0; i<96; i++) {
162
+#if LCD_BLACK == 0
163
+		memfill(lcd_buf[i].Data, 0xff, 12);
164
+#else
165
+		memfill(lcd_buf[i].Data, 0x00, 12);
166
+#endif
167
+	};
168
+}
169
+
170
+#pragma vector=DMA_VECTOR
171
+__interrupt void DMA_ISR (void)
172
+{
173
+	switch (DMAIV) {
174
+	case 0:
175
+		DMA0CTL &= ~DMAEN;	// disable
176
+		DMA0CTL &= ~DMAIFG;	// clear IRQ flag
177
+		debug_uart_tx("DMA0 IRQ\n");
178
+		break;
179
+	case 2:
180
+		debug_uart_tx("DMA1 IRQ\n");
181
+		break;
182
+	case 4:
183
+		debug_uart_tx("DMA2b IRQ\n");
184
+		break;
185
+	case 6:
186
+		DMA2CTL &= ~DMAEN;	// disable
187
+		DMA2CTL &= ~DMAIFG;	// clear IRQ flag
188
+#ifdef LCD_DMA
189
+		LcdDmaBusy = 0;
190
+#endif
191
+		//LED7_TOGGLE();
192
+		// debug_uart_tx("DMA2 IRQ\n");
193
+		break;
194
+	}
195
+}
196
+
197
+/* writes the complete internal framebuffer to the LCD */
198
+void mw_lcd_update_screen(void)
199
+{
200
+#ifndef LCD_DMA
201
+	unsigned int i,j;
202
+#endif
203
+
204
+//	debug_uart_tx("uscr1\n");
205
+
206
+	LCD_CS_ASSERT();
207
+
208
+	/* send WRITE command */
209
+	LCD_SPI_UCBxTXBUF = LCD_WRITE_CMD;
210
+	while (!(LCD_SPI_UCBxIFG & UCTXIFG))
211
+		nop();
212
+
213
+//	debug_uart_tx("uscr2\n");
214
+
215
+#ifdef LCD_DMA
216
+	LcdDmaBusy = 1;
217
+  
218
+	/* USCIB0 TXIFG is the DMA trigger
219
+	 * DMACTL1 controls dma2 and [dma3]
220
+	 */
221
+	DMACTL1 = DMA2TSEL_19;    
222
+
223
+	DMA2SA = (unsigned int) lcd_buf;
224
+	DMA2DA = (unsigned int) &LCD_SPI_UCBxTXBUF;
225
+            
226
+	DMA2SZ = 96 * sizeof(tLcdLine);
227
+  
228
+	/* 
229
+	 * single transfer, increment source address, source byte and dest byte,
230
+	 * level sensitive, enable interrupt, clear interrupt flag
231
+	 */
232
+	DMA2CTL = DMADT_0 + DMASRCINCR_3 + DMASBDB + DMALEVEL + DMAIE;  
233
+  
234
+	/* start the transfer */
235
+	DMA2CTL |= DMAEN;
236
+
237
+//	debug_uart_tx("uscr3\n");
238
+
239
+	// LED7_OFF();
240
+	while (LcdDmaBusy)
241
+		nop();
242
+
243
+//	debug_uart_tx("uscr4\n");
244
+#else
245
+	for (i=0; i<96; i++) {
246
+		for ( j = 0; j < sizeof(tLcdLine); j++ ) {
247
+			LCD_SPI_UCBxTXBUF = ((unsigned char *)(&lcd_buf[i]))[j];
248
+			while (!(LCD_SPI_UCBxIFG & UCTXIFG))
249
+				nop();
250
+		}
251
+	}
252
+#endif
253
+
254
+	/* send final trailer byte */
255
+	LCD_SPI_UCBxTXBUF = 0x00;
256
+	while (!(LCD_SPI_UCBxIFG & UCTXIFG))
257
+		nop();
258
+
259
+//	debug_uart_tx("uscr5\n");
260
+	/* wait for shift to complete ( ~3 us ) */
261
+	while (LCD_SPI_UCBxSTAT & 0x01)
262
+		nop();
263
+
264
+//	debug_uart_tx("uscr6\n");
265
+	LCD_CS_DEASSERT();
266
+
267
+	mw_lcd_static_mode();
268
+}
269
+
270
+void mw_lcd_draw_pixel(unsigned char x, unsigned char y, unsigned char color)
271
+{
272
+	switch (color) {
273
+		case 1:
274
+			lcd_buf[y].Data[x/8] |= 1 << (x % 8);
275
+			break;
276
+		case 0:
277
+			lcd_buf[y].Data[x/8] &= ~(1 << (x % 8));
278
+			break;
279
+		case 2:
280
+			lcd_buf[y].Data[x/8] ^= 1 << (x % 8);
281
+			break;
282
+	}
283
+}
284
+