Test application for the LCD4884. It uses the LCD 4884 from SainSmart / DFRobot, the on board accelerometer and RGB LED.

Dependencies:   LCD4884 MMA8451Q mbed

/media/uploads/COX/mbed_pic_s.jpg

This is the first version.

- I want to add support for a smaller font (like 5x6).

- Update the 5 way read and de-bounce.

It was my first try with MBED on the FRDM KL25Z board and LCD shield.

!!!!!

The shield needs to be modified to work correctly. It has the 5V routed to the 5 way switch so it is more than the 3V threshold for the ADC.

!!!!!

main.cpp

Committer:
COX
Date:
2013-03-09
Revision:
1:0dee51d54fd6
Parent:
0:b06425bd412a

File content as of revision 1:0dee51d54fd6:

#include "mbed.h"
#include "LCD4884.h"
#include "MMA8451Q.h"

#define MMA8451_I2C_ADDRESS (0x1d<<1)
#define SERIAL_FREQ 10
    
//keypad debounce parameter
#define DEBOUNCE_MAX 10
//#define DEBOUNCE_ON  10
//#define DEBOUNCE_OFF 3 
 
#define NUM_KEYS 5
 
#define NUM_MENU_ITEM   6
 
// joystick number
#define LEFT_KEY 0
#define CENTER_KEY 1
#define DOWN_KEY 2
#define RIGHT_KEY 3
#define UP_KEY 4
 
// menu starting points
 
#define MENU_X  4      // 0-83
#define MENU_Y  0       // 0-5

/*------------------------------------------------------------------------------
; DFrobot bitmap - size 48x24 pixels, black/white image
------------------------------------------------------------------------------*/
unsigned char demo_bmp[]=

{
0x00,0x00,0x10,0x20,0x20,0x60,0xE0,0xC0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xC0,0xF0,0xF0,0xF8,0xF8,0xFC,0xFC,0x3E,0x3E,0x32,0x61,0x00,0x00,
0x00,0x00,0x61,0x32,0x3E,0x3E,0xFC,0xFC,0xF8,0xF8,0xF0,0xF0,0xC0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0xC0,0xE0,0x60,0x20,0x20,0x10,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x08,0x78,0xF3,0xFB,0xF3,0x1B,0x18,0xE8,0xEC,0xC0,0xC4,0xC0,0xF0,0xE0,0x70,0x73,0xE7,0xFE,0xFE,0xF8,0xFE,0xDE,0x0F,0x0F,0xBF,0xFF,0xEB,0x83,0x06,0x06,0x0F,0x0F,0x1C,0x18,0x20,0x00,0x00,
0x00,0x00,0x20,0x18,0x1C,0x0F,0x0F,0x06,0x06,0x83,0xEB,0xFF,0xBF,0x0F,0x0F,0xDE,0xFE,0xF8,0xFE,0xFE,0xE7,0x73,0x70,0xE0,0xF0,0xC0,0xC4,0xC0,0xEC,0xE8,0x18,0x1B,0xF3,0xFB,0xF3,0x78,0x08,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x02,0x03,0x03,0x03,0x03,0x06,0x06,0x0F,0x1F,0x2E,0x68,0xF3,0xE7,0xEF,0xDF,0x9D,0xBC,0xB8,0xB8,0x9C,0xD8,0xE3,0x7F,0x7F,0xFE,0xF0,0xC7,0x87,0x07,0x07,0xFF,0x7E,0x1C,0xFC,0xFC,0xFC,0xFC,0xFE,0xE0,0xF8,
0xF8,0xE0,0xFE,0xFC,0xFC,0xFC,0xFC,0x1C,0x7E,0xFF,0x07,0x07,0x87,0xC7,0xF0,0xFE,0x7F,0x7F,0xE3,0xD8,0x9C,0xB8,0xB8,0xBC,0x9D,0xDF,0xEF,0xE7,0xF3,0x68,0x2E,0x1F,0x0F,0x06,0x06,0x03,0x03,0x03,0x03,0x02,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x21,0x39,0x1F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0E,0x0E,0x1E,0x1F,0x3F,0x7F,0xFE,0xFC,0xF9,0xF2,0xFE,0xF8,0xE3,0x8F,0xE7,0xCF,0xC7,
0xC7,0xCF,0xE7,0x8F,0xE3,0xF8,0xFE,0xF2,0xF9,0xFC,0xFE,0x7F,0x3F,0x1F,0x1E,0x0E,0x0E,0x0F,0x0F,0x0F,0x0F,0x0F,0x1F,0x39,0x21,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xDF,0x3F,0x01,0x03,0x07,0x0F,0x1F,0x3F,0xFF,0xFF,
0xFF,0xFF,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x3F,0xDF,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
/******************************************************************************/
 
 
/*------------------------------------------------------------------------------
; DFrobot chinese - size 12x12  
------------------------------------------------------------------------------*/
/*unsigned char DFrobot_chinese[]=
{
  0x84,0x64,0xFF,0x24,0x44,0xFE,0x02,0x02,0xFF,0x02,0x00,0x00,0x01,0x00,0x07,0x04,0x02,0x01,0x00,0x00,0x07,0x04,0x07,0x00,
  0xA0,0xAF,0xA9,0xE9,0xAF,0x30,0xAF,0xA9,0xF9,0xAF,0xA0,0x00,0x00,0x07,0x04,0x04,0x07,0x00,0x07,0x04,0x04,0x07,0x00,0x00,
  0x00,0x00,0x00,0x80,0x60,0x1F,0x60,0x80,0x00,0x00,0x00,0x00,0x04,0x04,0x02,0x01,0x00,0x00,0x00,0x01,0x02,0x04,0x04,0x00,
  0x22,0x12,0x0A,0xBF,0x6A,0x52,0x4A,0x7F,0xCA,0x12,0x22,0x00,0x04,0x05,0x05,0x04,0x05,0x02,0x02,0x01,0x00,0x00,0x00,0x00,
  0x00,0x02,0x02,0x02,0x02,0xFE,0x02,0x02,0x03,0x02,0x00,0x00,0x04,0x04,0x04,0x04,0x04,0x07,0x04,0x04,0x04,0x04,0x04,0x00,
  0x00,0xFF,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x06,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};*/


LCD4884 lcd;
AnalogIn JStick(PTB0);
Timeout readJStick;
MMA8451Q acc(PTE25, PTE24, MMA8451_I2C_ADDRESS);

//DigitalOut TestPin1(PTA13);
//DigitalOut TestPin2(PTD5);
PwmOut r (LED_RED);
PwmOut g (LED_GREEN);
PwmOut b (LED_BLUE);

PwmOut rgb[3] = {PwmOut(LED_RED), PwmOut(LED_GREEN), PwmOut(LED_BLUE)};

//LEFT_KEY, CENTER_KEY, DOWN_KEY, RIGHT_KEY, UP_KEY
float adc_key_val[5] ={
  0.10, 0.20, 0.40, 0.60, 0.90 };

float lcdBrightness = 1;
float JStickReadSpeed = 0.015;
float x, y, z;

// debounce counters
char button_count[NUM_KEYS];
// button status - pressed/released
char button_status[NUM_KEYS];
 
// menu definition
char menu_items[NUM_MENU_ITEM][14]={
  "BRIGHTNESS",
  "RGB",
  "CHAR MAP",
  "BITMAP",
  "ACCELEROMETER",
  "ABOUT"  
};

void brightness();
void rgb_led_ctrl();
void charmap();
void bitmap();
void accelerometer();
void about();
void init_MENU(void);
void update_adc_key();
void waitfor_OKkey();

void (*menu_funcs[NUM_MENU_ITEM])(void) = {
  brightness,
  rgb_led_ctrl,
  charmap,
  bitmap,
  accelerometer,
  about
};
 
char current_menu_item = 0;
char rgb_menu_item = 0;

void setup()
{
 
  /* reset button arrays */
  for(char i=0; i<NUM_KEYS; i++){
    button_count[i]=0;
    button_status[i]=0;
  }
 
  lcd.LCD_init();
  lcd.LCD_clear();

  /*Setup RGB LED*/
  rgb[0].period_us(100);
  for(char i=0; i<3; i++){
    rgb[i] = 1;
  }

  /*Menu initialization*/
  init_MENU();
  current_menu_item = 0;    
 
  lcd.backlight(ON);//Turn on the backlight
  
  readJStick.attach(&update_adc_key, JStickReadSpeed);
}
 
unsigned long buttonFlasher = 0;
 
/* loop */
 
void loop()
{
  for(char i=0; i<NUM_KEYS; i++){
    if(button_status[i] != 0){
        button_status[i] = 0;  // reset button flag

        switch(i){
            case UP_KEY:
                // current item to normal display
                lcd.LCD_write_string(MENU_X, MENU_Y + current_menu_item, menu_items[current_menu_item], MENU_NORMAL );
                if(current_menu_item == 0)
                    current_menu_item = NUM_MENU_ITEM -1;
                else
                    current_menu_item -=1;
                // next item to highlight display
                lcd.LCD_write_string(MENU_X, MENU_Y + current_menu_item, menu_items[current_menu_item], MENU_HIGHLIGHT );
                break;

            case DOWN_KEY:
                // current item to normal display
                lcd.LCD_write_string(MENU_X, MENU_Y + current_menu_item, menu_items[current_menu_item], MENU_NORMAL );
                current_menu_item +=1;
                if(current_menu_item >(NUM_MENU_ITEM-1))  current_menu_item = 0;
                // next item to highlight display
                lcd.LCD_write_string(MENU_X, MENU_Y + current_menu_item, menu_items[current_menu_item], MENU_HIGHLIGHT );
                break;

            /*case LEFT_KEY:
            case RIGHT_KEY:
                init_MENU();
                current_menu_item = 0;
                break;*/

            case CENTER_KEY:
                lcd.LCD_clear();
                lcd.LCD_write_string(36, 5, "OK", MENU_HIGHLIGHT );
                (*menu_funcs[current_menu_item])();
                init_MENU();
                break;  
            }
        }
    }
}
 
/* menu functions */
 
void init_MENU(void)
{
  lcd.LCD_clear();

  for (char i=0; i<NUM_MENU_ITEM; i++){
    if(i==current_menu_item)
        lcd.LCD_write_string(MENU_X, MENU_Y+i, menu_items[i], MENU_HIGHLIGHT);
    else
        lcd.LCD_write_string(MENU_X, MENU_Y+i, menu_items[i], MENU_NORMAL);
  }
}
 
// waiting for center key press
void waitfor_OKkey()
{
    char stay = 1;
    
    while(stay)
    {
        for(char i=0; i<NUM_KEYS; i++)
        {
            if(button_status[i] != 0){
                if(CENTER_KEY == i)
                {
                    stay = 0;
                    button_status[i] = 0;
                }
            }
        }
    }
}
 
void brightness()
{
  char redraw = 1;
  
  lcd.LCD_write_string(14, 1, "LCD", MENU_NORMAL);

  while(1)
  {
    if(redraw)
    {
        lcd.LCD_set_XY(12,2);
        for(char i=0; i<10; i++)
        {
            if(i < lcdBrightness * 10)
                lcd.LCD_write_char(92, MENU_NORMAL);
            else
                lcd.LCD_write_char(95, MENU_NORMAL);
        }
        redraw = 0;
    }
    
    if (button_status[RIGHT_KEY])
    {
        button_status[RIGHT_KEY] = 0;
        redraw = 1;
        if(lcdBrightness < 1)
        {
            lcdBrightness += 0.1;
            lcd.backlight(lcdBrightness);
        }
    }
    if (button_status[LEFT_KEY])
    {
        button_status[LEFT_KEY] = 0;
        redraw = 1;
        if(lcdBrightness > 0)
        {
            lcdBrightness -= 0.1;
            lcd.backlight(lcdBrightness);
        }
    }
    
    if (button_status[CENTER_KEY])
    {
        button_status[CENTER_KEY] = 0;
        break;
    }
  }
}

void rgb_led_ctrl()
{
  char redraw = 1;
  float temp;
  
  lcd.LCD_write_string(14, 0, "RGB", MENU_NORMAL);

  while(1)
  {
    if(redraw)
    {
      lcd.LCD_write_string(5, 2, "R:", (rgb_menu_item == 0)?MENU_HIGHLIGHT:MENU_NORMAL);
      lcd.LCD_write_string(5, 3, "G:", (rgb_menu_item == 1)?MENU_HIGHLIGHT:MENU_NORMAL);
      lcd.LCD_write_string(5, 4, "B:", (rgb_menu_item == 2)?MENU_HIGHLIGHT:MENU_NORMAL);

        for(char j=0; j<3; j++)
        {
            lcd.LCD_set_XY(17,2+j);
            temp = rgb[j];
            for(char i=0; i<10; i++)
            {
                if(i < (1-temp)*10)
                    lcd.LCD_write_char(92, MENU_NORMAL);
                else
                    lcd.LCD_write_char(32, MENU_NORMAL);
            }
        }
        redraw = 0;
    }
    
    if (button_status[RIGHT_KEY])
    {
        button_status[RIGHT_KEY] = 0;
        redraw = 1;
        temp = rgb[rgb_menu_item];
        if(temp > 0){
            rgb[rgb_menu_item] = temp - 0.1;
        }
    }
    if (button_status[LEFT_KEY])
    {
        button_status[LEFT_KEY] = 0;
        redraw = 1;
        temp = rgb[rgb_menu_item];
        if(temp < 1){
            rgb[rgb_menu_item] = temp + 0.1;
        }
    }
    if (button_status[UP_KEY])
    {
        button_status[UP_KEY] = 0;
        redraw = 1;
        if(rgb_menu_item == 0)
            rgb_menu_item = 2;
        else
            rgb_menu_item--;
    }
    if (button_status[DOWN_KEY])
    {
        button_status[DOWN_KEY] = 0;
        redraw = 1;
        if(rgb_menu_item == 2)
            rgb_menu_item = 0;
        else
            rgb_menu_item++;
    }
    
    if (button_status[CENTER_KEY])
    {
        button_status[CENTER_KEY] = 0;
        break;
    }
  }
}
 
void charmap(){
  char i,j;
  for(i=0; i<5; i++){
    for(j=0; j<14; j++){
      lcd.LCD_set_XY(j*6,i);
      lcd.LCD_write_char(i*14+j+32, MENU_NORMAL);
    }
  }
  waitfor_OKkey();   
}
 
void bitmap(){
  lcd.LCD_draw_bmp_pixel(0,0, demo_bmp, 84,40);
  //lcd.LCD_write_chinese(6,3, DFrobot_chinese,12,6,0,0);
  waitfor_OKkey();
}
 
void accelerometer(){
    while(1)
    {
        x = abs(acc.getAccX());
        y = abs(acc.getAccY());
        z = abs(acc.getAccZ());
        wait(0.1);
        lcd.LCD_set_XY(5,2);
        lcd.LCD_write_char(48+int(x),MENU_NORMAL);
        lcd.LCD_write_char('.',MENU_NORMAL);
        lcd.LCD_write_char(48+int((x-int(x))*10),MENU_NORMAL);
        lcd.LCD_set_XY(32,2);
        lcd.LCD_write_char(48+int(y),MENU_NORMAL);
        lcd.LCD_write_char('.',MENU_NORMAL);
        lcd.LCD_write_char(48+int((y-int(y))*10),MENU_NORMAL);
        lcd.LCD_set_XY(59,2);
        lcd.LCD_write_char(48+int(z),MENU_NORMAL);
        lcd.LCD_write_char('.',MENU_NORMAL);
        lcd.LCD_write_char(48+int((z-int(z))*10),MENU_NORMAL);
        if (button_status[CENTER_KEY])
        {
            button_status[CENTER_KEY] = 0;
            break;
        }
    }
}
void about(){
  lcd.LCD_write_string( 0, 1, "LCD4884 Shield", MENU_NORMAL);
  lcd.LCD_write_string( 0, 3, "sainsmart.com", MENU_NORMAL);
  waitfor_OKkey();
}
 
// which includes DEBOUNCE ON/OFF mechanism, and continuous pressing detection
// Convert ADC value to key number
 
char get_key(float input)
{
  char k;
 
  for (k = 0; k < NUM_KEYS; k++)
  {
    if (input < adc_key_val[k])
    {
      return k;
    }
  }
  if (k >= NUM_KEYS)
    k = NUM_KEYS;     // No valid key pressed
 
  return k;
}

//poor attempt at a debounce mechanism. 
void update_adc_key(){
  float adc_key_in;
  char key_in;
  char i;

//TestPin2 = HIGH;

  adc_key_in = JStick.read();

  key_in = get_key(adc_key_in);
  for(i=0; i<NUM_KEYS; i++)
  {
    if(key_in == i)  //one key is pressed 
    {
        if(button_count[i] < DEBOUNCE_MAX) button_count[i]++;
        if(button_count[i] == DEBOUNCE_MAX){
            button_status[i] = 1;
            button_count[i] = 1;
            JStickReadSpeed = 0.200;
        }
    }
    else // no button pressed
    {
        if(button_count[i] > 0) button_count[i]--;
        if(button_count[i] == 0){
            button_status[i] = 0;
            JStickReadSpeed = 0.015;
        }
    }
  }

  readJStick.attach(&update_adc_key, JStickReadSpeed);

//TestPin2 = LOW;

}

int main(void)
{
    lcd = LCD4884();
    setup();
    while(1) {
        //TestPin1 = HIGH;
        loop();
        //TestPin1 = LOW;
    };
}