• [ON7IR] nanoKeyer runs on Nano Every

    From ON7IR via rec.radio.amateur.moderat@21:1/5 to All on Thu Jul 1 22:11:01 2021
    XPost: rec.radio.amateur.moderated

    Ham radio ON7IR

    ///////////////////////////////////////////
    nanoKeyer runs on Nano Every

    Posted: 30 Jun 2021 06:01 AM PDT https://on7ir.blogspot.com/2021/06/nanokeyer-runs-on-nano-every.html


    In the previous post I mentioned that the Arduino Nano that is used in the nanoKeyer has limited memory and cannot run a lot of extra functions. A
    Nano Every with its larger memory could be a solution if more functions are required.
    The ordered Nano Every board arrived and it is time to upload the sketch of
    the K3NG keyer.
    But first the board has to be added to the IDE. Therefore go to the menu
    Tools > Board > Boards Manager and then type Nano Every in the search
    field. Arduino megaAVR Boards will be shown. It contains the boards Arduino
    Uno WiFi Rev2 and Arduino Nano Every. Click on the install button to add
    them to the IDE. ARduino megaAVR Boards are added to the IDE

    Now go to Tools > Board > Arduino megaAVR Boards and select Arduino Nano
    Every

    The Tools menu also has the item Registers emulation. It might show
    ATMEGA328 but it must be set to None (ATMEGA4809). My IDE is in dutch
    language. 'Hulpmiddelen' means 'Tools '


    Okay, time to compile and run the sketch. But ... the IDE is reporting
    problems with the error 'PIND' was not declared in this scope. Compile the sketch with the Arduino Nano board selected and it is quite happy to run
    it. But not with the Nano Every.
    What's going wrong?
    The Nano Every is pin compatible with the Arduino Nano so that should not
    be the problem. According to website https://arduino.cc the Every is an improved Nano and they say 'Your code will still work'. Unfortunately that
    is not quite correct. The issue is related to the different type of
    processor.
    The cpu of the Nano Every is an Atmel ATMEGA4809 which, although it is
    using the same AVR architecture as the Arduino Nano's ATmega328P, has some significant differences. The register names is one of them.
    For the Every board the IDE can emulate the ATmega328P registers (via Tools
    Registers emulation > ATMEGA328 but unfortunately it is not a full
    emulation and you guess it, the macro PIND (or PINx to be correct) is not emulated.
    But what is PIND?
    Well let's have a quick word about the ATMega168 (and ATMega328) port
    register.
    The cpu has 3 ports called B, C and D. Port B covers Arduino's digital
    ports D8-D13, Port C covers the analog ports and Port D covers digital
    ports D0-D7.
    Each port has 3 registers.
    - DDR (Data Direction Register) : controls direction (input or output).
    - PORT : controls the pin being LOW or HIGH
    - PIN : reads all digital input pins of that port at the same time
    Thus PIND refers to port register D. In the sketch also PINB used, refering
    to port register B.

    Why not just use the functions digitalRead() or digitalWrite() for the port manipulation?
    The answer is speed. digitalRead() and digitalWrite() needs a lot machine instructions while direct port access is a matter of a few clock cycles.

    Let's look closer in the k3ng_keyer sketch at lines 19460 -19462.

    Line 19460 is where the first error is reported. It has the code case 2: return(bitRead(PIND, 2)); break;
    bitRead(PIND, 2) means read bit 2 of PIN register D. Bit 2 corresponds to Arduino's digital port D2 (see pinout diagram of the Arduino Nano). At next line bitRead(PIND, 5) corresponds to D5, and next line bitRead(PINB, 0) corresponds to D8. In other words the Nano's digital ports D2, D5 and D8
    are controlled here.
    Let's find out how the ATMEGA4809 handles its port registers.
    The answer is in the datasheet of the ATMEGA4809 at chapter 16 'PORT - I/O
    Pin Configuration'
    We can use PORTx to manipulate the port registers as it seems PORTx.IN, y
    is doing the same as PINx, y. The pinout diagram of the ATMEGA4809 shows
    which digital port belongs to which port of the cpu.
    On the Nano Every digital port D2 is controlled by Port A bit 0 (PA0) , D5
    by Port B bit 2 (PB2) and D8 by port E bit 3 (PE3).
    The solution is to replace the bitRead(PINx, y) commands by (PORTx.IN, y).
    It is obvious that we must not use the ATMEGA328 emulation but set
    emulation to None (ATMEGA4809).
    So replace
    case 2: return(bitRead(PIND, 2)); break;
    case 5: return(bitRead(PIND, 5)); break;
    case 8: return(bitRead(PINB, 0)); break;
    with
    case 2: return(bitRead(PORTA.IN, 0)); break;
    case 5: return(bitRead(PORTB.IN, 2)); break;
    case 8: return(bitRead(PORTE.IN, 3)); break;
    compile it and the keyer works just fine on a Nano Every. That is with the
    few tests I did so far.

    The nanoKeyer sketch that I loaded into the Arduino Nano had next features enabled in keyer_features_and_options_nanokeyer_rev_d.h
    #define FEATURE_BUTTONS
    #define FEATURE_COMMAND_MODE
    #define FEATURE_MEMORIES
    #define FEATURE_WINKEY_EMULATION
    #define FEATURE_POTENTIOMETER
    After compilation the IDE reports that the sketch uses 25652 bytes (83%) , maximum space is 30720 bytes. Global variables use 907 bytes of dynamic
    memory and 1141 remain for local variables, maximum is 2048 bytes.
    If only a few extra options as below were added then the IDE is reporting
    that the sketch is too large using 39362 bytes (128%) and 1155 bytes (56%) occupied by global variables.
    #define FEATURE_COMMAND_LINE_INTERFACE
    #define FEATURE_SERIAL_HELP
    #define FEATURE_AUTOSPACE
    With these extra options loaded into the Nano Every there is still enough memory left for extra options or features. The IDE reports that the sketch
    uses 39184 bytes (79%) , maximum space is 49152 bytes. Global variables use
    754 bytes (12%) out of 6144 bytes.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)