No match for operator | when attempting to write to PORT

I just started using the nano every. I'm using Arduino 1.8.13 on Windows 10 x64.

I'm using the Arduino to read a shift register with the following bit of code:

bitWrite(PORTA,1,1);
bitWrite(PORTA,1,0);
for (int x=0;x<=7;x++) {
    bitWrite(j1And3Data,x,bitRead(PORTD, 3));
    PORTE = PORTE | 0b00001111;
    PORTE = PORTE & 0b11110000;
  }
Serial.println(j1And3Data, BIN);

It's giving me the following error message

no match for 'operator|' (operand types are 'PORT_t {aka PORT_struct}' and '')

So it's upset about the PORTE line, this code worked just fine on an UNO and I made sure to update my PORT letters to the correct ones for the Nano Every. I have tried this with register emulation turned on and turned off. I haven't been able to find much in the way of documentation for reading the pin on the ATMega4809, but clearly I'm doing something wrong.

I'm using digital pin 7 as my latch, so I set it high then low to store the current inputs. Then I read all eight bits from the shift register, using the data line (D14/A0), and pulsing my clock line after each read (digital pin 8).

Here is my full code:

uint8_t CtrlLatchPin = 7;         // Global Latch Output pin for reading data from Controller
uint8_t j1ClockPin = 8;          // Clock pulse Output Pin for Controller 1
uint8_t j1DataPin = 14;           // Data Input pin from Controller 1


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

  // Configure Pin Modes
  pinMode(CtrlLatchPin, OUTPUT);
  pinMode(j1ClockPin, OUTPUT);
  pinMode(j1DataPin, INPUT_PULLUP);

}

void loop() {

  bitWrite(PORTA,1,1);
  bitWrite(PORTA,1,0);
  for (int x=0;x<=7;x++) {
    bitWrite(j1And3Data,x,bitRead(PORTD, 3));
    PORTE = PORTE | B00001111;
    PORTE = PORTE & B11110000;
  }  
Serial.println(j1And3Data, BIN);
}

You should look up how to do "real" port manipulation on the 4809.
What you're doing now uses a "compatibility package" that is ... quite slow, probably defeating whatever you had in mind.

And PORTx is (simulating) an output register, so perhaps it doesn't return values.

Conside

    VPORTE.OUT = VPORTE.IN | 0b00001111;
    VPORTE.OUT = VPORTE.IN & 0b11110000;

OR

    PORTE.OUTSET = 0b00001111;
    PORTE.OUTCLR = 0b00001111;
1 Like

I've tried to find some examples of "real" port manipulation for the 4809. The most I could find was some RTFM responses :frowning: any chance you have a link I could reference to learn from?

What's the difference between these two ways of referencing the ports? Is either one of them any better than the other (where better means takes less processing time than just using digitalWrite)

The VPORT register is located in the I/O register area and supports IN/OUT and SBI/CBI instructions, so access is fast (single cycle).
Since the PORT register is accessed using the LD/ST instruction, ST instruction is delayed by one cycle than OUT instruction.
(Reading is also one cycle delayed than IN instruction if optimized to LDS instruction.)
But PORT register has SET, CLR and TGL registers.
This makes it faster if for use by RMW(read modify write) with more than 2 bits.
(If 1 bit RMW, faster SBI/CBI instructions.)

However, since it is a difference of 1 clock or 2 clocks, if you don't need to ultimately optimize with the assembler level (a.k.a. if annoy even 1 cpu clock), you do not need to worry about chosen.

1 Like

Thanks, that cleared it up! Know of a good resource I could read to learn more about this?

Official datasheets... :roll_eyes:

What resource were you using for the older AVRs?
If there is one that is particularly good, it would probably be easier to re-write it for the new AVRs than to start from scratch.

Come to think of it, I think the "Port Emulation" feature on the Every and WiFi2 "fakes" the PORTB/PORTC/PORTD of the original Nano/Uno, rather than just providing familiar names for the new ports. So "PORTD = 0x12;" will end up as some combination of writes to bits of the 4809 ports A, B, C, and F, while "PORTE" remains an new-style structure (defined NATIVELY, not by the compatibility feature) for accessing the 4809 PORTE features.

To access the 4809 ports in native mode, you'll need to turn OFF the "register emulation" in the TOOLS menu. And you'll find your port bits scattered all over :frowning:

For the older AVRs just a quick search online pulled up plenty of pages that went over the instructions explaining what they did and providing examples of how to use them. When I do the same kind of search for the ATMega4809 (for example ATMega 4809 Port Manipulation) I get results for usb port issues, serial port issues, and extremely unhelpful forum posts that end with the person who asked for help being told to read the manual. I've seen the manual, if I understood it I wouldn't be on the forum asking why things aren't working or asking if anyone knew of a resource that did a good job breaking it down :rofl:

I did make sure to turn off port emulation and your post that I marked as the solution worked perfectly, thank you!

In the end I changed my code to look like this:

  bitWrite(VPORTA.OUT,1,1);
  bitWrite(VPORTA.OUT,1,0);
  for (int x=0;x<=7;x++) {
    bitWrite(j1And3Data,x,bitRead(VPORTD.IN, 3));
    PORTE.OUT = PORTE.IN | 0b00001111;
    PORTE.OUT = PORTE.IN & 0b11110000;
  }  

You can see I used both VPORT and PORT to confirm either way would work as expected, I'll try to read up more on them to pick one or the other to be consistent with my code.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.