fork from github

master
zen 4 years ago
parent 9f840e5ce0
commit 950cc7012a
  1. 222
      Grove_LCD_rgb_V2.0.c
  2. 99
      Grove_LCD_rgb_V2.0.h
  3. 6
      Makefile
  4. 204
      mod.c
  5. 6
      start.sh
  6. 4
      stop.sh
  7. 24
      test.sh

@ -0,0 +1,222 @@
#include "Grove_LCD_rgb_V2.0.h"
#include <linux/init.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/delay.h>
static int _displayfunction = 0;
static int _displaycontrol = 0;
static int _displaymode = 0;
extern struct i2c_client *i2c_client_lcd;
extern struct i2c_client *i2c_client_rgb;
//--- Mid level commands, for sending data/cmds --------
inline void lcd_command(int value)
{
i2c_smbus_write_byte_data(i2c_client_lcd, 0x80, value);
}
// send data
int lcd_write(char value)
{
i2c_smbus_write_byte_data(i2c_client_lcd, 0x40, value);
return 0;
}
void lcd_setReg(unsigned char addr, unsigned char dta)
{
i2c_smbus_write_byte_data(i2c_client_rgb, addr, dta);
}
void lcd_setRGB(unsigned char r, unsigned char g, unsigned char b)
{
lcd_setReg(REG_RED, r);
lcd_setReg(REG_GREEN, g);
lcd_setReg(REG_BLUE, b);
}
void lcd_setColor(enum color c)
{
lcd_setRGB((c &0xFF0000)>>16, (c &0x00FF00)>>8, c &0x0000FF);
}
//--- high level commands, for the user! ---------------------
void lcd_clear(void)
{
lcd_command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero
mdelay(2); // this command takes a long time!
}
void lcd_home(void)
{
lcd_command(LCD_RETURNHOME); // set cursor position to zero
mdelay(2); // this command takes a long time!
}
void lcd_setCursor(int col, int row)
{
col = (row == 0 ? col|0x80 : col|0xc0);
i2c_smbus_write_byte_data(i2c_client_lcd, 0x80, col);
}
// Turn the display on/off (quickly)
void lcd_noDisplay(void)
{
_displaycontrol &= ~LCD_DISPLAYON;
lcd_command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void lcd_display(void)
{
_displaycontrol |= LCD_DISPLAYON;
lcd_command(LCD_DISPLAYCONTROL | _displaycontrol);
}
// Turns the underline cursor on/off
void lcd_noCursor(void)
{
_displaycontrol &= ~LCD_CURSORON;
lcd_command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void lcd_cursor(void) {
_displaycontrol |= LCD_CURSORON;
lcd_command(LCD_DISPLAYCONTROL | _displaycontrol);
}
// Turn on and off the blinking cursor
void lcd_noBlink(void)
{
_displaycontrol &= ~LCD_BLINKON;
lcd_command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void lcd_blink(void)
{
_displaycontrol |= LCD_BLINKON;
lcd_command(LCD_DISPLAYCONTROL | _displaycontrol);
}
// These commands scroll the display without changing the RAM
void lcd_scrollDisplayLeft(void)
{
lcd_command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
}
void lcd_scrollDisplayRight(void)
{
lcd_command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
}
// This is for text that flows Left to Right
void lcd_leftToRight(void)
{
_displaymode |= LCD_ENTRYLEFT;
lcd_command(LCD_ENTRYMODESET | _displaymode);
}
// This is for text that flows Right to Left
void lcd_rightToLeft(void)
{
_displaymode &= ~LCD_ENTRYLEFT;
lcd_command(LCD_ENTRYMODESET | _displaymode);
}
// This will 'right justify' text from the cursor
void lcd_autoscroll(void)
{
_displaymode |= LCD_ENTRYSHIFTINCREMENT;
lcd_command(LCD_ENTRYMODESET | _displaymode);
}
// This will 'left justify' text from the cursor
void lcd_noAutoscroll(void)
{
_displaymode &= ~LCD_ENTRYSHIFTINCREMENT;
lcd_command(LCD_ENTRYMODESET | _displaymode);
}
// Allows us to fill the first 8 CGRAM locations
// with custom characters
void lcd_createChar(int location, int charmap[])
{
unsigned char dta[8];
int i;
location &= 0x7; // we only have 8 locations 0-7
lcd_command(LCD_SETCGRAMADDR | (location << 3));
for(i=0; i<8; i++)
{
dta[i] = charmap[i];
}
i2c_smbus_write_block_data(i2c_client_lcd, 0x40, 8, dta);
}
// Control the backlight LED blinking
void lcd_blinkLED(void)
{
lcd_setReg(0x07, 0x17); // blink every second
lcd_setReg(0x06, 0x7f); // half on, half off
}
void lcd_noBlinkLED(void)
{
lcd_setReg(0x07, 0x00);
lcd_setReg(0x06, 0xff);
}
void lcd_begin(void)
{
_displayfunction |= LCD_5x8DOTS;
_displayfunction |= LCD_2LINE;
// Send function set command sequence
lcd_command(LCD_FUNCTIONSET | _displayfunction);
mdelay(5); // wait more than 4.1ms
// second try
lcd_command(LCD_FUNCTIONSET | _displayfunction);
mdelay(1);
// third go
lcd_command(LCD_FUNCTIONSET | _displayfunction);
// finally, set # lines, font size, etc.
lcd_command(LCD_FUNCTIONSET | _displayfunction);
// turn the display on with no cursor or blinking default
_displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
lcd_display();
// clear it off
lcd_clear();
// Initialize to default text direction (for romance languages)
_displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
// set the entry mode
lcd_command(LCD_ENTRYMODESET | _displaymode);
// backlight init
lcd_setReg(REG_MODE1, 0);
// set LEDs controllable by both PWM and GRPPWM registers
lcd_setReg(REG_OUTPUT, 0xFF);
// set MODE2 values
// 0010 0000 -> 0x20 (DMBLNK to 1, ie blinky mode)
lcd_setReg(REG_MODE2, 0x20);
lcd_setColor(WHITE);
}
//--- Comand for printing -------------------------------
void lcd_print(char c[])
{
int n;
for (n=0; c[n] != '\0'; n++) lcd_write(c[n]);
}

@ -0,0 +1,99 @@
#ifndef GROVE_LCD_H_
#define GROVE_LCD_H_
// Device I2C Arress
#define LCD_ADDRESS 0x7c
#define RGB_ADDRESS 0xc4
// Set colors
enum color {
AQUA = 0x00FFFF,
BLACK = 0x000000,
BLUE = 0x0000FF,
PURPLE = 0xFF00FF,
GREEN = 0x00FF00,
RED = 0xFF0000,
WHITE = 0xFFFFFF,
YELLOW = 0xFFFF00
};
#define REG_RED 0x04 // pwm2
#define REG_GREEN 0x03 // pwm1
#define REG_BLUE 0x02 // pwm0
#define REG_MODE1 0x00
#define REG_MODE2 0x01
#define REG_OUTPUT 0x08
// commands
#define LCD_CLEARDISPLAY 0x01
#define LCD_RETURNHOME 0x02
#define LCD_ENTRYMODESET 0x04
#define LCD_DISPLAYCONTROL 0x08
#define LCD_CURSORSHIFT 0x10
#define LCD_FUNCTIONSET 0x20
#define LCD_SETCGRAMADDR 0x40
#define LCD_SETDDRAMADDR 0x80
// flags for display entry mode
#define LCD_ENTRYRIGHT 0x00
#define LCD_ENTRYLEFT 0x02
#define LCD_ENTRYSHIFTINCREMENT 0x01
#define LCD_ENTRYSHIFTDECREMENT 0x00
// flags for display on/off control
#define LCD_DISPLAYON 0x04
#define LCD_DISPLAYOFF 0x00
#define LCD_CURSORON 0x02
#define LCD_CURSOROFF 0x00
#define LCD_BLINKON 0x01
#define LCD_BLINKOFF 0x00
// flags for display/cursor shift
#define LCD_DISPLAYMOVE 0x08
#define LCD_CURSORMOVE 0x00
#define LCD_MOVERIGHT 0x04
#define LCD_MOVELEFT 0x00
// flags for function set
#define LCD_8BITMODE 0x10
#define LCD_4BITMODE 0x00
#define LCD_2LINE 0x08
#define LCD_5x8DOTS 0x00
void lcd_print(char c[]);
int lcd_write(char value);
// TODO may be.
// void lcd_print_DEC(int i);
// void lcd_print_HEX(int i);
// void lcd_print_OCT(int i);
// void lcd_print_BIN(int i);
void lcd_begin(void);
void lcd_clear(void);
void lcd_home(void);
void lcd_noDisplay(void);
void lcd_display(void);
void lcd_noBlink(void);
void lcd_blink(void);
void lcd_noCursor(void);
void lcd_cursor(void);
void lcd_scrollDisplayLeft(void);
void lcd_scrollDisplayRight(void);
void lcd_leftToRight(void);
void lcd_rightToLeft(void);
void lcd_autoscroll(void);
void lcd_noAutoscroll(void);
void lcd_createChar(int, int[]);
void lcd_setCursor(int, int);
// color control
void lcd_setRGB(unsigned char r, unsigned char g, unsigned char b);// set rgb
void lcd_setColor(enum color c);
// blink the LED backlight
void lcd_blinkLED(void);
void lcd_noBlinkLED(void);
#endif /* GROVE_LCD_H_ */

@ -0,0 +1,6 @@
obj-m += modq.o
modq-objs := mod.o Grove_LCD_rgb_V2.0.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

204
mod.c

@ -0,0 +1,204 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include "Grove_LCD_rgb_V2.0.h"
// ADD device i2c
// echo grove_lcd 0x3e | sudo tee /sys/class/i2c-adapter/i2c-1/new_device
// echo grove_rgb 0x62 | sudo tee /sys/class/i2c-adapter/i2c-1/new_device
// Delete i2c device
// echo 0x3e | sudo tee /sys/class/i2c-adapter/i2c-1/delete_device
// echo 0x62 | sudo tee /sys/class/i2c-adapter/i2c-1/delete_device
// Test i2c
// i2cdetect -y 1
struct i2c_client *i2c_client_lcd;
struct i2c_client *i2c_client_rgb;
#define DEVICE_NAME "grove_lcd"
#define CLASS_NAME "grove_lcd_lcd"
static int majorNumber;
static struct class* grove_lcd_class = NULL;
static struct device* grove_lcd_device = NULL;
static int is_device_open = 0;
// --- Driver for display (grove_lcd) ----------------------------
static const struct i2c_device_id grove_lcd_id[] = {
{ "grove_lcd", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, grove_lcd_id);
static int grove_lcd_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
i2c_client_lcd = client;
return 0;
}
static int grove_lcd_remove(struct i2c_client *client)
{
return 0;
}
static struct i2c_driver grove_lcd_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "grove_lcd",
},
.probe = grove_lcd_probe,
.remove = grove_lcd_remove,
.id_table = grove_lcd_id,
};
// --- Driver for LED (grove_rgb) --------------------------------
static const struct i2c_device_id grove_rgb_id[] = {
{ "grove_rgb", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, grove_rgb_id);
static int grove_rgb_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
i2c_client_rgb = client;
lcd_begin();
lcd_print("Grove_LCD start!");
return 0;
}
static int grove_rgb_remove(struct i2c_client *client)
{
return 0;
}
static struct i2c_driver grove_rgb_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "grove_rgb",
},
.probe = grove_rgb_probe,
.remove = grove_rgb_remove,
.id_table = grove_rgb_id,
};
// --- Device ----------------------------------------------------
static int device_open( struct inode *inode, struct file *file )
{
if ( is_device_open ) return -EBUSY;
is_device_open++;
return 0;
}
static int device_release( struct inode *inode, struct file *file )
{
is_device_open--;
return 0;
}
static ssize_t device_write(struct file *filp, const char *buff, size_t len, loff_t * offset)
{
int i;
if (buff[0] == '@')
{
if (buff[1] == 'A') lcd_setColor(AQUA);
if (buff[1] == 'B') lcd_setColor(BLUE);
if (buff[1] == 'P') lcd_setColor(PURPLE);
if (buff[1] == 'G') lcd_setColor(GREEN);
if (buff[1] == 'R') lcd_setColor(RED);
if (buff[1] == 'W') lcd_setColor(WHITE);
if (buff[1] == 'Y') lcd_setColor(YELLOW);
if (buff[1] == 'L')
{
if (buff[1] == '1') lcd_setCursor(0,1);
if (buff[1] == '0') lcd_setCursor(0,0);
}
if (buff[1] == 'H') lcd_home();
if (buff[1] == 'C') lcd_clear();
return len;
}
for (i=0; i<len-1; i++)
{
lcd_write(buff[i]);
}
//printk(" --- buf: %s", buff);
return len;
}
static ssize_t device_read( struct file *filp, char *buffer, size_t length, loff_t * offset )
{
char ch[] = "Grove-LCD: Pleas print IN display.\n";
printk (ch);
//copy_to_user(buffer, ch, sizeof(ch));
return 0;
}
static struct file_operations fops =
{
.read = device_read,
.write = device_write,
.open = device_open,
.release = device_release
};
// --- Init module -----------------------------------------------
static int __init grove_lcd_init(void) {
printk("Grove-LCD: display modele - start.\n");
majorNumber = register_chrdev(0, DEVICE_NAME, &fops);
if (majorNumber<0){
printk(KERN_ALERT "Grove-LCD: failed to register a major number\n");
return majorNumber;
}
printk(KERN_INFO "Grove-LCD: registered correctly with major number %d\n", majorNumber);
grove_lcd_class = class_create(THIS_MODULE, CLASS_NAME);
if (IS_ERR(grove_lcd_class)){
unregister_chrdev(majorNumber, DEVICE_NAME);
printk(KERN_ALERT "Grove-LCD: Failed to register device class\n");
return PTR_ERR(grove_lcd_class);
}
printk(KERN_INFO "Grove-LCD: device class registered correctly\n");
grove_lcd_device = device_create(grove_lcd_class, NULL, MKDEV(majorNumber, 0), NULL, DEVICE_NAME);
if (IS_ERR(grove_lcd_device)){
class_destroy(grove_lcd_class);
unregister_chrdev(majorNumber, DEVICE_NAME);
printk(KERN_ALERT "Grove-LCD: Failed to create the device\n");
return PTR_ERR(grove_lcd_device);
}
printk("Grove-LCD: device class created correctly\n");
i2c_add_driver(&grove_lcd_driver);
i2c_add_driver(&grove_rgb_driver);
return 0;
}
static void __exit grove_lcd_exit(void) {
device_destroy(grove_lcd_class, MKDEV(majorNumber, 0));
class_unregister(grove_lcd_class);
class_destroy(grove_lcd_class);
unregister_chrdev(majorNumber, DEVICE_NAME);
i2c_del_driver(&grove_lcd_driver);
i2c_del_driver(&grove_rgb_driver);
printk("Grove-LCD: display modele - kill.\n");
}
module_init(grove_lcd_init);
module_exit(grove_lcd_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("ZEN");

@ -0,0 +1,6 @@
#!/bin/bash
make
sudo insmod modq.ko
echo grove_lcd 0x3e | sudo tee /sys/class/i2c-adapter/i2c-1/new_device
echo grove_rgb 0x62 | sudo tee /sys/class/i2c-adapter/i2c-1/new_device

@ -0,0 +1,4 @@
#!/bin/bash
echo 0x62 | sudo tee /sys/class/i2c-adapter/i2c-1/delete_device
echo 0x3e | sudo tee /sys/class/i2c-adapter/i2c-1/delete_device
sudo rmmod modq.ko

@ -0,0 +1,24 @@
#!/bin/bash
sudo insmod modq.ko
echo grove_lcd 0x3e | sudo tee /sys/class/i2c-adapter/i2c-1/new_device > /dev/nul
echo grove_rgb 0x62 | sudo tee /sys/class/i2c-adapter/i2c-1/new_device > /dev/nul
while [ "$B" != "exid" ]
do
echo "Enter print string:"
read B
if [ "$B" != "exid" ]
then
sudo echo "@C" | sudo tee /dev/grove_lcd > /dev/nul
fi
if [ "$B" != "exid" ]
then
sudo echo $B | sudo tee /dev/grove_lcd > /dev/nul
fi
done
echo "Close display menager."
echo 0x62 | sudo tee /sys/class/i2c-adapter/i2c-1/delete_device > /dev/nul
echo 0x3e | sudo tee /sys/class/i2c-adapter/i2c-1/delete_device > /dev/nul
sudo rmmod modq.ko
Loading…
Cancel
Save