Fork of Smoothie to port to mbed non-LPC targets.

Dependencies:   mbed

Fork of Smoothie by Stéphane Cachat

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Smoothiepanel.cpp Source File

Smoothiepanel.cpp

00001 /*
00002 This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
00003 Smoothie 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.
00004 Smoothie 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.
00005 You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>.
00006 */
00007 #include "Smoothiepanel.h"
00008 #include "smoothiepanel/LCDBang.h"
00009 
00010 #include "smoothiepanel/Colors.h"
00011 
00012 // commands
00013 #define LCD_CLEARDISPLAY 0x01
00014 #define LCD_RETURNHOME 0x02
00015 #define LCD_ENTRYMODESET 0x04
00016 #define LCD_DISPLAYCONTROL 0x08
00017 #define LCD_CURSORSHIFT 0x10
00018 #define LCD_FUNCTIONSET 0x20
00019 #define LCD_SETCGRAMADDR 0x40
00020 #define LCD_SETDDRAMADDR 0x80
00021 
00022 // flags for display entry mode
00023 #define LCD_ENTRYRIGHT 0x00
00024 #define LCD_ENTRYLEFT 0x02
00025 #define LCD_ENTRYSHIFTINCREMENT 0x01
00026 #define LCD_ENTRYSHIFTDECREMENT 0x00
00027 
00028 // flags for display on/off control
00029 #define LCD_DISPLAYON 0x04
00030 #define LCD_DISPLAYOFF 0x00
00031 #define LCD_CURSORON 0x02
00032 #define LCD_CURSOROFF 0x00
00033 #define LCD_BLINKON 0x01
00034 #define LCD_BLINKOFF 0x00
00035 
00036 // flags for display/cursor shift
00037 #define LCD_DISPLAYMOVE 0x08
00038 #define LCD_CURSORMOVE 0x00
00039 #define LCD_MOVERIGHT 0x04
00040 #define LCD_MOVELEFT 0x00
00041 
00042 // flags for function set
00043 #define LCD_8BITMODE 0x10
00044 #define LCD_4BITMODE 0x00
00045 #define LCD_2LINE 0x08
00046 #define LCD_1LINE 0x00
00047 #define LCD_5x10DOTS 0x04
00048 #define LCD_5x8DOTS 0x00
00049 
00050 // flags for backlight control
00051 #define LCD_BACKLIGHT 0x08
00052 #define LCD_NOBACKLIGHT 0x00
00053 
00054 
00055 #define LCD_WRITE       0x00
00056 #define LCD_READ        0x01
00057 #define LCD_ACK         0x01
00058 
00059 Smoothiepanel::Smoothiepanel() {
00060     // Default values
00061     this->backlightval     = 0x00;
00062     this->displaycontrol   = 0x00;
00063     this->displayfunction  = LCD_4BITMODE | LCD_2LINE | LCD_5x8DOTS; // in case they forget to call begin() at least we have somethin
00064     this->displaymode      = 0x00;
00065     this->_numlines        = 4;
00066 
00067     this->wii_connected    = false;
00068 
00069     // I2C com
00070     int i2c_pins = THEKERNEL->config->value(panel_checksum, i2c_pins_checksum)->by_default(3)->as_number();
00071     if(i2c_pins == 0){
00072         this->i2c = new mbed::I2C(P0_0, P0_1);
00073     }else if(i2c_pins == 1){
00074         this->i2c = new mbed::I2C(P0_10, P0_11);
00075     }else if(i2c_pins == 2){
00076         this->i2c = new mbed::I2C(P0_19, P0_20);
00077     }else{ // 3, default
00078         this->i2c = new mbed::I2C(P0_27, P0_28);
00079     }
00080     this->wii = new Wiichuck(this->i2c);
00081 
00082     this->i2c_address   = (char)THEKERNEL->config->value(panel_checksum, i2c_address_checksum)->by_default(0)->as_number();
00083     this->i2c_address = (this->i2c_address & 0x07) << 1;
00084     this->i2c_frequency = THEKERNEL->config->value(panel_checksum, i2c_frequency_checksum)->by_default(20000)->as_number();
00085     i2c->frequency(this->i2c_frequency);
00086     this->lcd_contrast  = THEKERNEL->config->value(panel_checksum, lcd_contrast_checksum)->by_default(0)->as_number();
00087     this->backlight_red   = THEKERNEL->config->value(panel_checksum, lcd_led_checksum)->by_default(255)->as_number();
00088     this->backlight_red   = THEKERNEL->config->value(panel_checksum, lcd_led_red_checksum)->by_default(this->backlight_red)->as_number();
00089     this->backlight_green = THEKERNEL->config->value(panel_checksum, lcd_led_green_checksum)->by_default(255)->as_number();
00090     this->backlight_blue  = THEKERNEL->config->value(panel_checksum, lcd_led_blue_checksum)->by_default(255)->as_number();
00091     this->playledval      = THEKERNEL->config->value(panel_checksum, play_led_brightness_checksum)->by_default(255)->as_number();
00092     this->backledval      = THEKERNEL->config->value(panel_checksum, back_led_brightness_checksum)->by_default(255)->as_number();
00093 
00094 //  this->interrupt_pin.from_string(THEKERNEL->config->value(panel_checksum, i2c_interrupt_pin_checksum)->by_default("nc")->as_string())->as_input();
00095     this->encoder_a_pin.from_string(THEKERNEL->config->value( panel_checksum, encoder_a_pin_checksum)->by_default("nc")->as_string())->as_input();
00096     this->encoder_b_pin.from_string(THEKERNEL->config->value( panel_checksum, encoder_b_pin_checksum)->by_default("nc")->as_string())->as_input();
00097     this->encoder_hue   = THEKERNEL->config->value(panel_checksum, encoder_led_hue_checksum)->by_default(220)->as_number();
00098 }
00099 
00100 Smoothiepanel::~Smoothiepanel() {
00101     delete this->wii;
00102     delete this->i2c;
00103 }
00104 
00105 void pca9634_init(I2C i2c, int address){
00106     const int leds = PCA9634_ADDRESS | (address & 0x0E);
00107     char cmd[2];
00108 
00109     // initialize led controller
00110     cmd[0] = 0x00;
00111     cmd[1] = 0x00;
00112     i2c.write(leds, cmd, 2);
00113     cmd[0] = 0x01;
00114     cmd[1] = 0x02;
00115     i2c.write(leds, cmd, 2);
00116     cmd[0] = 0x0C;
00117     cmd[1] = 0xAA;
00118     i2c.write(leds, cmd, 2);
00119     cmd[0] = 0x0D;
00120     i2c.write(leds, cmd, 2);
00121 }
00122 
00123 void pca9634_setLed(I2C *i2c, int address, char led, char val){
00124     const int leds = PCA9634_ADDRESS | (address & 0x0E);
00125     char cmd[2];
00126 
00127     cmd[0] = led; // lcd blue
00128     cmd[1] = val;
00129     i2c->write(leds, cmd, 2);
00130 }
00131 
00132 void pca9505_write(I2C *i2c, int address, char reg, char val){
00133     const int expander = PCA9505_ADDRESS | (address & 0x0E);
00134     char cmd[2];
00135 
00136     cmd[0] = reg;
00137     cmd[1] = val;
00138     i2c->write(expander, cmd, 2);
00139 }
00140 
00141 char pca9505_read(I2C *i2c, int address, char reg){
00142     const int expander = PCA9505_ADDRESS | (address & 0x0E);
00143     char cmd[1];
00144 
00145     cmd[0] = 0x04;
00146     i2c->write(expander, cmd, 1, false);
00147     i2c->read(expander, cmd, 1);
00148     return cmd[0];
00149 }
00150 
00151 void Smoothiepanel::init(){
00152     // init lcd and buzzer
00153     lcdbang_init(*this->i2c);
00154 //    lcdbang_print(*this->i2c, " Smoothiepanel Beta - design by Logxen -");
00155     lcdbang_contrast(*this->i2c, this->lcd_contrast);
00156 
00157     pca9634_init(*this->i2c, this->i2c_address);
00158     setEncoderByHue(this->encoder_hue);
00159     setBacklightColor(this->backlight_red, this->backlight_green, this->backlight_blue);
00160     setPlayLED(this->playledval);
00161     setBackLED(this->backledval);
00162 
00163     pca9505_write(this->i2c, this->i2c_address, 0x18, 0xAA); // enable leds for button/led wing on port0
00164     pca9505_write(this->i2c, this->i2c_address, 0x08, 0x01); // enable leds for button/led wing on port0
00165 //    wait_us(3000);
00166 //    this->clear();
00167 }
00168 
00169 void Smoothiepanel::setLed(int led, bool on){
00170     // LED turns on when bit is cleared
00171     char saved = pca9505_read(this->i2c, this->i2c_address, 0x08);
00172     if(on) {
00173         switch(led) {
00174             case LED_FAN_ON: pca9505_write(this->i2c, this->i2c_address, 0x08, saved | 0x40); break; // on
00175             case LED_HOTEND_ON: pca9505_write(this->i2c, this->i2c_address, 0x08, saved | 0x10); break; // on
00176             case LED_BED_ON: pca9505_write(this->i2c, this->i2c_address, 0x08, saved | 0x04); break; // on
00177         }
00178     }else{
00179         switch(led) {
00180             case LED_FAN_ON: pca9505_write(this->i2c, this->i2c_address, 0x08, saved & ~0x40); break; // off
00181             case LED_HOTEND_ON: pca9505_write(this->i2c, this->i2c_address, 0x08, saved & ~0x10); break; // off
00182             case LED_BED_ON: pca9505_write(this->i2c, this->i2c_address, 0x08, saved & ~0x04); break; // off
00183         }
00184     }
00185 }
00186 
00187 void Smoothiepanel::setLedBrightness(int led, int val){
00188     switch(led){
00189 //        case LED_FAN_ON: this->backlight_green = val; break; // on
00190 //        case LED_HOTEND_ON: this->backlight_red = val; break; // on
00191 //        case LED_BED_ON: this->backlight_blue = val; break; // on
00192     }
00193 }
00194 
00195 // cycle the buzzer pin at a certain frequency (hz) for a certain duration (ms)
00196 void Smoothiepanel::buzz(long duration, uint16_t freq) {
00197     const int expander = PCA9505_ADDRESS | this->i2c_address;
00198     char cmd[2];
00199     char saved;
00200 
00201     // save register state
00202     cmd[0] = 0x04;
00203     this->i2c->write(expander, cmd, 1, false);
00204     this->i2c->read(expander, cmd, 1);
00205     saved = cmd[0];
00206 
00207     // buzz
00208     cmd[0] = 0x0C;
00209     cmd[1] = saved & 0xFE;
00210     this->i2c->write(expander, cmd, 2);
00211     wait_ms(duration); // TODO: Make this not hold up the whole system
00212     cmd[1] = saved;
00213     this->i2c->write(expander, cmd, 2);
00214 }
00215 
00216 uint8_t Smoothiepanel::readButtons(void) {
00217     const int expander = PCA9505_ADDRESS | this->i2c_address;
00218     uint8_t button_bits = 0x00;
00219     char cmd[1];
00220 
00221     cmd[0] = 0x03;
00222     this->i2c->write(expander, cmd, 1, false);
00223     this->i2c->read(expander, cmd, 1);
00224     //cmd[0] = ~cmd[0];
00225     if((cmd[0] & 0x10) > 0) button_bits |= BUTTON_SELECT; // encoder click
00226     if((cmd[0] & 0x02) > 0) button_bits |= BUTTON_LEFT; // back button
00227     if((cmd[0] & 0x01) > 0) button_bits |= BUTTON_PAUSE; // play button
00228     if((cmd[0] & 0x20) > 0){ // wii accessory connected
00229         if(!this->wii_connected){
00230             this->wii->init_device();
00231             if(this->wii->device_type >= 0){
00232                 this->wii_connected = true;
00233                 wait_ms(100);
00234             }
00235         }
00236         if(this->wii_connected){
00237             this->wii->poll_device();
00238             if(this->wii->data_ready){
00239                 if(this->wii->device_type == DEVICE_NUNCHUCK){
00240                     if(this->wii->SY > 192) button_bits |= BUTTON_UP;
00241                     else if(this->wii->SY < 64) button_bits |= BUTTON_DOWN;
00242                     if(this->wii->SX > 192) button_bits |= BUTTON_RIGHT;
00243                     else if(this->wii->SX < 64) button_bits |= BUTTON_LEFT;
00244                     if(!this->wii->BC) button_bits |= BUTTON_SELECT;
00245                     if(!this->wii->BZ) button_bits |= BUTTON_LEFT;
00246                 }else if(this->wii->device_type == DEVICE_CLASSIC){
00247                     if(this->wii->LY > 192) button_bits |= BUTTON_UP;
00248                     else if(this->wii->LY < 64) button_bits |= BUTTON_DOWN;
00249                     if(this->wii->LX > 192) button_bits |= BUTTON_RIGHT;
00250                     else if(this->wii->LX < 64) button_bits |= BUTTON_LEFT;
00251                     if(!this->wii->BDU) button_bits |= BUTTON_UP;
00252                     else if(!this->wii->BDD) button_bits |= BUTTON_DOWN;
00253                     if(!this->wii->BDL) button_bits |= BUTTON_LEFT;
00254                     else if(!this->wii->BDR) button_bits |= BUTTON_RIGHT;
00255                     if(!this->wii->BA) button_bits |= BUTTON_SELECT;
00256                     if(!this->wii->BB) button_bits |= BUTTON_LEFT;
00257                 }
00258             }else this->wii_connected = false;
00259         }
00260     }else this->wii_connected = false;
00261 
00262     // update the encoder color
00263     if(this->encoder_changed){
00264         if(this->encoder_hue > 360) this->encoder_hue -= 360;
00265         else if(this->encoder_hue < 0) this->encoder_hue += 360;
00266         this->encoder_changed = false;
00267 
00268         setEncoderByHue(this->encoder_hue);
00269     }
00270 
00271     return button_bits;
00272 }
00273 
00274 int Smoothiepanel::readEncoderDelta() {
00275     static int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
00276     static uint8_t old_AB = 0;
00277     int8_t state;
00278     old_AB <<= 2;                   //remember previous state
00279     old_AB |= ( this->encoder_a_pin.get() + ( this->encoder_b_pin.get() * 2 ) );  //add current state
00280     state = enc_states[(old_AB&0x0f)];
00281     if(state != 0){
00282         this->encoder_hue += state;
00283         this->encoder_changed = true;
00284     }
00285     return state;
00286 }
00287 
00288 void Smoothiepanel::clear()
00289 {
00290     command(LCD_CLEARDISPLAY);  // clear display, set cursor position to zero
00291 //#ifndef USE_FASTMODE
00292 //    wait_ms(50);  // this command takes a long time!
00293 //#endif
00294 }
00295 
00296 void Smoothiepanel::home()
00297 {
00298     command(LCD_RETURNHOME);  // set cursor position to zero
00299 //#ifndef USE_FASTMODE
00300 //    wait_us(2000);  // this command takes a long time!
00301 //#endif
00302 }
00303 
00304 void Smoothiepanel::setCursor(uint8_t col, uint8_t row)
00305 {
00306     int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
00307     if ( row > _numlines ) row = _numlines - 1;    // we count rows starting w/0
00308     command(LCD_SETDDRAMADDR | (col + row_offsets[row]));
00309 }
00310 
00311 // Turn the display on/off (quickly)
00312 void Smoothiepanel::noDisplay() {
00313     displaycontrol &= ~LCD_DISPLAYON;
00314     command(LCD_DISPLAYCONTROL | displaycontrol);
00315 }
00316 
00317 void Smoothiepanel::display() {
00318     displaycontrol |= LCD_DISPLAYON;
00319     command(LCD_DISPLAYCONTROL | displaycontrol);
00320 }
00321 
00322 // Turns the underline cursor on/off
00323 void Smoothiepanel::noCursor() {
00324     displaycontrol &= ~LCD_CURSORON;
00325     command(LCD_DISPLAYCONTROL | displaycontrol);
00326 }
00327 void Smoothiepanel::cursor() {
00328     displaycontrol |= LCD_CURSORON;
00329     command(LCD_DISPLAYCONTROL | displaycontrol);
00330 }
00331 
00332 // Turn on and off the blinking cursor
00333 void Smoothiepanel::noBlink() {
00334     displaycontrol &= ~LCD_BLINKON;
00335     command(LCD_DISPLAYCONTROL | displaycontrol);
00336 }
00337 void Smoothiepanel::blink() {
00338     displaycontrol |= LCD_BLINKON;
00339     command(LCD_DISPLAYCONTROL | displaycontrol);
00340 }
00341 
00342 // These commands scroll the display without changing the RAM
00343 void Smoothiepanel::scrollDisplayLeft(void) {
00344     command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
00345 }
00346 void Smoothiepanel::scrollDisplayRight(void) {
00347     command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
00348 }
00349 
00350 // This is for text that flows Left to Right
00351 void Smoothiepanel::leftToRight(void) {
00352     displaymode |= LCD_ENTRYLEFT;
00353     command(LCD_ENTRYMODESET | displaymode);
00354 }
00355 
00356 // This is for text that flows Right to Left
00357 void Smoothiepanel::rightToLeft(void) {
00358     displaymode &= ~LCD_ENTRYLEFT;
00359     command(LCD_ENTRYMODESET | displaymode);
00360 }
00361 
00362 // This will 'right justify' text from the cursor
00363 void Smoothiepanel::autoscroll(void) {
00364     displaymode |= LCD_ENTRYSHIFTINCREMENT;
00365     command(LCD_ENTRYMODESET | displaymode);
00366 }
00367 
00368 // This will 'left justify' text from the cursor
00369 void Smoothiepanel::noAutoscroll(void) {
00370     displaymode &= ~LCD_ENTRYSHIFTINCREMENT;
00371     command(LCD_ENTRYMODESET | displaymode);
00372 }
00373 
00374 void Smoothiepanel::command(uint8_t value) {
00375     lcdbang_write(*this->i2c, value>>4, true);
00376     lcdbang_write(*this->i2c, value, true);
00377 }
00378 
00379 void Smoothiepanel::write(const char* line, int len) {
00380     for (int i = 0; i < len; ++i) {
00381         lcdbang_write(*this->i2c, *line++);
00382     }
00383 }
00384 
00385 // Allows to set the backlight, if the LCD backpack is used
00386 void Smoothiepanel::setBacklight(uint8_t status) {
00387 /*  // LED turns on when bit is cleared
00388     _backlightBits = M17_BIT_LB|M17_BIT_LG|M17_BIT_LR; // all off
00389     if (status & LED_RED) _backlightBits &= ~M17_BIT_LR; // red on
00390     if (status & LED_GREEN) _backlightBits &= ~M17_BIT_LG; // green on
00391     if (status & LED_BLUE) _backlightBits &= ~M17_BIT_LB; // blue on
00392 
00393     burstBits16(_backlightBits);
00394 */
00395 }
00396 
00397 void Smoothiepanel::setBacklightColor(uint8_t r, uint8_t g, uint8_t b) {
00398     const int leds = PCA9634_ADDRESS | this->i2c_address;
00399     char cmd[2];
00400 
00401     cmd[0] = 0x07; // lcd blue
00402     cmd[1] = b;
00403     this->i2c->write(leds, cmd, 2);
00404     cmd[0] = 0x08; // lcd green
00405     cmd[1] = g;
00406     this->i2c->write(leds, cmd, 2);
00407     cmd[0] = 0x09; // lcd red
00408     cmd[1] = r;
00409     this->i2c->write(leds, cmd, 2);
00410 }
00411 
00412 void Smoothiepanel::setBacklightByHue(int h) {
00413     float r, g, b;
00414     HSVtoRGB(&r, &g, &b, h, 1.0, 1.0);
00415     setBacklightColor(r*0xFF, g*0xFF, b*0xFF);
00416 }
00417 
00418 void Smoothiepanel::setEncoderLED(uint8_t r, uint8_t g, uint8_t b) {
00419     const int leds = PCA9634_ADDRESS | this->i2c_address;
00420     char cmd[2];
00421 
00422     cmd[0] = 0x04; // encoder red
00423     cmd[1] = r;
00424     this->i2c->write(leds, cmd, 2);
00425     cmd[0] = 0x05; // encoder green
00426     cmd[1] = g;
00427     this->i2c->write(leds, cmd, 2);
00428     cmd[0] = 0x06; // encoder blue
00429     cmd[1] = b;
00430     this->i2c->write(leds, cmd, 2);
00431 }
00432 
00433 void Smoothiepanel::setEncoderByHue(int h) {
00434     float r, g, b;
00435     HSVtoRGB(&r, &g, &b, h, 1.0, 1.0);
00436     setEncoderLED(r*0xFF, g*0xFF, b*0xFF);
00437 }
00438 
00439 void Smoothiepanel::setPlayLED(uint8_t v) {
00440     const int leds = PCA9634_ADDRESS | this->i2c_address;
00441     char cmd[2];
00442 
00443     cmd[0] = 0x02; // play
00444     cmd[1] = v;
00445     this->i2c->write(leds, cmd, 2);
00446 }
00447 
00448 void Smoothiepanel::setBackLED(uint8_t v) {
00449     const int leds = PCA9634_ADDRESS | this->i2c_address;
00450     char cmd[2];
00451 
00452     cmd[0] = 0x03; // back
00453     cmd[1] = v;
00454     this->i2c->write(leds, cmd, 2);
00455 }
00456 
00457 /*
00458 // write either command or data, burst it to the expander over I2C.
00459 void Smoothiepanel::send(uint8_t value, uint8_t mode) {
00460 #ifdef USE_FASTMODE
00461     // polls for ready. not sure on I2C this is any faster
00462 
00463     // set Data pins as input
00464     char data[2];
00465     data[0]= MCP23017_IODIRB;
00466     data[1]= 0x1E;
00467     i2c->write(this->i2c_address, data, 2);
00468     uint8_t b= _backlightBits >> 8;
00469     burstBits8b((M17_BIT_RW>>8)|b); // RW hi,RS lo
00470     char busy;
00471     data[0] = MCP23017_GPIOB;
00472     do {
00473         burstBits8b(((M17_BIT_RW|M17_BIT_EN)>>8)|b); // EN hi
00474         i2c->write(this->i2c_address, data, 1);
00475         i2c->read(this->i2c_address, &busy, 1); // Read D7
00476         burstBits8b((M17_BIT_RW>>8)|b); // EN lo
00477         burstBits8b(((M17_BIT_RW|M17_BIT_EN)>>8)|b); // EN hi
00478         burstBits8b((M17_BIT_RW>>8)|b); // EN lo
00479     } while ((busy&(M17_BIT_D7>>8)) != 0);
00480 
00481     // reset data bits as output
00482     data[0]= MCP23017_IODIRB;
00483     data[1]= 0x00;
00484     i2c->write(this->i2c_address, data, 2);
00485     burstBits8b(b); // RW lo
00486 
00487 #else
00488 //  wait_us(320);
00489 #endif
00490 
00491     // BURST SPEED, OH MY GOD
00492     // the (now High Speed!) I/O expander pinout
00493     //  B7 B6 B5 B4 B3 B2 B1 B0 A7 A6 A5 A4 A3 A2 A1 A0 - MCP23017
00494     //  15 14 13 12 11 10 9  8  7  6  5  4  3  2  1  0
00495     //  RS RW EN D4 D5 D6 D7 B  G  R     B4 B3 B2 B1 B0
00496 
00497     // n.b. RW bit stays LOW to write
00498     uint8_t buf = _backlightBits >> 8;
00499     // send high 4 bits
00500     if (value & 0x10) buf |= M17_BIT_D4 >> 8;
00501     if (value & 0x20) buf |= M17_BIT_D5 >> 8;
00502     if (value & 0x40) buf |= M17_BIT_D6 >> 8;
00503     if (value & 0x80) buf |= M17_BIT_D7 >> 8;
00504 
00505     if (mode) buf |= (M17_BIT_RS|M17_BIT_EN) >> 8; // RS+EN
00506     else buf |= M17_BIT_EN >> 8; // EN
00507 
00508     burstBits8b(buf);
00509 
00510     // resend w/ EN turned off
00511     buf &= ~(M17_BIT_EN >> 8);
00512     burstBits8b(buf);
00513 
00514     // send low 4 bits
00515     buf = _backlightBits >> 8;
00516     // send high 4 bits
00517     if (value & 0x01) buf |= M17_BIT_D4 >> 8;
00518     if (value & 0x02) buf |= M17_BIT_D5 >> 8;
00519     if (value & 0x04) buf |= M17_BIT_D6 >> 8;
00520     if (value & 0x08) buf |= M17_BIT_D7 >> 8;
00521 
00522     if (mode) buf |= (M17_BIT_RS|M17_BIT_EN) >> 8; // RS+EN
00523     else buf |= M17_BIT_EN >> 8; // EN
00524 
00525     burstBits8b(buf);
00526 
00527     // resend w/ EN turned off
00528     buf &= ~(M17_BIT_EN >> 8);
00529     burstBits8b(buf);
00530 }
00531 
00532 // We pause the system
00533 uint32_t Smoothiepanel::on_pause_release(uint32_t dummy){
00534     if(!paused) {
00535         THEKERNEL->pauser->take();
00536         paused= true;
00537     }else{
00538         THEKERNEL->pauser->release();
00539         paused= false;
00540     }
00541     return 0;
00542 }
00543 */
00544