Help needed on: How to shift a binary value over a set of pins?

I'm trying to interface with an 8-bit parallel interface on a VFD display. I would like to create a function that takes in a character, converts the character to its binary ASCII value, and then places the value onto a group of 8 pins. I've been looking for a solution to this problem, and have reviewed solutions like using the Uno's built-in Ports, but I believe the solution lies in some form of bit masking/manipulation. Any help would be appreciated. I will leave my code here, although I only got as far as finding the binary representation of the character. Again, thank you for any help.

const char DATA[] = {2, 3, 4, 5, 6, 7, 8, 9};
String message = "HELLO, WORLD";

void setup() {
  for (int n = 0; n<8; n += 1){
    pinMode(DATA[n], OUTPUT);
  }

  int messageLength = message.length();
  for (int i = 0; i < messageLength; i += 1){
    int binChar = (byte)message[i];
  }
}

void loop() {
  // put your main code here, to run repeatedly:

}

-Hyper

any example? take "H", show what pin should looks like.

I'm aiming to be able to call a function such as printChar("H"), which is binary 01001000, and then written to pins would be:
pin 2 - low
pin 3 - low
pin 4 - low
pin 5 - high
pin 6 - low
pin 7 - low
pin 8 - high
pin 9 - low

This is the first step. Then I will adapt the code so that I can print strings (e.g. printString("Hello, World!")), but one step at a time!
-Hyper

(Edit- Corrected pin names)

Using a for loop, read the value of each bit in the character byte using the bitRead() function and write the value to the corresponding pin.

For convenience I would put the pin numbers in an array thus allowing them to be accesses using the bit number used in bitRead()

output

  pin 2 - 0
  pin 3 - 0
  pin 4 - 0
  pin 5 - 1
  pin 6 - 0
  pin 7 - 0
  pin 8 - 1
  pin 9 - 0
#define N 8
const byte  pMap0 [N] = { 2, 3, 4, 5, 6, 7, 8, 9 };
char s [80];

void
setPins (
    byte  val,
    const byte *pinMap )
{
    for (int i = 0; i < N; i++, val >>= 1)  {
        sprintf (s, "  pin %d - %d", pinMap [i], val & 1);
        Serial.println (s);
    }
}

void
setup (void)
{
    Serial.begin (9600);

    setPins ((byte) 'H', pMap0);
}

void
loop (void)
{
}

some notes...

If going to works with ASCII string, do not use String class:

If you want to split message by bytes, why the type of binChar is int ?

How would I store them in an array?

Note: I believe that a lot of my problems stem from a lack of understanding of C++ variable type usage and declaration. I will do work to study up on it.
-Hyper

If I'm not going to use the String class, what should I use? I still need to be able to index through the group of characters and interact with each character by itself.
And yes, I see now how it's stupid to store a byte as an integer, I'll make that correction. Thank you!
-Hyper

This is helpful! While I don't understand string formatting in C++ or why that works, I believe I understand the (what I believe is) rotate operation and hopefully that will help me find a solution. Thank you!
-Hyper

Use C-style char array:

char message[] = "HELLO, WORLD";

It's a pity the Arduino doesn't have any 8-bit ports to write to, eh?

This works well with my code. Although I don't see an advantage, I don't doubt that it's the proper way. Thank you for the information!
-Hyper

Like I mentioned in my original post, I had seen some other posts/questions on the forum relating to ports, but because of my setup and in the pursuit of knowledge, I'd like to learn how to perform the same thing on specific pins instead of a hardware-defined port. Thank you for the suggestion though!
-Hyper

1 Like

Why? You can use PORTD as a whole 8bit, if you don't use a Serial

But that was my point. To do an 8-bit write to a port, you want to choose a port. To receive a serial character, you need at least one pin of port D. B & C aren't complete. So there's no easily available 8-bit port to do what he wanted in one write. At a minimum, it's a mask of some bits to one port, the rest to another.
Sorry, didn't spell it all out for everyone.

1 Like

Currently, my code is as follows. I can now separate each bit of each letter, and now need help indexing through the pin numbers. My serial output gives me the following:

**myterious box character**
0

I believe this may be a result of my data pin array being defined incorrectly. Any thoughts?

#define WR 11
#define RD 10
int DATA[8] = {2, 3, 4, 5, 6, 7, 8, 9};
char message[] = "HELLO, WORLD";

void setup() {
  Serial.begin(9600);

  //set all pins to outputs
  pinMode(WR, OUTPUT);
  pinMode(RD, OUTPUT);
  for (int n = 0; n<8; n += 1){
    pinMode(DATA[n], OUTPUT);
  }


  int messageLength = strlen(message);
  //for every letter in the string
  for (int i = 0; i < messageLength; i += 1){
    //binchar is the binary representation for each letter
    byte binChar = (byte)message[i];
    //for every bit in the byte
    for (int i = 0; i < 8; i += 1){
      //get the bit at each bit postition, and set the corresponding pin high or low
      int bit = bitRead(binChar, i);
      //digitalWrite(DATA[i], bit);
      Serial.println(DATA[i]);
      Serial.println(bit);
      Serial.println();
    }
    delay(100);
    //signal to display to read data lines
    digitalWrite(WR, HIGH);
    digitalWrite(RD, HIGH);
    //wait for display to latch data
    delay(100);
    //return read/write pins to normal state
    digitalWrite(WR, LOW);
    digitalWrite(RD, LOW);
  }
}

void loop() {
  // put your main code here, to run repeatedly:

}


-Hyper

Edit: Comments, features, and fixes

Why you comment out the key line of code?

      //digitalWrite(DATA[i], bit);

I'm looking through a tiny window just now, that's what I saw and wonder about.

Also, is the baud rate in the serial monitor set to match

Serial.begin(9600);

?

a7

byte outputPins[] = {2, 3, 4, 5, 6, 7, 8, 9};

Then, when you read bit 0 in your for loop you can set the state of the corresponding pin like this

for (int b = 0; b < sizeof(byte); b++)
{
  digitalWrite(outputPins[b], bitRead(binChar, b));  //read bit state and write to corresponding pin
}

I only commented this line out for testing purposes. I'll uncomment it and give it a go.
And yes indeed, the serial monitor baudrate is set to match the predefined baud, that was one of the first things I tried because it was the previous cause of the mysterious box character :laughing:
Thank you though for the tips, and I'll see if the serial weirdness is realistically a problem or not.
-Hyper

SUCCESS!
My message has been successfully printed onto the screen!

Changes since the last code upload:
-Reversed data pin order (VFD uses Little endian and my code incremented instead of decrementing)
-Added display initialization code

Next steps:
-"Functionify" my code so I can send hex bytes (for commands like reset) and also character arrays (for text)

Thank you to all who helped!! I'll be sure to post again if I need more help.
-Hyper