Need to convert array of bits into a byte?

Hello everyone I am building a 6502 8-bit computer on breadboards at the moment. I am monitoring the address lines on the MCU and I am short a couple of shift registers, so i have the first half of the 16-bit address bus hooked into an Arduino Uno via D2-D9. I have the second half running on a shift register. My problem is that I ether end up with a string of numbers or an array of 1s and 0s. I need to be able to convert the individual bits into a byte, then I can tell the arduino to output Hex as well. The shift register is working great, but until I get more I need to figure this out! Any help is appreciated thanks!

#define HIGH 1
#define LOW 0
int addrbus1[8]; //Array for first 8-bits
byte addrbus2;   //Byte for second 8-bits
String str1 ="";


void setup() {    
  DDRD &= B00000011;       // set Arduino pins 2 to 7 as inputs, leaves 0 & 1 (RX & TX) as is
  DDRB = B11101100;        // set pins 8 to 13 as inputs

  Serial.begin(19200);
  Serial.write(17);    //Turn on backlight
  Serial.write(12);    //clear
  
}

void loop() {  
//Due to lack of a second shift register...  
//We are pulling bits from FIRST 8-bits of 16-bit Address bus using D2-D9
//This stores the data in an array, but I'd like it in a byte instead.
  for (int c = 0; c < 8; c++) {
    addrbus1[c] = digitalRead(c+2);    
  }
    
//We are pulling bits from SECOND 8-bits of 16-bit Address bus using an HD14021 8-bit Shift Register 
  digitalWrite(10, 0);
  addrbus2 = shiftIn(12, 11, MSBFIRST);
  digitalWrite(10, 1);

//Stream bits from array to a string, then print to the LCD
  str1 = "";
  for (int c = 0; c < 8; c++) {
      str1 = str1 + String(addrbus1[c]);  
}

//Clear LCD
  Serial.write(12);
  Serial.print(str1);
//Send a simple byte for the second 8-bits :) 
  Serial.println(addrbus2, BIN);
  Serial.print(addrbus2, HEX);
  

  delay(10);

}

Untested, but it should work, assuming digital pin 2 is the low order bit.

unsigned byte lowAddr;

  lowAddr = 0;
  for (int c = 0; c < 8; c++) {
    lowAddr =  lowAddr | (digitalRead(c+2) << c);
  }

As lar3ry pointed out, just read the bits into a single byte. Don't use the array.

Also, check your DDRB assignment, it doesn't look correct.

Finally, if you're not set on the wiring, I would suggest you use pins 4-11 instead. That way you could simply do something like this, which would be very fast:

uint8_t lowAddr = (PIND & 0xF0) + (PINB & 0x0F);

Completely and totally unrelated to your problem, but a hint that is better heard now than later.

There are very few places where numbers belong in code. Especially if it is a number you might use again, because if it changes you have to go through the whole code changing each instance of the number. The only place numbers should be around is when they are mathematical constants. 1 and 0 get in there a lot but not much else.

Where you have code like this:

Serial.write(17);    //Turn on backlight
Serial.write(12);    //clear

Instead, either #define those values, or set up an enum to hold them so they have names and you can instead say:

enum LCDCommands{
CLEAR = 12,
BACKLIGHT_ON = 17
};

...

Serial.write(BACKLIGHT_ON);  
Serial.write(CLEAR);

Or something to that effect that makes sense to you. Not only does it save time when you are making changes, but for the rest of the time you are writing this code you can use a word that corresponds to what you want to do instead of having to remember which number to send. It makes life a lot easier.

You'd be better off using a MEGA or a Teensy++ that has whole 8 bit Ports open for use the read/write a Port Register in a single operation.

You might also want to look at the 'Bits and Bytes' commands here if you stick with the UNO. http://arduino.cc/en/Reference/HomePage

And see if you can scare up a 6510 (used in the C64) instead of a 6502, it's slightly better.

@Delta_G Yeah, I realized that it's just bad habit. I usually do go back later on and clean up the code. I didn't know about the 'enum' command though, thank you for that one.

@GoForSmoke I have heard that about the 6510, but I already had the 6502 in my stash. I am not very patient when I get an idea to build something. XD I will eventually grab a MEGA when the need arises, of course now would be a great time, come to think about it. I am also trying to figure out how to use this 6532 RIOT chip along with it. Any ideas?

@lar3ry & int2str Thank you both for the code. I tried both, and they both worked. @int2str it worked pretty quick. However, I have lost my shift register and I am not sure how. I slid the D2:D9 to D4:D11 and moved the other lines around, but even though I have the pins correct in the code, it shows up as FF. Also, I have noticed that the hex values I am seeing on the LCD are reversed. ie. "9E" instead of "E9".

Here is a quick video to demonstrate. http://youtu.be/b3ztVKf1hmk

#define HIGH 1
#define LOW 0

enum LCDCommands{
  CLEAR = 12,
  BACKLIGHT_ON = 17,
  NEWLINE = 13
};
enum Pins{
  LATCH = 2,
  SHIFTCLK = 3,
  SHIFTINPUT = 12,
  MCUCLK = 13
};

byte addrbus1; //Array for first 8-bits
byte addrbus2;   //Byte for second 8-bits

void setup() {    
  DDRD &= B00001111;       // set Arduino pins 2 to 7 as inputs, leaves 0 & 1 (RX & TX) as is
  DDRB = B11100000;        // set pins 8 to 12 as inputs, 13 as output

  Serial.begin(19200);
  Serial.write(BACKLIGHT_ON);
  Serial.write(CLEAR);

}

void loop() {   
  //We are pulling bits from FIRST 8-bits of 16-bit Address bus using D4-D11
  uint8_t addrbus1 = (PINB & 0x0f) + (PIND & 0xF0) ; 

  //We are pulling bits from SECOND 8-bits of 16-bit Address bus using an HD14021 8-bit Shift Register 
  digitalWrite(2, 0);
  addrbus2 = shiftIn(12, 3, MSBFIRST);
  digitalWrite(2, 1);


  Serial.write(CLEAR);
  Serial.print(addrbus1, HEX); Serial.print(" "); Serial.print(addrbus1, BIN);
  Serial.write(NEWLINE);
  Serial.print(addrbus2, HEX); Serial.print(" "); Serial.print(addrbus2, BIN);

  delay(50); 
  digitalWrite(MCUCLK, 0); //cheap clock driver line low
  delay(50); 
  digitalWrite(MCUCLK, 1); //cheap clock driver line high
}

mkelley88:
I have noticed that the hex values I am seeing on the LCD are reversed. ie. “9E” instead of “E9”.

Either swap the pins (move the ones from D8-D11 to D4-D7 and vice versa), or change it in the code:

uint8_t addrbus1 = ((PINB & 0x0f) << 4) + ((PIND & 0xF0) >> 4);

int2str:
Either swap the pins (move the ones from D8-D11 to D4-D7 and vice versa), or change it in the code:

uint8_t addrbus1 = ((PINB & 0x0f) << 4) + ((PIND & 0xF0) >> 4);

Perfect that worked great, now if I can just get my shift register back.
Also, when the bytes are displayed on the screen, is there anyway to keep the length of the output the same?

For instance hex out ‘00’ will just show up as ‘0’, 01 will show as ‘1’ I would prefer it to show as “01”
The same with binary, instead of 1001, how do i get it to show 00001001 in full?

If there’s no simple way, I can just deal with it this way, but I figure I might as well ask.

0 0.0 0
FF 11111111.0 0
FF 11111111.1 1
FF 11111111.1 1
FF 11111111.2 10
FF 11111111.2 10
FF 11111111.3 11
FF 11111111.3 11
FF 11111111.4 100
FF 11111111.4 100
FF 11111111.5 101
FF 11111111.5 101
FF 11111111.6 110
FF 11111111.6 110
FF 11111111.7 111
FF 11111111.7 111
FF 11111111.8 1000
FF 11111111.8 1000
FF 11111111.9 1001
FF 11111111.9 1001
void displayBinary(const uint8_t &b) {
    for (uint8_t bit = 0x80; bit != 0; bit >>= 1)
        Serial.write(b & bit ? '1' : '0');
}

Wow, thanks so much! I finally feel like the screen is no longer having seizures! :D

You can buy a MEGA or just buy the chip (or a 1284 with 16k SRAM), program that and build it into your design.

I don't know why you want to build a 6502 museum piece except maybe you have software to run on it. I had a VIC-20 in 83-84 and then a C-64 in 85, sold both. It was amazing how much you could do with such little CPU, the 13 indirect addressing modes made a lot possible but it was like getting the most out of a chainsaw motor on a go-cart.

Sorry but I don't know that 6532 RIOT chip. It looks interesting in a back-then sort of way. http://en.wikipedia.org/wiki/MOS_Technology_6532

They are legacy parts, you can buy used pulls and never used from Hong Kong on eBay. I wouldn't bother trying to use one to enhance an AVR though, it would involve wait states.