Commits

f...@hp-work  committed 1edad34

"SWITCHTO" FIO_FALLBACK performance tweaks, shift1 Comments

  • Participants
  • Parent commits 91feec1
  • Branches fastIO

Comments (0)

Files changed (4)

 //
 // TODO:
 //  support chipkit (https://github.com/chipKIT32/chipKIT32-MAX/blob/master/hardware/pic32/cores/pic32/wiring_digital.c)
+// maybe improve fio_digitalRead
 
 #include "FastIO.h"
 
 }
 
 void fio_shiftOut(fio_register dataRegister, uint8_t dataBit, fio_register clockRegister, uint8_t clockBit){
-	// shift out 0x0 (B00000000) fast
+	// shift out 0x0 (B00000000) fast, byte order is irrelevant
 	fio_digitalWrite_LOW(dataRegister, dataBit);
 	for(uint8_t i = 0; i<8; ++i){
 		fio_digitalWrite_HIGH(clockRegister, clockBit);
 	/*
 	 * this function are based on Shif1 protocol developed by Roman Black (http://www.romanblack.com/shift1.htm)
 	 *
-	 * test sketch: http://pastebin.com/raw.php?i=2hnC9v2Z
-	 * tested with: TPIC6595N
+	 * test sketches:
+	 * 	http://pastebin.com/raw.php?i=2hnC9v2Z
+	 * 	http://pastebin.com/raw.php?i=bGg4DhXQ
+	 * 	http://pastebin.com/raw.php?i=tg1ZFiM5 - flickering neighbor
+	 * tested with:
+	 * 	TPIC6595N - seems to work fine (circuit: http://www.3guys1laser.com/arduino-one-wire-shift-register-prototype)
+	 * 	7HC595N - flickering neighbor
 	 */
 
 	// disable interrupts since timing is going to be critical
 	oldSREG = SREG;
 	cli();
 
-	// iterate but ignore last byte (must be LOW)
-	for(int8_t i = 7; i>0; --i){
+	// iterate but ignore last bit (is it correct now?)
+	for(int8_t i = 7; i>=1; --i){
 
-		// assume that pin is HIGH (smokin' pot all day... :)
+		// assume that pin is HIGH (smokin' pot all day... :) - requires initialization
 		if(LOW==!!(value & (1 << i))){
 			// LOW = 0 Bit
-			fio_digitalWrite_SWITCH(shift1Register,shift1Bit);
+			fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,LOW);
 			// hold pin LOW for 15us
 			delayMicroseconds(15);
-			fio_digitalWrite_SWITCH(shift1Register,shift1Bit);
+			fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,HIGH);
 			// hold pin HIGH for 30us
 			delayMicroseconds(30);
 		}else{
 			// HIGH = 1 Bit
-			fio_digitalWrite_SWITCH(shift1Register,shift1Bit);
+			fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,LOW);
 			//hold pin LOW for 1us - done! :)
-			fio_digitalWrite_SWITCH(shift1Register,shift1Bit);
+			fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,HIGH);
 			//hold pin HIGH for 15us
 			delayMicroseconds(15);
 		}
 	}
 	// send last bit (=LOW) and Latch command
-	fio_digitalWrite_LOW(shift1Register,shift1Bit);
+	fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,LOW);
 	// Hold pin low for 200us
-	delayMicroseconds(200);
+	delayMicroseconds(199);
 	fio_digitalWrite_HIGH(shift1Register,shift1Bit);
-	// Hold pin high for 300us and leave it that way
-	delayMicroseconds(300);
+	// Hold pin high for 300us and leave it that way - using explicit HIGH here, just in case.
+	delayMicroseconds(299);
 
 	// enable interrupts
 	SREG = oldSREG;
 void fio_shiftOut1(uint8_t pin, uint8_t value){
 	fio_shiftOut1(fio_pinToOutputRegister(pin, SKIP),fio_pinToBit(pin),value);
 }
-
 // __attribute__ ((always_inline)) /* let the optimizer decide that for now */
 void fio_digitalWrite(fio_register pinRegister, fio_bit pinBit,uint8_t value);
 
+/**
+ * This is where the magic happens that makes things fast.
+ * Implemented as preprocessor directives to force inlining
+ * SWITCH is fast for FIO but probably slow for FIO_FALLBACK so SWITCHTO is recommended if the value is known.
+ */
+
 #ifndef FIO_FALLBACK
 #define fio_digitalWrite_LOW(reg,bit) *reg &= ~bit
+#define fio_digitalWrite_HIGH(reg,bit) *reg |= bit
 #define fio_digitalWrite_SWITCH(reg,bit) *reg ^= bit
-#define fio_digitalWrite_HIGH(reg,bit) *reg |= bit
+#define fio_digitalWrite_SWITCHTO(reg,bit,val) fio_digitalWrite_SWITCH(reg,bit)
 #else
-// reg -> dummy, bit -> pin
+// reg -> dummy NULL, bit -> pin
 #define fio_digitalWrite_HIGH(reg,bit) digitalWrite(bit,HIGH)
+#define fio_digitalWrite_LOW(reg,bit) digitalWrite(bit,LOW)
 #define fio_digitalWrite_SWITCH(reg,bit) digitalWrite(bit, !digitalRead(bit))
-#define fio_digitalWrite_LOW(reg,bit) digitalWrite(bit,LOW)
+#define fio_digitalWrite_SWITCHTO(reg,bit,val) digitalWrite(bit,val);
 #endif
 
 /*!

File LiquidCrystal_SR.cpp

    // to read the Enable pulse, and then reads the new contents of the SR.
    fio_digitalWrite_HIGH(_srEnableRegister, _srEnableBit);
    waitUsec( 1 );                 // enable pulse must be >450ns
-   fio_digitalWrite_SWITCH(_srEnableRegister, _srEnableBit);
+   fio_digitalWrite_SWITCHTO(_srEnableRegister, _srEnableBit,LOW);
 
    // clear shiftregister
    // ---------------------------
    fio_shiftOut(_srDataRegister, _srDataBit, _srClockRegister, _srClockBit, val2, MSBFIRST);
    
    // LCD ENABLE PULSE, se above comment
-   fio_digitalWrite_HIGH(_srEnableRegister, _srEnableBit);
+   fio_digitalWrite_SWITCHTO(_srEnableRegister, _srEnableBit,HIGH);
    waitUsec( 1 );                 // enable pulse must be >450ns
-   fio_digitalWrite_SWITCH(_srEnableRegister, _srEnableBit);
+   fio_digitalWrite_SWITCHTO(_srEnableRegister, _srEnableBit,LOW);
    waitUsec( 40 );                // commands need > 37us to settle
 }
 

File LiquidCrystal_SR_LCD3.cpp

    // Make new data active.
    fio_digitalWrite_HIGH(_strobe_register, _strobe_bit);
    waitUsec( 1 ); // strobe pulse must be >450ns (old code had 10ms)
-   fio_digitalWrite_SWITCH(_strobe_register, _strobe_bit);
+   fio_digitalWrite_SWITCHTO(_strobe_register, _strobe_bit,LOW);
    waitUsec( 40 ); // commands need > 37us to settle
 }