There is very little on this nuanced use, so I will share my findings:
I am creating a 16 bit, 128 instruction, 16 step, 10 flag breadboard computer inspired by Ben Eater's design. For my control logic, I am using a (4) 32 Mbit (2Mb x16) UV EPROM chips to yield 64 control bits from 21 address bits. This means I will have to program 8 Million addresses (4 chips x 16 bits ea.). This task requires (14) 4 bit shift registers to setup the data for each write.
My method is to read one char at a time from a PC c++ program and shift that char into the appropriate register set. I am doing this by using PORTC as a serial out shift register.
I set the LSB (pin A0) of PORTC as a digital output
I set PORTC = the current char (ex./ 0b10011001)
I shift the value at the A0 pin into the serial input of the 74LS194 shift register
I shift PORTC right 1 bit and repeat.
This outputs the bits serially on pin A0
The problem occurred when I shifted to the 8th bit: It was always 0.
After a lot of research, I deduced only the first 7 bits were valid.
My solution was to shift out 7 bits, then set PORTC = currentChar >> 7 when sending the final bit, placing the MSB of currentChar into the LSB of PORTC for the final shift out.
By doing this, it was possible to preserve the MSB that was being lost when writing the whole byte to PORTC.
I understand the 2 MSB's of PORTC are not connected to any pins, but I ask the community, does anyone have any insight as to why the MSB of PORTC seems to be always 0 when writing at byte to that port? Why only the first 7 bits are written to the register?
Post some minimal code that illustrates your problem. Then we can might see what is going wrong.
My question is why you can't make the entire port be output bits. I don't yet see that it would be a problem, but that is the only thing that seens odd.
My first concern would be, are you absolutely positive there is nothing in your data path that is suppressing the eighth bit of the char? No conversion through, for example, a signed 8 bit int? Because that would do it, if mishandled.
These things are best tested with unique patterns, like 0xAA, 0X55, 0XA5, 0X5A, to ensure manipulation is robust.
Forgive me if this is well known to you, but this is your first visit, so you are an unknown quantity to us, and we see a very high proportion of beginners who take on projects beyond their skill level.
Meanwhile I've been failing to get a test sketch to work that cycles all 256 byte values shifting each 8 times... I guess it's tired and I'm getting late.
And bit 6 is... RESET, it seems. So the OP's report seems mysterious.
People tend to think of the IO SFRs as normal memory that happens to appear on pins, but that's not actually the case - there is special purpose hardware that may or may not implement all of the bits.
PC6 is available as a digital IO if you disable RESET, so that explains why it exists.
I don't understand why you're shifting PORTC instead of some internal variable that is then sent to only one of the bits (the way shiftOut works (only faster, with direct IO.))
That clarifies, who would have thought I should read the datasheet... I chose that method as an opportunity to get some experience with port manipulation mainly, and to experiment with execution times of large data sets, I'll try shiftOut and digitalWrite and compare the times. Code upload soon, it is working currently
A snippet, as it currently works, reads serial chars from the COM port and shifts them into 74LS194's
uint8_t getByte() {
while (!Serial.available()) {
//wait for data
}
return static_cast<uint8_t>(Serial.read());//should always be less than 256, can fit in byte
}
void sendBitAddReg() {
digitalWrite(ADDRCLK, HIGH);
digitalWrite(ADDRCLK, LOW);
PORTC = PORTC >> 1;
}
void loop() {
//=======send address word to register======= 24 bits as 3 bytes
for (int i = 0; i < 3; i++){
//Receive 1 byte and cast into uint8_t, from int from serial read
currentByte = getByte();
//load byte to port c register
PORTC = currentByte;
//with output pin as lsb of PORT byte, clock external register, send 8 bits
for (int j = 0; j < 7; j++) {
sendBitAddReg(); //send current LSB then shift byte once, loop for 7 of 8 bits
}
//this has to be done because PORTC's 8th bit will not retain an assigned value
//so send 8th bit by setting PORTC to currentByte shifted 7 and clocking bit
PORTC = currentByte >> 7;
digitalWrite(ADDRCLK, HIGH);
digitalWrite(ADDRCLK, LOW);
}
shiftout on most Arduino cores uses digitalWrite(), so it's pretty slow.
I had in mind something like:
for (byte i =0; i<7; i++) { // for 8 bits
if ((data & 1) == 1) { // Check the data bit
PORTC |= 1 << DATAPIN; // and set output pin as appropriate
} else {
PORTC &= ~(1 << DATAPIN);
}
ADDRCLKPORT |= 1 << ADDRCLKPIN; // toggle clock
ADDRCLKPORT &= ~(1 << ADDRCLKPIN); // toggle clock
data >>= 1; // shift data so the next bit is in place.
}
(Note that checking the bit and doing either operation is going to be faster than reading the port, changing the bit, and writing it back out.)
If we can run this to ground, I will sleep better, even if the OP has been provided a superior solution rendering the issue moot.
I've looked at the datasheet and it looks like the port output register can function as a general purpose 7 bit register and still allow use of bit 6 as an input that is by default hooked to RESET.
But I've been mislead by confident evidently incorrect assertions elsewhere (not the fora).
Ya I find that interesting that bit 6 has not caused any issue yet using it in such a way, I have tested this with delays and LED's on the 74LS194 output and can confirm integrity of the data even after 30KB has been passed through, and haven't noticed any signs of resets.
Maybe has something to do with 0's shifting in from the left...more research and experiments added to the queue