Custom port write function, save port?

We all know the 595 shift registers and the arduino "shiftOut" function. Lets imagine you have the same thing, but with 64 Outputs and different polarity. I'm trying to make a libary to control a 64bit shitregister.

If i use "digitalWrite(x,x)" for this, the shifting progress is way to slow, so its not an option. I've implemented the following function:

#define thePort PORTD         //define Hardware port where Shift-Registers are connected
#define DATA PD5              //define Dataline
#define OE 6                  //define latch pin
#define CLK PD7               //define clockline

void setOutputs(unsigned long val_one, unsigned long val_two) { //Function to shift out 2 x 32bit fast void setOutputs(unsigned long val_one, unsigned long val_two) { //Function to shift out 2 x 32bit fast enough to prevent flicker!

	// ------------WARNING!--------------------
	// This functions operates directly on ports, not via digitalWrite()
	// because digitalWrite() would be to slow, and display would flicker
	// if different pins are used, you maybe hav to change the variable "thePort"
	// to the matching I/O port letter of the controller!

	digitalWrite(OE, LOW); //Disable Outputs to prevent flicker

	//Send first 32-bit variable value

	for (int i = 0; i < 32; i++) {
		thePort &= ~_BV(DATA);  //Data LOW
		if ( bitRead(val_one, i) == 1) {
			thePort |= _BV(DATA);  //Data HIGH
		}
		thePort |= _BV(CLK);  //CLK HIGH
		thePort &= ~_BV(CLK); //CLK LOW
	}

	//Send second 32-bit variable value
	for (int i = 0; i < 32; i++) {
		thePort &= ~_BV(DATA);  //Data LOW
		if ( bitRead(val_two, i) == 1) {
			thePort |= _BV(DATA);  //Data HIGH
		}
		thePort |= _BV(CLK);  //CLK HIGH
		thePort &= ~_BV(CLK); //CLK LOW
	}
	digitalWrite(OE, HIGH); //Enable Outputs

}

This function works fine, but relys on a defined port and pin instead of a library call.

I looked at the digitalWrite code - here is what happens:

void digitalWrite(uint8_t pin, uint8_t val)
{
	uint8_t timer = digitalPinToTimer(pin);
	uint8_t bit = digitalPinToBitMask(pin);
	uint8_t port = digitalPinToPort(pin);
	volatile uint8_t *out;

	if (port == NOT_A_PIN) return;

	// If the pin that support PWM output, we need to turn it off
	// before doing a digital write.
	if (timer != NOT_ON_TIMER) turnOffPWM(timer);

	out = portOutputRegister(port);

	uint8_t oldSREG = SREG;
	cli();

	if (val == LOW) {
		*out &= ~bit;
	} else {
		*out |= bit;
	}

	SREG = oldSREG;
}

Now my approach was to only run the conversion to port once and save the port, i tied the following:

lib.h

class HVSR {

public:
	HVSR(uint8_t clkPin, uint8_t dataPin, uint8_t enPin);
	void setOutputs(uint32_t firstv, uint32_t secondv);
private:

	volatile uint8_t *theDataPort;
	volatile uint8_t *theClkPort;
	uint8_t theDataPin;
	uint8_t theClkPin;
	uint8_t theEnPin;

};

constructor

HVSR::HVSR(uint8_t clkPin, uint8_t dataPin, uint8_t enPin){

	//***

	//***Set pin states***********
	pinMode(clkPin,OUTPUT);											//Set Clock-Pin to Output
	pinMode(dataPin,OUTPUT);										//Set Data-Pin to Output
	pinMode(enPin,OUTPUT);											//Set Chip-Enable-Pin to Output

	//***Convert pins to MCU native values for fast shifting****
	theClkPort = portOutputRegister(digitalPinToPort(clkPin));							//get the port of the given pin
	theDataPort = portOutputRegister(digitalPinToPort(dataPin));						//get the port of the given pin
	theClkPin = digitalPinToBitMask(clkPin);						//get the bit of the selected pin
	theDataPin = digitalPinToBitMask(dataPin);						//get the bit of the selected pin
	theEnPin=enPin;
	digitalWrite(enPin,HIGH);

}

shift function

void HVSR::setOutputs(uint32_t firstv, uint32_t secondv){



	cli();
	digitalWrite(theEnPin, LOW); //Disable Outputs to prevent flicker

		//Send first 32-bit variable value

		for (int i = 0; i < 32; i++) {
			theDataPort &= ~_BV(theDataPin);  //Data LOW
			if ( bitRead(firstv, i) == 1) {
				theDataPort |= _BV(theDataPin);  //Data HIGH
			}
			theClkPort |= _BV(theClkPin);  //CLK HIGH
			theClkPort &= ~_BV(theClkPin); //CLK LOW
		}

		//Send second 32-bit variable value
		for (int i = 0; i < 32; i++) {
			theDataPort &= ~_BV(theDataPin);  //Data LOW
			if ( bitRead(secondv, i) == 1) {
				theDataPort |= _BV(theDataPin);  //Data HIGH
			}
			theClkPort |= _BV(theClkPin);  //CLK HIGH
			theClkPort &= ~_BV(theClkPin); //CLK LOW
		}
		digitalWrite(theEnPin, HIGH); //Enable Outputs
		sei();

}

i tried to copy the content of the digitalWrite() to my own lib, but sadly i cant compile. I'm getting the following errors (multiple, but only posted here)

..\HVShift.cpp:63:15: error:   in evaluation of 'operator|=(volatile uint8_t* {aka volatile unsigned char*}, int)'
..\HVShift.cpp:64:15: error: invalid operands of types 'volatile uint8_t* {aka volatile unsigned char*}' and 'int' to binary 'operator&'
    theClkPort &= ~_BV(theClkPin); //CLK LOW

Has anyone here an idea how to fix and explain me what i'm doing wrong?

(deleted)

spycatcher2k:
You could just use the SPI pins & Library!

Yes, but the idea is to create a library to use on all pins of the arduino...

push

sgt_johnny:
push

That's REALLY not appreciated on this forum. If you don't get answers then add more detail. There is enough traffic here that you don't need to bump threads just to get them to the top. Especially after only a few hours. If you're down on page three or four maybe. But not this. Around here if you are getting ignored then there is usually a reason for that and bumping your thread will only make it worse.

theClkPort &= ~_BV(theClkPin);

theClkPort is a pointer. You have to treat it like a pointer.

*theClkPort &= ~_BV(theClkPin);