Commits

Anonymous committed e713d3e

FastIO library
FastIO support for SR class
SR Example
Small adaptions to make things work with eclipse too

  • Participants
  • Parent commits fbed52f
  • Branches fastIO

Comments (0)

Files changed (12)

+#if (ARDUINO <  100)
+#include <WProgram.h>
+#else
+#include <Arduino.h>
+#endif
+#include "FastIO.h"
+#include <util/delay.h>
+
+fio_register fio_pinToOutputRegister(uint8_t pin){
+	pinMode(pin, OUTPUT);
+	digitalWrite(pin, LOW); // also turns off pwm timer
+#ifdef FIO_FALLBACK
+	//  just wasting memory if not using fast io...
+	return 0;
+#else
+	return portOutputRegister(digitalPinToPort(pin));
+#endif
+}
+
+fio_register fio_pinToInputRegister(uint8_t pin){
+	pinMode(pin, INPUT);
+	digitalWrite(pin, LOW); // also turns off pwm timer and pullup
+#ifdef FIO_FALLBACK
+	//  just wasting memory if not using fast io...
+	return 0;
+#else
+	return portInputRegister(digitalPinToPort(pin));
+#endif
+}
+
+uint8_t fio_pinToBit(uint8_t pin){
+#ifdef FIO_FALLBACK
+	// (ab)use the bit variable to store the pin
+	return pin;
+#else
+	return digitalPinToBitMask(pin);
+#endif
+}
+
+void fio_digitalWrite(fio_register pinRegister, uint8_t pinBit, uint8_t value) {
+#ifdef FIO_FALLBACK
+	digitalWrite(pinBit, value);
+#else
+	if(value == LOW){
+		fio_digitalWrite_LOW(pinRegister,pinBit);
+	}else{
+		fio_digitalWrite_HIGH(pinRegister,pinBit);
+	}
+#endif
+}
+
+int fio_digitalRead(fio_register pinRegister, uint8_t pinBit){
+#ifdef FIO_FALLBACK
+	return digitalRead(pinBit);
+#else
+	if (*pinRegister & pinBit) return HIGH;
+	return LOW;
+#endif
+}
+
+void fio_shiftOut(fio_register dataRegister, fio_bit dataBit, fio_register clockRegister, fio_bit clockBit, uint8_t value){
+	// # disable interrupts
+	// uint8_t oldSREG = SREG;
+	// cli();
+
+	for(int8_t i = 7; i>-1; --i){
+		fio_digitalWrite(dataRegister, dataBit, !!(value & (1 << i)));
+		fio_digitalWrite_HIGH(clockRegister, clockBit);
+		fio_digitalWrite_LOW(clockRegister, clockBit);
+	}
+
+	// # enable interrupts
+	// SREG = oldSREG;
+}
+
+void fio_shiftOut(fio_register dataRegister, uint8_t dataBit, fio_register clockRegister, uint8_t clockBit){
+	fio_digitalWrite_LOW(dataRegister, dataBit);
+	for(uint8_t i = 0; i<8; ++i){
+			fio_digitalWrite_HIGH(clockRegister, clockBit);
+			fio_digitalWrite_LOW(clockRegister, clockBit);
+	}
+}
+
+void fio_shiftOut1_init(fio_register shift1Register, fio_bit shift1Bit){
+	// Make sure that capacitors are charged
+	fio_digitalWrite(shift1Register,shift1Bit,HIGH);
+	delayMicroseconds(300);
+}
+void fio_shiftOut1(fio_register shift1Register, fio_bit shift1Bit, uint8_t value){
+
+	// disable interrupts since timing is going to be critical
+	uint8_t oldSREG;
+	oldSREG = SREG;
+	cli();
+
+
+	// note: profiling showed that shift out takes 18us longer than the sum of needed delays
+
+	// iterate but ignore last byte (must be LOW)
+	for(int8_t i = 7; i>0; --i){
+		fio_digitalWrite_LOW(shift1Register,shift1Bit);
+		if(LOW==!!(value & (1 << i))){
+			// LOW = 0 Bit
+			// hold pin LOW for 15us
+			delayMicroseconds(14);
+			fio_digitalWrite_HIGH(shift1Register,shift1Bit);
+			// hold pin HIGH for 30us
+			delayMicroseconds(29);
+		}else{
+			// HIGH = 1 Bit
+			//hold pin LOW for 1us - did that already
+			fio_digitalWrite_HIGH(shift1Register,shift1Bit);
+			//hold pin HIGH for 15us
+			delayMicroseconds(14);
+		}
+	}
+	// send last bit (=LOW) and Latch command
+	fio_digitalWrite_LOW(shift1Register,shift1Bit);
+	delayMicroseconds(199); // Hold pin low for 200us
+	fio_digitalWrite_HIGH(shift1Register,shift1Bit);
+	delayMicroseconds(299); // Hold pin high for 300us
+
+	// enable interrupts
+	SREG = oldSREG;
+
+}
+
+#ifndef FAST_IO_H
+#define FAST_IO_H
+
+#include <inttypes.h>
+#include <util/delay.h>
+
+#ifndef __AVR__
+#define FIO_FALLBACK
+#endif
+
+typedef uint8_t fio_bit;
+
+#ifndef FALLBACK
+typedef volatile uint8_t * fio_register;
+#else
+// remove volatile to give optimizer a chance
+typedef uint8_t fio_register;
+#endif
+
+/*!
+ @function
+ @abstract  Get the output register for specified pin.
+ @discussion if fast digital IO is disabled this function returns NULL
+ @param  pin[in] Number of a digital pin
+ @result  Register
+ */
+fio_register fio_pinToOutputRegister(uint8_t pin);
+
+/*!
+ @function
+ @abstract  Get the input register for specified pin.
+ @discussion if fast digital IO is disabled this function returns NULL
+ @param  pin[in] Number of a digital pin
+ @result  Register
+ */
+fio_register fio_pinToInputRegister(uint8_t pin);
+
+/*!
+ @function
+ @abstract Find the bit which belongs to specified pin
+ @discussion if fast digitalWrite is disabled this function returns the pin
+ @param pin[in] Number of a digital pin
+ @result Bit
+ */
+fio_bit fio_pinToBit(uint8_t pin);
+
+
+/*!
+ @method
+ @abstract direct digital write
+ @discussion without any checks
+ @discussion falls back to normal digitalWrite if fast io is disabled
+ @param pinRegister[in] Register - ignored if fast digital write is disabled
+ @param pinBit[in] Bit - Pin if fast digital write is disabled
+ @param value[in] desired output
+ */
+// __attribute__ ((always_inline)) /* let the optimizer decide that for now */
+void fio_digitalWrite(fio_register pinRegister, fio_bit pinBit,uint8_t value);
+
+// todo: how do i get te compiler to use these when value is known at compile time?
+#ifndef FIO_FALLBACK
+#define fio_digitalWrite_LOW(reg,bit) *reg &= ~bit
+#define fio_digitalWrite_HIGH(reg,bit) *reg |= bit
+#else
+#define fio_digitalWrite_HIGH(reg,bit) digitalWrite(bit,HIGH)
+#define fio_digitalWrite_LOW(reg,bit) digitalWrite(bit,LOW)
+#endif
+
+/*!
+ @function
+ @abstract direct digital read
+ @discussion without any checks
+ @discussion falls back to normal digitalRead if fast io is disabled
+ @param pinRegister[in] Register - ignored if fast io is disabled
+ @param pinBit[in] Bit - Pin if fast io is disabled
+ @result Value read from pin
+ */
+int fio_digitalRead(fio_register pinRegister, fio_bit pinBit);
+
+/*!
+ @method
+ @abstract faster shift out
+ @discussion using fast digital write
+ @discussion falls back to normal digitalWrite if fastio is disabled
+ @param dataRegister[in] Register of data pin - ignored if fast digital write is disabled
+ @param dataBit[in] Bit of data pin - Pin if fast digital write is disabled
+ @param clockRegister[in] Register of data pin - ignored if fast digital write is disabled
+ @param clockBit[in] Bit of data pin - Pin if fast digital write is disabled
+ */
+void fio_shiftOut(fio_register dataRegister, fio_bit dataBit, fio_register clockRegister, fio_bit clockBit, uint8_t value);
+
+/*!
+ @method
+ @abstract faster shift out clear
+ @discussion using fast digital write
+ @discussion falls back to normal digitalWrite if fastio is disabled
+ @param dataRegister[in] Register of data pin - ignored if fast digital write is disabled
+ @param dataBit[in] Bit of data pin - Pin if fast digital write is disabled
+ @param clockRegister[in] Register of data pin - ignored if fast digital write is disabled
+ @param clockBit[in] Bit of data pin - Pin if fast digital write is disabled
+ */
+void fio_shiftOut(fio_register dataRegister, fio_bit dataBit, fio_register clockRegister, fio_bit clockBit);
+
+/*!
+ * @method
+ * @abstract one wire shift out
+ * @discussion protocol needs initialisation (fio_shiftOut1_init)
+ * @param shift1Register[in] pins register
+ * @param shift1Bit[in] pins bit
+ * @param value[in] value to shift out, last byte is ignored and always shifted out LOW
+ */
+void fio_shiftOut1(fio_register shift1Register, fio_bit shift1Bit, uint8_t value);
+/*!
+ * @method
+ * @abstract initializes one wire shift out protocol
+ * @discussion Puts pin to HIGH state and delays until Capacitors are charged.
+ * @param shift1Register[in] pins register
+ * @param shift1Bit[in] pins bit
+ */
+void fio_shiftOut1_init(fio_register shift1Register, fio_bit shift1Bit);
+
+#endif // FAST_IO_H
 #endif
 
 #include <inttypes.h>
-#include <../Wire/Wire.h>
-#include <I2CIO.h>
+#include "../Wire/Wire.h"
+#include "I2CIO.h"
 
 // CLASS VARIABLES
 // ---------------------------------------------------------------------------
 
 //
 // PRIVATE METHODS
-// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
 #else
 #include <Arduino.h>
 #endif
-#include <LCD.h>
+#include "LCD.h"
 
 // CLASS CONSTRUCTORS
 // ---------------------------------------------------------------------------

LiquidCrystal.cpp

 #else
 #include <Arduino.h>
 #endif
-#include <LiquidCrystal.h>
+#include "LiquidCrystal.h"
 
 // STATIC helper routines
 // ---------------------------------------------------------------------------
 #define LiquidCrystal_4bit_h
 
 #include <inttypes.h>
-#include <LCD.h>
+#include "LCD.h"
 
 
 /*!

LiquidCrystal_I2C.cpp

 #include <Arduino.h>
 #endif
 #include <inttypes.h>
-#include <I2CIO.h>
-#include <LiquidCrystal_I2C.h>
+#include "I2CIO.h"
+#include "LiquidCrystal_I2C.h"
 
 
 

LiquidCrystal_I2C.h

 #define LiquidCrystal_I2C_h
 #include <inttypes.h>
 #include <Print.h>
-#include <I2CIO.h>
-#include <LCD.h>
+#include "I2CIO.h"
+#include "LCD.h"
 
 // flags for backlight control
 #define LCD_BACKLIGHT   0x00

LiquidCrystal_SR.cpp

 //  Original project homepage: http://code.google.com/p/arduinoshiftreglcd/
 //
 // History
+// 2012.01.16  flo - faster digitalWrite/shiftOut
 // 2011.10.29  fmalpartida - adaption of the library to the LCD class hierarchy.
 // 2009.05.23  raron - but; based mostly (as in almost verbatim) on the 
 //             "official" LiquidCrystal library.
 #else
 #include <Arduino.h>
 #endif
-#include <LiquidCrystal_SR.h>
+#include "LiquidCrystal_SR.h"
+
+#include "FastIO.h"
 
 // When the display powers up, it is configured as follows:
 //
 {
    // Initialise private variables
    _two_wire    = 0;
-   _srdata_pin  = srdata; 
-   _srclock_pin = srclock; 
-   _enable_pin  = enable;
-   
-   if (enable == TWO_WIRE)
-   {
-      _enable_pin = _srdata_pin;
+
+   _srDataRegister = fio_pinToOutputRegister(srdata);
+   _srDataBit = fio_pinToBit(srdata);
+   _srClockRegister = fio_pinToOutputRegister(srclock);
+   _srClockBit = fio_pinToBit(srclock);
+
+   if (enable == TWO_WIRE){
       _two_wire   = 1;
+      _srEnableRegister = _srDataRegister;
+      _srEnableBit = _srDataBit;
+   }else{
+      _srEnableRegister = fio_pinToOutputRegister(enable);
+      _srEnableBit = fio_pinToBit(enable);
    }
-   
+
    // Configure control pins as outputs
    // ------------------------------------------------------------------------
-   pinMode(_srclock_pin, OUTPUT);
-   pinMode(_srdata_pin, OUTPUT);
-   pinMode(_enable_pin, OUTPUT);
-   
+
    _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x10DOTS;
 }
 
    // ----------------------------------------------
    if ( _two_wire ) 
    {
-      shiftOut ( _srdata_pin, _srclock_pin, MSBFIRST, 0x00 );
+	   fio_shiftOut(_srDataRegister, _srDataBit, _srClockRegister, _srClockBit);
    }
-   digitalWrite( _enable_pin, LOW );
    
    mode = mode ? SR_RS_BIT : 0; // RS bit; LOW: command.  HIGH: character.
    val1 = mode | SR_EN_BIT | ((value >> 1) & 0x78); // upper nibble
    val2 = mode | SR_EN_BIT | ((value << 3) & 0x78); // lower nibble
    
-   shiftOut ( _srdata_pin, _srclock_pin, MSBFIRST, val1 );
+   fio_shiftOut(_srDataRegister, _srDataBit, _srClockRegister, _srClockBit, val1);
    
-   digitalWrite( _enable_pin, HIGH );
+   fio_digitalWrite(_srEnableRegister, _srEnableBit, HIGH);
    waitUsec( 1 );                 // enable pulse must be >450ns
-   digitalWrite( _enable_pin, LOW );
+   fio_digitalWrite(_srEnableRegister, _srEnableBit, LOW);
 
    // clear shiftregister
    // ---------------------------
    if ( _two_wire ) 
    {
-      shiftOut ( _srdata_pin, _srclock_pin, MSBFIRST, 0x00 ); 
+	   fio_shiftOut(_srDataRegister, _srDataBit, _srClockRegister, _srClockBit);
    }
-   shiftOut ( _srdata_pin, _srclock_pin, MSBFIRST, val2 );
+   fio_shiftOut(_srDataRegister, _srDataBit, _srClockRegister, _srClockBit, val2);
    
-   digitalWrite( _enable_pin, HIGH );
+   fio_digitalWrite(_srEnableRegister, _srEnableBit, HIGH);
    waitUsec( 1 );                 // enable pulse must be >450ns
-   digitalWrite( _enable_pin, LOW );
+   fio_digitalWrite(_srEnableRegister, _srEnableBit, LOW);
    waitUsec( 40 );                // commands need > 37us to settle
 }
 
    // --------------------------
    if ( _two_wire ) 
    {
-      shiftOut ( _srdata_pin, _srclock_pin, MSBFIRST, 0x00 ); 
+	   fio_shiftOut(_srDataRegister, _srDataBit, _srClockRegister, _srClockBit);
    }
-   digitalWrite( _enable_pin, LOW );
+   fio_digitalWrite(_srEnableRegister, _srEnableBit, LOW);
    
    val1 = SR_EN_BIT | ((value >> 1) & 0x78);
-   shiftOut ( _srdata_pin, _srclock_pin, MSBFIRST, val1 );
+   fio_shiftOut(_srDataRegister, _srDataBit, _srClockRegister, _srClockBit, val1);
+
    
-   digitalWrite( _enable_pin, HIGH );
+   fio_digitalWrite(_srEnableRegister, _srEnableBit, HIGH);
    waitUsec( 1 );                 // enable pulse must be >450ns
-   digitalWrite( _enable_pin, LOW );
+   fio_digitalWrite(_srEnableRegister, _srEnableBit, LOW);
    
    waitUsec( 40 );               // commands need > 37us to settle
 }
-
-
-

LiquidCrystal_SR.h

 #define _LIQUIDCRYSTAL_SR_
 
 #include <inttypes.h>
-#include <LCD.h>
+#include "LCD.h"
+#include "FastIO.h"
 
 
 // two-wire indicator constant
    uint8_t _srclock_pin; // Clock Pin
    uint8_t _enable_pin;  // Enable Pin
    uint8_t _two_wire;    // two wire mode
+
+   fio_register _srDataRegister; // Serial Data pin
+   fio_bit _srDataBit;
+   fio_register _srClockRegister; // Clock Pin
+   fio_bit _srClockBit;
+   fio_register _srEnableRegister; // Enable Pin
+   fio_bit _srEnableBit;
+
 };
 
 #endif

examples/HelloWorld_SR/HelloWorld_SR.ino

+#include <LiquidCrystal_SR.h>
+
+LiquidCrystal_SR lcd(8,7,TWO_WIRE);
+//                   | |
+//                   | \-- Clock Pin
+//                   \---- Data/Enable Pin
+
+// Creat a set of new characters
+byte armsUp[8] = {0b00100,0b01010,0b00100,0b10101,0b01110,0b00100,0b00100,0b01010};
+byte armsDown[8] = {0b00100,0b01010,0b00100,0b00100,0b01110,0b10101,0b00100,0b01010};
+
+void setup(){
+
+  lcd.begin(16,2);               // initialize the lcd
+
+  lcd.createChar (0, armsUp);    // load character to the LCD
+  lcd.createChar (1, armsDown);    // load character to the LCD
+
+  lcd.home ();                   // go home
+  lcd.print(F("LiquidCrystal_SR"));
+}
+
+void loop(){
+  // Do a little animation
+  for(int i = 0; i <= 15; i++) showHappyGuy(i);
+  for(int i = 15; i >= 0; i--) showHappyGuy(i);
+}
+
+void showHappyGuy(int pos){
+  lcd.setCursor ( pos, 1 ); // go to position
+  lcd.print(char(random(0,2))); // show one of the two custom characters
+  delay(150); // wait so it can be seen
+  lcd.setCursor ( pos, 1 ); // go to position again
+  lcd.print(F(" ")); // delete character
+}
 # Datatypes (KEYWORD1)
 ###########################################
 
+LiquidCrystal_SR	 KEYWORD1
 LiquidCrystal_I2C    KEYWORD1
 LiquidCrystal        KEYWORD1
 LCD                  KEYWORD1