Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for reading from CD74HC165 shift-in register #408

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

reznet
Copy link

@reznet reznet commented Feb 27, 2021

This adds support for reading from the digital inputs on a CD74HC165 shift-in register. I based this on the multiplexer code and tested it in my own Arduino code. I'm on a Mac, so some of the build commands did not work and I added Mac equivalents to tasks.json. However, the arduino-example-builder exe does not run on Mac and I could not find a Mac equivalent.

the implementation uses bitRead and shiftIn from the Arduino library and compiles fine, but when trying to add tests, these are not defined. should they be? or do we need our own implementation of these methods?

as is, the test class is not useful - it's a placeholder. I'm happy to flesh it out when the missing Arduino methods are solved.

Copy link
Owner

@tttapa tttapa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your contribution!

I cannot merge this pull request here, the Arduino-Helpers code is maintained separately, so I would have to merge that upstream.

I've added some comments, but don't feel obligated to fix them, I have an old local shift register input class stashed somewhere that's still waiting for me to order some hardware to test it, so I could always push that.

@@ -17,6 +17,19 @@
"isDefault": true,
},
},
{
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tasks should use operating system specific options within a single task rather than having multiple tasks for different operating systems.

*/
void begin() override;

void read();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function doesn't have a definition.

const pin_t clockEnablePin;
const pin_t loadPin;

uint8_t buffer;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This buffer should have enough space to store N bits, not just 8. It should probably be an AH::BitArray<N>, like the ShiftRegisterOut class.


template <uint8_t N>
int ShiftRegisterIn<N>::digitalRead(pin_t pin) {
return bitRead(buffer, pin);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bitRead cannot address N bits, this should be a read from the AH::BitArray<N>.


template <uint8_t N>
void ShiftRegisterIn<N>::pinMode(pin_t, PinMode_t mode) {
ExtIO::pinMode(dataPin, mode);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When do you have to change the mode of the data pin? AFAIK, shift registers have push/pull data outputs, so INPUT_PULLUP should never be necessary. Even if INPUT_PULLUP were necessary, it would have to be in a different method, the pinMode() method should change the modes of the input of the IO extender, not the data pins.


// ISSUE: shiftIn is available when building for Arduino but not when
// running tests
buffer = shiftIn(dataPin, clockPin, LSBFIRST);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally, this would use an ExtIO version of shiftIn(), similar to

void shiftOut(pin_t dataPin, pin_t clockPin, BitOrder_t bitOrder, uint8_t val) {
// Native version
if (isNativePin(dataPin) && isNativePin(clockPin)) {
::shiftOut((int)dataPin, (int)clockPin, bitOrder, val);
}
// ExtIO version
else if (!isNativePin(dataPin) && !isNativePin(clockPin)) {
auto dataEl = getIOElementOfPin(dataPin);
auto dataPinN = dataPin - dataEl->getStart();
auto clockEl = getIOElementOfPin(clockPin);
auto clockPinN = clockPin - clockEl->getStart();
for (uint8_t i = 0; i < 8; i++) {
uint8_t mask = bitOrder == LSBFIRST ? (1 << i) : (1 << (7 - i));
dataEl->digitalWrite(dataPinN, (val & mask) ? HIGH : LOW);
clockEl->digitalWrite(clockPinN, HIGH);
clockEl->digitalWrite(clockPinN, LOW);
}
}
// Mixed version (slow)
else {
for (uint8_t i = 0; i < 8; i++) {
uint8_t mask = bitOrder == LSBFIRST ? (1 << i) : (1 << (7 - i));
digitalWrite(dataPin, (val & mask) ? HIGH : LOW);
digitalWrite(clockPin, HIGH);
digitalWrite(clockPin, LOW);
}
}
}
void shiftOut(int dataPin, int clockPin, BitOrder_t bitOrder, uint8_t val) {
::shiftOut(arduino_pin_cast(dataPin), arduino_pin_cast(clockPin), bitOrder,
val);
}

I'll see if I can add one.

I believe the bit order should be a parameter, similar to ShiftRegisterOut.

}

template <uint8_t N>
void ShiftRegisterIn<N>::updateBufferedInputs() {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the datasheet:

For predictable operation the LOW-to-HIGH transition of CE should only take place while CP is HIGH. Also, CP and CE should be LOW before the LOW-to-HIGH transition of PL to prevent shifting the data when PL goes HIGH.

I don't believe this is satisfied here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants