From 3de34d0735f0d15b0bb0fc463c5fa912df6fb4c3 Mon Sep 17 00:00:00 2001 From: ntruchsess <> Date: Tue, 8 Apr 2014 23:01:18 +0000 Subject: [PATCH] I2C_LCD: add attribute pinMapping Merge branch 'I2C' git-svn-id: https://svn.fhem.de/fhem/trunk@5492 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/52_I2C_LCD.pm | 34 +++++---- ...{LiquidCrystal_I2C.pm => LiquidCrystal.pm} | 76 ++++++++++++++++--- 2 files changed, 88 insertions(+), 22 deletions(-) rename fhem/FHEM/lib/{LiquidCrystal_I2C.pm => LiquidCrystal.pm} (87%) diff --git a/fhem/FHEM/52_I2C_LCD.pm b/fhem/FHEM/52_I2C_LCD.pm index 894df6418..c79415654 100644 --- a/fhem/FHEM/52_I2C_LCD.pm +++ b/fhem/FHEM/52_I2C_LCD.pm @@ -66,6 +66,13 @@ I2C_LCD_Define($$) my @a = split("[ \t][ \t]*", $def); $hash->{STATE}="defined"; + + my @keyvalue = (); + while (my ($key, $value) = each %mapping) { + push @keyvalue,"$key=$value"; + }; + $main::attr{$a[0]}{"pinMapping"} = join (',',sort @keyvalue); + $hash->{mapping} = \%mapping; if ($main::init_done) { eval { @@ -73,12 +80,7 @@ I2C_LCD_Define($$) }; return I2C_LCD_Catch($@) if $@; } - - my @keyvalue = (); - while (my ($key, $value) = each %mapping) { - push @keyvalue,"$key=$value"; - }; - $main::attr{$a[0]}{"pinMapping"} = join (',',sort @keyvalue);; + return undef; } @@ -92,14 +94,17 @@ I2C_LCD_Init($$) $hash->{sizex} = shift @$args; $hash->{sizey} = shift @$args; - $hash->{I2C_Address} = shift @$args if (@$args); + if (defined (my $address = shift @$args)) { + $hash->{I2C_Address} = $address =~ /^0.*$/ ? oct($address) : $address; + } my $name = $hash->{NAME}; if (defined $hash->{I2C_Address}) { eval { main::AssignIoPort($hash,AttrVal($hash->{NAME},"IODev",undef)); - require LiquidCrystal_I2C; - my $lcd = LiquidCrystal_I2C->new($hash->{I2C_Address},$hash->{sizex},$hash->{sizey},\%mapping); + require LiquidCrystal; + my $lcd = LiquidCrystal->new($hash->{sizex},$hash->{sizey}); + $lcd->setMapping($hash->{mapping}); $lcd->attach(I2C_LCD_IO->new($hash)); $lcd->init(); $hash->{lcd} = $lcd; @@ -139,13 +144,16 @@ I2C_LCD_Attr($$$$) { last; }; $attribute eq "pinMapping" and do { + my %newMapping = (); foreach my $keyvalue (split (/,/,$value)) { my ($key,$value) = split (/=/,$keyvalue); #Log3 ($name,5,"pinMapping, token: $key=$value, current mapping: $mapping{$key}"); die "unknown token $key in attribute pinMapping, valid tokens are ".join (',',keys %mapping) unless (defined $mapping{$key}); die "undefined or invalid value for token $key in attribute pinMapping, valid LED-Pins are ".join (',',@LEDPINS) unless $value and grep (/$value/,@LEDPINS); - $mapping{$key} = $value; + $newMapping{$key} = $value; } + $hash->{mapping} = \%newMapping; + I2C_LCD_Init($hash,split (' ',$hash->{DEF})) if ($main::init_done); last; }; $main::attr{$name}{$attribute}=$value; @@ -352,12 +360,12 @@ sub new { }, $class; } -sub i2c_write { - my ( $self, $address, @data ) = @_; +sub write { + my ( $self, @data ) = @_; my $hash = $self->{hash}; if (defined (my $iodev = $hash->{IODev})) { main::CallFn($iodev->{NAME}, "I2CWrtFn", $iodev, { - i2caddress => $address, + i2caddress => $hash->{I2C_Address}, direction => "i2cwrite", data => join (' ',@data) }); diff --git a/fhem/FHEM/lib/LiquidCrystal_I2C.pm b/fhem/FHEM/lib/LiquidCrystal.pm similarity index 87% rename from fhem/FHEM/lib/LiquidCrystal_I2C.pm rename to fhem/FHEM/lib/LiquidCrystal.pm index 11941b9db..0d66da616 100644 --- a/fhem/FHEM/lib/LiquidCrystal_I2C.pm +++ b/fhem/FHEM/lib/LiquidCrystal.pm @@ -1,3 +1,11 @@ +# LiquidCrystal.pm +# +# Perl-library to drive LCD-displays controlled by Hitachi HD44780 LCD controller +# +# Copyright (C) 2013/2014 Norbert Truchsess (norbert.truchsess@t-online.de) +# +# based on LiquidCrystal.cpp as of: +# # www.DFRobot.com # last updated on 21/12/2011 # Tim Starling Fix the reset bug (Thanks Tim) @@ -5,7 +13,7 @@ # Support Forum: http://www.dfrobot.com/forum/ # Compatible with the Arduino IDE 1.0 # Library version:1.1 - +# # When the display powers up, it is configured as follows: # # 1. Display clear @@ -25,7 +33,7 @@ # can't assume that its in that state when a sketch starts (and the # LiquidCrystal constructor is called). -package LiquidCrystal_I2C; +package LiquidCrystal; use warnings; use strict; @@ -76,6 +84,17 @@ use constant En => 0b00000100; # Enable bit use constant Rw => 0b00000010; # Read / Write bit use constant Rs => 0b00000001; # Register select bit +our %mapping_bits = ( + RS => 0, + RW => 1, + E => 2, + LED => 3, + D4 => 4, + D5 => 5, + D6 => 6, + D7 => 7, +); + sub print($$) { my ($self,$c) = @_; my @buf = unpack "c*",$c; @@ -90,14 +109,45 @@ sub write($$) { return 0; } -sub new($$$$) { - my ( $class, $lcd_Addr, $lcd_cols, $lcd_rows ) = @_; - return bless { - Addr => $lcd_Addr, +sub new($$$$@) { + my ( $class, $lcd_cols, $lcd_rows ) = @_; + + my $lcd = bless { cols => $lcd_cols, rows => $lcd_rows, backlightval => LCD_NOBACKLIGHT, }, $class; + $lcd->setMapping(); + return $lcd; +} + +# $lcd_mapping = { +# 'P0' => 'RS', +# 'P1' => 'RW', +# 'P2' => 'E', +# 'P3' => 'LED', +# 'P4' => 'D4', +# 'P5' => 'D5', +# 'P6' => 'D6', +# 'P7' => 'D7', +#}; + +sub setMapping(@) { + my ( $self, $lcd_mapping ) = @_; + + my %mapping; + if ( defined $lcd_mapping ) { + while (my ($key, $value) = each %$lcd_mapping) { + die "illegal value for MAPPING: $value, must be one of RS,RW,E,LED,D4,D5,D6,D7" unless grep {$value eq $_} keys %mapping_bits; + die "illegal value for PIN: $key, must be one of P0..P7" unless $key =~ /^P([\d])$/; + $mapping{0x01 << $mapping_bits{$value}} = 0x01 << $1; + } + } else { + foreach my $i (0..7) { + $mapping{0x01 << $i} = 0x01 << $i; + } + } + $self->{mapping} = \%mapping; } sub init($) { @@ -107,7 +157,7 @@ sub init($) { sub attach($$) { my ($self,$dev) = @_; - $self->{I2CDevice} = $dev; + $self->{io} = $dev; } sub init_priv($) { @@ -359,8 +409,16 @@ sub write4bits($$) { sub expanderWrite($$) { my ( $self, $data ) = @_; - - $self->{I2CDevice}->i2c_write($self->{Addr},($data) | $self->{backlightval}); + + $data |= $self->{backlightval}; + + my $mapped = 0; + + while (my ($orig, $remapped) = each %{$self->{mapping}}) { + $mapped |= $data & $orig ? $remapped : 0; + } + + $self->{io}->write($mapped); } sub pulseEnable($$) {