/* BigIOinput.cpp - Read parallel to serial input BigIOinput *PRELIMINARY* Arduino library Copyright (c) 2011 Devon Sean McCullough Licensed under the GPL (GNU Public License) 2011 Jul 22 Fri 00:25 EDT Devon BigIOinput sketch into library HARDWARE Arduino <===> MotherBoard Shield <===> Mama's BIG-IO-input digital outputs to Shift, Clock optional digital output normally wired low to Inhibit digital input from Qh BUGS not tested yet POSSIBLE VARIATIONS default wiring map map datatype with length so it can repeat replace unsigned long long with a more economical type http://focus.ti.com/docs/prod/folders/print/sn74hc165.html SN54HC165 SN74HC165 www.ti.com SCLS116F - DECEMBER 1982 - REVISED DECEMBER 2010 8-BIT PARALLEL-LOAD SHIFT REGISTERS * Wide Operating Voltage Range of 2 V to 6 V * Outputs Can Drive Up To 10 LSTTL Loads * Low Power Consumption, 80-µA Max Icc * Typical tpd = 13 ns * ±4-mA Output Drive at 5 V * Low Input Current of 1 µA Max * Complementary Outputs * Direct Overriding Load (Data) Inputs * Gated Clock Inputs * Parallel-to-Serial Data Conversion SN54HC165...J OR W PACKAGE SN74HC165...D, DB, N, NS, OR PW PACKAGE (TOP VIEW) +-----__-----+ SH/~LD | 1 16 | VCC CLK | 2 15 | CLK INH E | 3 14 | D F | 4 13 | C G | 5 12 | B H | 6 11 | A ~QH | 7 10 | SER GND | 8 9 | QH +------------+ http://www.arduino.cc/en/Tutorial/ShiftIn Arduino specific article on a similar chip. http://www.SamuraiCircuits.com/MotherboardShield Mama Shield socket (top view) +--------+ ARef |] [| V-In +3.3V |] [| Reset A0 |] [| D13 A1 |] [| D12 A2 |] [| D11 A3 |] [| D10 A4 |] [| D9 A5 |] [| D8 Bus1 |] [| D7 Bus2 |] [| D6 GND |] [| GND |========| Bus3 |] [| D5 Bus4 |] [| D4 Bus5 |] [| D3 Bus6 |] [| D2 Bus7 |] [| D1 Bus8 |] [| D0 +5V |] [| +5V +--------+ */ #include "WProgram.h" #include "BigIOinput.h" BigIOinput::BigIOinput(int size, byte shift, byte clock, byte qh) { _size = size; _shift = shift; _clock = clock; _qh = qh; _position = _size; pinMode(_shift, OUTPUT); digitalWrite(_shift, HIGH); pinMode(_clock, OUTPUT); digitalWrite(_clock, LOW); pinMode(_qh, INPUT); } void BigIOinput::load() { // Arduino clock 16MHz = 62.5ns > 20ns @ 4.5Vcc tw SH/~LD low min pulse duration // (SN74HC165 datasheet page 6) therefore no explicit delay _position = 0; digitalWrite(_shift, LOW); digitalWrite(_shift, HIGH); } boolean BigIOinput::shift() { return BigIOinput::shift(1); } BigIO_t BigIOinput::shift(int size) { // Lowest-order bit maps to lowest numbered hardware pin // so the bit-to-pin map is unchanged over size changes, // e.g., daisy-chained cards further from the Arduino // may be added and removed without affecting closer cards. // Arduino clock 16MHz = 62.5ns > 38ns @ 4.5Vcc tpd CLK to Qh max propagation delay // (SN74HC165 datasheet page 7) therefore no explicit delay // Bit position 0 is available immediately after load with no further clocking. BigIO_t data = 0, mask = 1; while (size--) { if (_position++) { digitalWrite(_clock, HIGH); digitalWrite(_clock, LOW); } if (digitalRead(_qh)) data |= mask; mask <<= 1; } return data; } boolean BigIOinput::read(int position) { // read a single bit at the given position // read calls reload and shift only as necessary // i.e., no load if bit(s) already in register if (_position >= position) BigIOinput::load(); if (_position < position) BigIOinput::shift(position - _position); return BigIOinput::shift(); } BigIO_t BigIOinput::read(int size, int position) { // read size bits at the given position if (_position >= position) BigIOinput::load(); if (_position < position) BigIOinput::shift(position - _position); return BigIOinput::shift(size); } void BigIOinput::read(int size, int position, byte *buffer) { // read size bits at the given position into buffer if (_position >= position) BigIOinput::load(); if (_position < position) BigIOinput::shift(position - _position); while (size > BIGIO_BITS_PER_BYTE) { size -= BIGIO_BITS_PER_BYTE; *buffer++ = BigIOinput::shift(BIGIO_BITS_PER_BYTE); } if (size) *buffer = BigIOinput::shift(size); } BigIO_t BigIOinput::read(int size, int position, const int *map) { // Read size bits at the given position and return value permuted by map. // Only bits mentioned in map are set, any others are zero. // Count bit positions from zero, from low to high order bits. BigIO_t bits = 0; while (size--) { boolean bit = BigIOinput::read(position++); int j = *map++; if (bit) bits |= 1LL << j; } return bits; } void BigIOinput::read(int size, int position, byte *buffer, const int *map) { // Read size bits at the given position into buffer permuted by map. // Only buffer bits mentioned in map are changed, any others stay the same. // Count bit positions from zero, // first from low to high order bits, // then from low to high numbered addresses. while (size--) { boolean bit = BigIOinput::read(position++); int ij = *map++; int i = ij / BIGIO_BITS_PER_BYTE; byte j = ij % BIGIO_BITS_PER_BYTE; if (bit) buffer[i] |= 1 << j; else buffer[i] &= ~(1 << j); } } // end BigIOinput.cpp