I'm currently trying to code a lower-lever bit shift register (74HC595) for Arduino Zero (that is based on SAMD21 Cortex M0).
I've already done a higher-level class with looks like that :
BitRegister.h
#ifndef BitRegister_h
#define BitRegister_h
#include "Arduino.h"
class BitRegister
{
public:
BitRegister(byte dataPin, byte clockPin, byte latchPin, uint8_t registerSize = 1);
void sendData(uint8_t led);
void shiftOut2(uint8_t bitOrder, uint8_t val);
private:
byte m_dataPin;
byte m_clockPin;
byte m_latchPin;
uint8_t m_registerSize; //allows register's cascade
};
#endif
BitRegister.cpp
#include "BitRegister.h"
//**************************************************************
BitRegister::BitRegister(byte dataPin,
byte clockPin,
byte latchPin,
uint8_t registerSize)
: m_dataPin(dataPin),
m_clockPin(clockPin),
m_latchPin(latchPin),
m_registerSize(registerSize) //Number of register (if cascade)
{
pinMode(m_dataPin, OUTPUT);
pinMode(m_clockPin, OUTPUT);
pinMode(m_latchPin, OUTPUT);
}
//**************************************************************
void BitRegister::sendData(uint8_t led)
{
led -= 1; //first LED is number 1
digitalWrite(m_latchPin, LOW);
for(int i = 1; i < m_registerSize + 1; i++){
int registerNumber = m_registerSize - i; //The number of the register we're working on in the loop
shiftOut(m_dataPin, m_clockPin, MSBFIRST, ~( 1 << (led - registerNumber*8) ) & 0xFF);
}
digitalWrite(m_latchPin, HIGH);
}
void BitRegister::shiftOut2(uint8_t bitOrder, uint8_t val)
{
uint8_t i;
for (i = 0; i < 8; i++) {
if (bitOrder == LSBFIRST)
digitalWrite(m_dataPin, !!(val & (1 << i)));
else
digitalWrite(m_dataPin, !!(val & (1 << (7 - i))));
digitalWrite(m_clockPin, HIGH);
digitalWrite(m_clockPin, LOW);
}
}
The problem is that I have to use it with many registers in cascade ant the shiftOut2
method (based on Arduino's shiftOut
method) is really slow (I think due to the multiple digitalWrite
).
So based on this SAMD21 Cortex M0 tutorial and on the Arduino Zero Pinout Diagram (below), I tried to create a lower-level of my bit shift register class.
The problem I'm currently facing is that I don't manage to rewrite the totality of my shiftOut2
method so for my test I have to write the ports numbers in hard directly in the method's body.
I connect my registers to Arduino's pins 10, 11 and 12 which are SAMD21 ports 18, 16 and 19.
The code of my class (which works) is the following :
LowBitRegister.h
is the same as BitRegister.h
(except class name and class constructor name).
LowBitRegister.cpp
#include "LowBitRegister.h"
//**************************************************************
LowBitRegister::LowBitRegister(byte dataPin,
byte clockPin,
byte latchPin,
uint8_t registerSize)
: m_dataPin(dataPin),
m_clockPin(clockPin),
m_latchPin(latchPin),
m_registerSize(registerSize) //Number of register (if cascade)
{
REG_PORT_DIR0 |= (1 << 18) | (1 << 19) | (1 << 16); //Set dataPin, clockPin and latchPin to OUTPUT
}
//**************************************************************
void LowBitRegister::sendData(uint8_t led)
{
led -= 1; //first LED is number 1
REG_PORT_OUT0 &= ~(1 << 16); //Set latchPin to LOW
for(int i = 1; i < m_registerSize + 1; i++){
int registerNumber = m_registerSize - i; //The number of the register we're working on in the loop
shiftOut2(MSBFIRST, ~( 1 << (led - registerNumber*8) ) & 0xFF);
}
REG_PORT_OUT0 |= (1 << 16); //Set latchPin to HIGH
}
void LowBitRegister::shiftOut2(uint8_t bitOrder, uint8_t val)
{
uint8_t i;
for (i = 0; i < 8; i++) {
if (bitOrder == LSBFIRST)
digitalWrite(m_dataPin, !!(val & (1 << i)));
else
digitalWrite(m_dataPin, !!(val & (1 << (7 - i))));
REG_PORT_OUT0 |= (1 << 19); //Set clockPin to HIGH
REG_PORT_OUT0 &= ~(1 << 19); //Set clockPin to LOW
}
}
As you can see, the only parts I don't manage to rewrite are :
digitalWrite(m_dataPin, !!(val & (1 << i)));
and
digitalWrite(m_dataPin, !!(val & (1 << (7 - i))));
If you have an idea to solve my problem I will be happy to read it.
Thank you!
I finally found a solution (but if you see any optimization I am interested) :
LowBitRegister.h
#ifndef LowBitRegister_h
#define LowBitRegister_h
#include "Arduino.h"
class LowBitRegister
{
public:
LowBitRegister(byte dataPin, byte clockPin, byte latchPin, uint8_t registerSize = 1); //Multiple registers cascade
void sendData(uint8_t led);
void lowShiftOut(uint8_t bitOrder, uint8_t val);
private:
byte m_dataPin;
byte m_clockPin;
byte m_latchPin;
uint8_t m_registerSize;
};
#endif
LowBitRegister.cpp
#include "LowBitRegister.h"
//**************************************************************
LowBitRegister::LowBitRegister(byte dataPin,
byte clockPin,
byte latchPin,
uint8_t registerSize)
: m_dataPin(dataPin),
m_clockPin(clockPin),
m_latchPin(latchPin),
m_registerSize(registerSize) //Number of register (if cascade)
{
REG_PORT_DIR0 |= (1 << m_dataPin) | (1 << m_clockPin) | (1 << m_latchPin); //Set dataPin, clockPin and latchPin to OUTPUT
}
//**************************************************************
void LowBitRegister::sendData(uint8_t led)
{
led -= 1; //first LED is number 1
REG_PORT_OUT0 &= ~(1 << m_latchPin); //Set latchPin to LOW
for(int i = 1; i < m_registerSize + 1; i++){
int registerNumber = m_registerSize - i; //The number of the register we're working on in the loop
lowShiftOut(MSBFIRST, ~( 1 << (led - registerNumber*8) ) & 0xFF);
}
REG_PORT_OUT0 |= (1 << m_latchPin); //Set latchPin to HIGH
}
void LowBitRegister::lowShiftOut(uint8_t bitOrder, uint8_t val)
{
uint8_t i;
for (i = 0; i < 8; i++) {
if (bitOrder == LSBFIRST){
if(val & (1 << i))
REG_PORT_OUT0 |= (1 << m_dataPin);
else
REG_PORT_OUT0 &= ~(1 << m_dataPin);
}
else {
if (val & (1 << (7 - i)))
REG_PORT_OUT0 |= (1 << m_dataPin);
else
REG_PORT_OUT0 &= ~(1 << m_dataPin);
}
REG_PORT_OUT0 |= (1 << m_clockPin); //Set clockPin to HIGH
REG_PORT_OUT0 &= ~(1 << m_clockPin); //Set clockPin to LOW
}
}