Allow TABS in config
[clinton/Smoothieware.git] / src / modules / utils / panel / panels / Smoothiepanel.cpp
CommitLineData
3dc1c2aa 1/*
1c2b594a
L
2This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
3Smoothie 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 3 of the License, or (at your option) any later version.
4Smoothie 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.
3dc1c2aa 5You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>.
1c2b594a
L
6*/
7#include "Smoothiepanel.h"
8#include "smoothiepanel/LCDBang.h"
9
ab4abea9 10#include "smoothiepanel/Colors.h"
61134a65
JM
11#include "Config.h"
12#include "checksumm.h"
ab4abea9 13
3dc1c2aa
JM
14// commands
15#define LCD_CLEARDISPLAY 0x01
16#define LCD_RETURNHOME 0x02
17#define LCD_ENTRYMODESET 0x04
18#define LCD_DISPLAYCONTROL 0x08
19#define LCD_CURSORSHIFT 0x10
20#define LCD_FUNCTIONSET 0x20
21#define LCD_SETCGRAMADDR 0x40
22#define LCD_SETDDRAMADDR 0x80
23
24// flags for display entry mode
25#define LCD_ENTRYRIGHT 0x00
26#define LCD_ENTRYLEFT 0x02
27#define LCD_ENTRYSHIFTINCREMENT 0x01
28#define LCD_ENTRYSHIFTDECREMENT 0x00
29
30// flags for display on/off control
31#define LCD_DISPLAYON 0x04
32#define LCD_DISPLAYOFF 0x00
33#define LCD_CURSORON 0x02
34#define LCD_CURSOROFF 0x00
35#define LCD_BLINKON 0x01
36#define LCD_BLINKOFF 0x00
37
38// flags for display/cursor shift
39#define LCD_DISPLAYMOVE 0x08
40#define LCD_CURSORMOVE 0x00
41#define LCD_MOVERIGHT 0x04
42#define LCD_MOVELEFT 0x00
43
44// flags for function set
45#define LCD_8BITMODE 0x10
46#define LCD_4BITMODE 0x00
47#define LCD_2LINE 0x08
48#define LCD_1LINE 0x00
49#define LCD_5x10DOTS 0x04
50#define LCD_5x8DOTS 0x00
51
52// flags for backlight control
53#define LCD_BACKLIGHT 0x08
54#define LCD_NOBACKLIGHT 0x00
55
56
1c2b594a
L
57#define LCD_WRITE 0x00
58#define LCD_READ 0x01
59#define LCD_ACK 0x01
60
61Smoothiepanel::Smoothiepanel() {
62 // Default values
63 this->backlightval = 0x00;
64 this->displaycontrol = 0x00;
65 this->displayfunction = LCD_4BITMODE | LCD_2LINE | LCD_5x8DOTS; // in case they forget to call begin() at least we have somethin
66 this->displaymode = 0x00;
67 this->_numlines = 4;
68
08ce8807
L
69 this->wii_connected = false;
70
1c2b594a
L
71 // I2C com
72 int i2c_pins = THEKERNEL->config->value(panel_checksum, i2c_pins_checksum)->by_default(3)->as_number();
73 if(i2c_pins == 0){
74 this->i2c = new mbed::I2C(P0_0, P0_1);
75 }else if(i2c_pins == 1){
76 this->i2c = new mbed::I2C(P0_10, P0_11);
77 }else if(i2c_pins == 2){
78 this->i2c = new mbed::I2C(P0_19, P0_20);
79 }else{ // 3, default
80 this->i2c = new mbed::I2C(P0_27, P0_28);
81 }
08ce8807 82 this->wii = new Wiichuck(this->i2c);
1c2b594a
L
83
84 this->i2c_address = (char)THEKERNEL->config->value(panel_checksum, i2c_address_checksum)->by_default(0)->as_number();
85 this->i2c_address = (this->i2c_address & 0x07) << 1;
86 this->i2c_frequency = THEKERNEL->config->value(panel_checksum, i2c_frequency_checksum)->by_default(20000)->as_number();
87 i2c->frequency(this->i2c_frequency);
88 this->lcd_contrast = THEKERNEL->config->value(panel_checksum, lcd_contrast_checksum)->by_default(0)->as_number();
ab4abea9
L
89 this->backlight_red = THEKERNEL->config->value(panel_checksum, lcd_led_checksum)->by_default(255)->as_number();
90 this->backlight_red = THEKERNEL->config->value(panel_checksum, lcd_led_red_checksum)->by_default(this->backlight_red)->as_number();
91 this->backlight_green = THEKERNEL->config->value(panel_checksum, lcd_led_green_checksum)->by_default(255)->as_number();
92 this->backlight_blue = THEKERNEL->config->value(panel_checksum, lcd_led_blue_checksum)->by_default(255)->as_number();
93 this->playledval = THEKERNEL->config->value(panel_checksum, play_led_brightness_checksum)->by_default(255)->as_number();
94 this->backledval = THEKERNEL->config->value(panel_checksum, back_led_brightness_checksum)->by_default(255)->as_number();
1c2b594a
L
95
96// this->interrupt_pin.from_string(THEKERNEL->config->value(panel_checksum, i2c_interrupt_pin_checksum)->by_default("nc")->as_string())->as_input();
4933a6ed
L
97 this->encoder_a_pin.from_string(THEKERNEL->config->value( panel_checksum, encoder_a_pin_checksum)->by_default("nc")->as_string())->as_input();
98 this->encoder_b_pin.from_string(THEKERNEL->config->value( panel_checksum, encoder_b_pin_checksum)->by_default("nc")->as_string())->as_input();
ab4abea9 99 this->encoder_hue = THEKERNEL->config->value(panel_checksum, encoder_led_hue_checksum)->by_default(220)->as_number();
1c2b594a
L
100}
101
102Smoothiepanel::~Smoothiepanel() {
08ce8807 103 delete this->wii;
1c2b594a
L
104 delete this->i2c;
105}
106
ab4abea9 107void pca9634_init(I2C i2c, int address){
1c2b594a
L
108 const int leds = PCA9634_ADDRESS | (address & 0x0E);
109 char cmd[2];
110
111 // initialize led controller
112 cmd[0] = 0x00;
113 cmd[1] = 0x00;
114 i2c.write(leds, cmd, 2);
115 cmd[0] = 0x01;
116 cmd[1] = 0x02;
117 i2c.write(leds, cmd, 2);
118 cmd[0] = 0x0C;
119 cmd[1] = 0xAA;
120 i2c.write(leds, cmd, 2);
121 cmd[0] = 0x0D;
122 i2c.write(leds, cmd, 2);
1c2b594a
L
123}
124
073389cb
L
125void pca9634_setLed(I2C *i2c, int address, char led, char val){
126 const int leds = PCA9634_ADDRESS | (address & 0x0E);
127 char cmd[2];
128
129 cmd[0] = led; // lcd blue
130 cmd[1] = val;
131 i2c->write(leds, cmd, 2);
132}
133
52500e58
L
134void pca9505_write(I2C *i2c, int address, char reg, char val){
135 const int expander = PCA9505_ADDRESS | (address & 0x0E);
136 char cmd[2];
137
138 cmd[0] = reg;
139 cmd[1] = val;
140 i2c->write(expander, cmd, 2);
141}
142
143char pca9505_read(I2C *i2c, int address, char reg){
144 const int expander = PCA9505_ADDRESS | (address & 0x0E);
145 char cmd[1];
146
147 cmd[0] = 0x04;
148 i2c->write(expander, cmd, 1, false);
149 i2c->read(expander, cmd, 1);
150 return cmd[0];
151}
152
1c2b594a
L
153void Smoothiepanel::init(){
154 // init lcd and buzzer
155 lcdbang_init(*this->i2c);
4933a6ed 156// lcdbang_print(*this->i2c, " Smoothiepanel Beta - design by Logxen -");
1c2b594a
L
157 lcdbang_contrast(*this->i2c, this->lcd_contrast);
158
ab4abea9
L
159 pca9634_init(*this->i2c, this->i2c_address);
160 setEncoderByHue(this->encoder_hue);
161 setBacklightColor(this->backlight_red, this->backlight_green, this->backlight_blue);
162 setPlayLED(this->playledval);
163 setBackLED(this->backledval);
52500e58
L
164
165 pca9505_write(this->i2c, this->i2c_address, 0x18, 0xAA); // enable leds for button/led wing on port0
166 pca9505_write(this->i2c, this->i2c_address, 0x08, 0x01); // enable leds for button/led wing on port0
4933a6ed
L
167// wait_us(3000);
168// this->clear();
1c2b594a
L
169}
170
073389cb
L
171void Smoothiepanel::setLed(int led, bool on){
172 // LED turns on when bit is cleared
52500e58 173 char saved = pca9505_read(this->i2c, this->i2c_address, 0x08);
073389cb
L
174 if(on) {
175 switch(led) {
52500e58
L
176 case LED_FAN_ON: pca9505_write(this->i2c, this->i2c_address, 0x08, saved | 0x40); break; // on
177 case LED_HOTEND_ON: pca9505_write(this->i2c, this->i2c_address, 0x08, saved | 0x10); break; // on
178 case LED_BED_ON: pca9505_write(this->i2c, this->i2c_address, 0x08, saved | 0x04); break; // on
073389cb
L
179 }
180 }else{
181 switch(led) {
52500e58
L
182 case LED_FAN_ON: pca9505_write(this->i2c, this->i2c_address, 0x08, saved & ~0x40); break; // off
183 case LED_HOTEND_ON: pca9505_write(this->i2c, this->i2c_address, 0x08, saved & ~0x10); break; // off
184 case LED_BED_ON: pca9505_write(this->i2c, this->i2c_address, 0x08, saved & ~0x04); break; // off
073389cb
L
185 }
186 }
187}
188
189void Smoothiepanel::setLedBrightness(int led, int val){
190 switch(led){
191// case LED_FAN_ON: this->backlight_green = val; break; // on
52500e58
L
192// case LED_HOTEND_ON: this->backlight_red = val; break; // on
193// case LED_BED_ON: this->backlight_blue = val; break; // on
073389cb
L
194 }
195}
196
3dc1c2aa 197// cycle the buzzer pin at a certain frequency (hz) for a certain duration (ms)
1c2b594a
L
198void Smoothiepanel::buzz(long duration, uint16_t freq) {
199 const int expander = PCA9505_ADDRESS | this->i2c_address;
200 char cmd[2];
4933a6ed
L
201 char saved;
202
203 // save register state
204 cmd[0] = 0x04;
205 this->i2c->write(expander, cmd, 1, false);
206 this->i2c->read(expander, cmd, 1);
207 saved = cmd[0];
1c2b594a
L
208
209 // buzz
210 cmd[0] = 0x0C;
4933a6ed 211 cmd[1] = saved & 0xFE;
1c2b594a
L
212 this->i2c->write(expander, cmd, 2);
213 wait_ms(duration); // TODO: Make this not hold up the whole system
4933a6ed 214 cmd[1] = saved;
1c2b594a
L
215 this->i2c->write(expander, cmd, 2);
216}
217
218uint8_t Smoothiepanel::readButtons(void) {
219 const int expander = PCA9505_ADDRESS | this->i2c_address;
220 uint8_t button_bits = 0x00;
221 char cmd[1];
222
223 cmd[0] = 0x03;
224 this->i2c->write(expander, cmd, 1, false);
225 this->i2c->read(expander, cmd, 1);
4933a6ed 226 //cmd[0] = ~cmd[0];
08ce8807 227 if((cmd[0] & 0x10) > 0) button_bits |= BUTTON_SELECT; // encoder click
4933a6ed 228 if((cmd[0] & 0x02) > 0) button_bits |= BUTTON_LEFT; // back button
52500e58 229 if((cmd[0] & 0x01) > 0) button_bits |= BUTTON_PAUSE; // play button
08ce8807
L
230 if((cmd[0] & 0x20) > 0){ // wii accessory connected
231 if(!this->wii_connected){
232 this->wii->init_device();
233 if(this->wii->device_type >= 0){
234 this->wii_connected = true;
235 wait_ms(100);
236 }
237 }
238 if(this->wii_connected){
239 this->wii->poll_device();
240 if(this->wii->data_ready){
241 if(this->wii->device_type == DEVICE_NUNCHUCK){
242 if(this->wii->SY > 192) button_bits |= BUTTON_UP;
243 else if(this->wii->SY < 64) button_bits |= BUTTON_DOWN;
244 if(this->wii->SX > 192) button_bits |= BUTTON_RIGHT;
245 else if(this->wii->SX < 64) button_bits |= BUTTON_LEFT;
246 if(!this->wii->BC) button_bits |= BUTTON_SELECT;
247 if(!this->wii->BZ) button_bits |= BUTTON_LEFT;
248 }else if(this->wii->device_type == DEVICE_CLASSIC){
249 if(this->wii->LY > 192) button_bits |= BUTTON_UP;
250 else if(this->wii->LY < 64) button_bits |= BUTTON_DOWN;
251 if(this->wii->LX > 192) button_bits |= BUTTON_RIGHT;
252 else if(this->wii->LX < 64) button_bits |= BUTTON_LEFT;
253 if(!this->wii->BDU) button_bits |= BUTTON_UP;
254 else if(!this->wii->BDD) button_bits |= BUTTON_DOWN;
255 if(!this->wii->BDL) button_bits |= BUTTON_LEFT;
256 else if(!this->wii->BDR) button_bits |= BUTTON_RIGHT;
257 if(!this->wii->BA) button_bits |= BUTTON_SELECT;
258 if(!this->wii->BB) button_bits |= BUTTON_LEFT;
259 }
260 }else this->wii_connected = false;
261 }
262 }else this->wii_connected = false;
1c2b594a 263
ab4abea9
L
264 // update the encoder color
265 if(this->encoder_changed){
266 if(this->encoder_hue > 360) this->encoder_hue -= 360;
267 else if(this->encoder_hue < 0) this->encoder_hue += 360;
268 this->encoder_changed = false;
269
270 setEncoderByHue(this->encoder_hue);
271 }
272
1c2b594a
L
273 return button_bits;
274}
275
276int Smoothiepanel::readEncoderDelta() {
4933a6ed
L
277 static int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
278 static uint8_t old_AB = 0;
ab4abea9 279 int8_t state;
4933a6ed 280 old_AB <<= 2; //remember previous state
3dc1c2aa 281 old_AB |= ( this->encoder_a_pin.get() + ( this->encoder_b_pin.get() * 2 ) ); //add current state
ab4abea9
L
282 state = enc_states[(old_AB&0x0f)];
283 if(state != 0){
284 this->encoder_hue += state;
285 this->encoder_changed = true;
286 }
287 return state;
1c2b594a
L
288}
289
290void Smoothiepanel::clear()
291{
292 command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero
4933a6ed
L
293//#ifndef USE_FASTMODE
294// wait_ms(50); // this command takes a long time!
295//#endif
1c2b594a
L
296}
297
298void Smoothiepanel::home()
299{
300 command(LCD_RETURNHOME); // set cursor position to zero
4933a6ed
L
301//#ifndef USE_FASTMODE
302// wait_us(2000); // this command takes a long time!
303//#endif
1c2b594a
L
304}
305
306void Smoothiepanel::setCursor(uint8_t col, uint8_t row)
307{
308 int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
309 if ( row > _numlines ) row = _numlines - 1; // we count rows starting w/0
310 command(LCD_SETDDRAMADDR | (col + row_offsets[row]));
311}
312
313// Turn the display on/off (quickly)
314void Smoothiepanel::noDisplay() {
315 displaycontrol &= ~LCD_DISPLAYON;
316 command(LCD_DISPLAYCONTROL | displaycontrol);
317}
318
319void Smoothiepanel::display() {
320 displaycontrol |= LCD_DISPLAYON;
321 command(LCD_DISPLAYCONTROL | displaycontrol);
322}
323
324// Turns the underline cursor on/off
325void Smoothiepanel::noCursor() {
326 displaycontrol &= ~LCD_CURSORON;
327 command(LCD_DISPLAYCONTROL | displaycontrol);
328}
329void Smoothiepanel::cursor() {
330 displaycontrol |= LCD_CURSORON;
331 command(LCD_DISPLAYCONTROL | displaycontrol);
332}
333
334// Turn on and off the blinking cursor
335void Smoothiepanel::noBlink() {
336 displaycontrol &= ~LCD_BLINKON;
337 command(LCD_DISPLAYCONTROL | displaycontrol);
338}
339void Smoothiepanel::blink() {
340 displaycontrol |= LCD_BLINKON;
341 command(LCD_DISPLAYCONTROL | displaycontrol);
342}
343
344// These commands scroll the display without changing the RAM
345void Smoothiepanel::scrollDisplayLeft(void) {
346 command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
347}
348void Smoothiepanel::scrollDisplayRight(void) {
349 command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
350}
351
352// This is for text that flows Left to Right
353void Smoothiepanel::leftToRight(void) {
354 displaymode |= LCD_ENTRYLEFT;
355 command(LCD_ENTRYMODESET | displaymode);
356}
357
358// This is for text that flows Right to Left
359void Smoothiepanel::rightToLeft(void) {
360 displaymode &= ~LCD_ENTRYLEFT;
361 command(LCD_ENTRYMODESET | displaymode);
362}
363
364// This will 'right justify' text from the cursor
365void Smoothiepanel::autoscroll(void) {
366 displaymode |= LCD_ENTRYSHIFTINCREMENT;
367 command(LCD_ENTRYMODESET | displaymode);
368}
369
370// This will 'left justify' text from the cursor
371void Smoothiepanel::noAutoscroll(void) {
372 displaymode &= ~LCD_ENTRYSHIFTINCREMENT;
373 command(LCD_ENTRYMODESET | displaymode);
374}
375
376void Smoothiepanel::command(uint8_t value) {
377 lcdbang_write(*this->i2c, value>>4, true);
378 lcdbang_write(*this->i2c, value, true);
379}
380
f54d25cb
JM
381void Smoothiepanel::write(const char* line, int len) {
382 for (int i = 0; i < len; ++i) {
383 lcdbang_write(*this->i2c, *line++);
384 }
1c2b594a
L
385}
386
387// Allows to set the backlight, if the LCD backpack is used
388void Smoothiepanel::setBacklight(uint8_t status) {
389/* // LED turns on when bit is cleared
390 _backlightBits = M17_BIT_LB|M17_BIT_LG|M17_BIT_LR; // all off
391 if (status & LED_RED) _backlightBits &= ~M17_BIT_LR; // red on
392 if (status & LED_GREEN) _backlightBits &= ~M17_BIT_LG; // green on
393 if (status & LED_BLUE) _backlightBits &= ~M17_BIT_LB; // blue on
394
395 burstBits16(_backlightBits);
396*/
397}
ab4abea9
L
398
399void Smoothiepanel::setBacklightColor(uint8_t r, uint8_t g, uint8_t b) {
400 const int leds = PCA9634_ADDRESS | this->i2c_address;
401 char cmd[2];
402
403 cmd[0] = 0x07; // lcd blue
404 cmd[1] = b;
405 this->i2c->write(leds, cmd, 2);
406 cmd[0] = 0x08; // lcd green
407 cmd[1] = g;
408 this->i2c->write(leds, cmd, 2);
409 cmd[0] = 0x09; // lcd red
410 cmd[1] = r;
411 this->i2c->write(leds, cmd, 2);
412}
413
414void Smoothiepanel::setBacklightByHue(int h) {
415 float r, g, b;
416 HSVtoRGB(&r, &g, &b, h, 1.0, 1.0);
417 setBacklightColor(r*0xFF, g*0xFF, b*0xFF);
418}
419
420void Smoothiepanel::setEncoderLED(uint8_t r, uint8_t g, uint8_t b) {
421 const int leds = PCA9634_ADDRESS | this->i2c_address;
422 char cmd[2];
423
424 cmd[0] = 0x04; // encoder red
425 cmd[1] = r;
426 this->i2c->write(leds, cmd, 2);
427 cmd[0] = 0x05; // encoder green
428 cmd[1] = g;
429 this->i2c->write(leds, cmd, 2);
430 cmd[0] = 0x06; // encoder blue
431 cmd[1] = b;
432 this->i2c->write(leds, cmd, 2);
433}
434
435void Smoothiepanel::setEncoderByHue(int h) {
436 float r, g, b;
437 HSVtoRGB(&r, &g, &b, h, 1.0, 1.0);
438 setEncoderLED(r*0xFF, g*0xFF, b*0xFF);
439}
440
441void Smoothiepanel::setPlayLED(uint8_t v) {
442 const int leds = PCA9634_ADDRESS | this->i2c_address;
443 char cmd[2];
444
445 cmd[0] = 0x02; // play
446 cmd[1] = v;
447 this->i2c->write(leds, cmd, 2);
448}
449
450void Smoothiepanel::setBackLED(uint8_t v) {
451 const int leds = PCA9634_ADDRESS | this->i2c_address;
452 char cmd[2];
453
454 cmd[0] = 0x03; // back
455 cmd[1] = v;
456 this->i2c->write(leds, cmd, 2);
457}
458
1c2b594a
L
459/*
460// write either command or data, burst it to the expander over I2C.
461void Smoothiepanel::send(uint8_t value, uint8_t mode) {
462#ifdef USE_FASTMODE
463 // polls for ready. not sure on I2C this is any faster
3dc1c2aa 464
1c2b594a
L
465 // set Data pins as input
466 char data[2];
467 data[0]= MCP23017_IODIRB;
468 data[1]= 0x1E;
469 i2c->write(this->i2c_address, data, 2);
470 uint8_t b= _backlightBits >> 8;
3dc1c2aa 471 burstBits8b((M17_BIT_RW>>8)|b); // RW hi,RS lo
1c2b594a
L
472 char busy;
473 data[0] = MCP23017_GPIOB;
474 do {
475 burstBits8b(((M17_BIT_RW|M17_BIT_EN)>>8)|b); // EN hi
476 i2c->write(this->i2c_address, data, 1);
477 i2c->read(this->i2c_address, &busy, 1); // Read D7
478 burstBits8b((M17_BIT_RW>>8)|b); // EN lo
479 burstBits8b(((M17_BIT_RW|M17_BIT_EN)>>8)|b); // EN hi
480 burstBits8b((M17_BIT_RW>>8)|b); // EN lo
481 } while ((busy&(M17_BIT_D7>>8)) != 0);
482
483 // reset data bits as output
484 data[0]= MCP23017_IODIRB;
485 data[1]= 0x00;
486 i2c->write(this->i2c_address, data, 2);
3dc1c2aa 487 burstBits8b(b); // RW lo
1c2b594a
L
488
489#else
490// wait_us(320);
491#endif
3dc1c2aa 492
1c2b594a
L
493 // BURST SPEED, OH MY GOD
494 // the (now High Speed!) I/O expander pinout
3dc1c2aa
JM
495 // B7 B6 B5 B4 B3 B2 B1 B0 A7 A6 A5 A4 A3 A2 A1 A0 - MCP23017
496 // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
497 // RS RW EN D4 D5 D6 D7 B G R B4 B3 B2 B1 B0
1c2b594a
L
498
499 // n.b. RW bit stays LOW to write
500 uint8_t buf = _backlightBits >> 8;
501 // send high 4 bits
502 if (value & 0x10) buf |= M17_BIT_D4 >> 8;
503 if (value & 0x20) buf |= M17_BIT_D5 >> 8;
504 if (value & 0x40) buf |= M17_BIT_D6 >> 8;
505 if (value & 0x80) buf |= M17_BIT_D7 >> 8;
3dc1c2aa 506
1c2b594a
L
507 if (mode) buf |= (M17_BIT_RS|M17_BIT_EN) >> 8; // RS+EN
508 else buf |= M17_BIT_EN >> 8; // EN
509
510 burstBits8b(buf);
511
512 // resend w/ EN turned off
513 buf &= ~(M17_BIT_EN >> 8);
514 burstBits8b(buf);
515
516 // send low 4 bits
517 buf = _backlightBits >> 8;
518 // send high 4 bits
519 if (value & 0x01) buf |= M17_BIT_D4 >> 8;
520 if (value & 0x02) buf |= M17_BIT_D5 >> 8;
521 if (value & 0x04) buf |= M17_BIT_D6 >> 8;
522 if (value & 0x08) buf |= M17_BIT_D7 >> 8;
3dc1c2aa 523
1c2b594a
L
524 if (mode) buf |= (M17_BIT_RS|M17_BIT_EN) >> 8; // RS+EN
525 else buf |= M17_BIT_EN >> 8; // EN
526
527 burstBits8b(buf);
528
529 // resend w/ EN turned off
530 buf &= ~(M17_BIT_EN >> 8);
531 burstBits8b(buf);
532}
533
534// We pause the system
535uint32_t Smoothiepanel::on_pause_release(uint32_t dummy){
536 if(!paused) {
537 THEKERNEL->pauser->take();
538 paused= true;
539 }else{
540 THEKERNEL->pauser->release();
541 paused= false;
542 }
543 return 0;
544}
545*/
546