/*
*
* RP2040_IO-PORTS_utilities.ino
*
* https://forum.arduino.cc/t/pi-pico-port-registers/1022778/36
*
*
*
* Author: tbillion ago 2022 post #38
* ... wrote a bunch of high level helper functions, really just for organization and readability.
* also based on the scarce google results on these things maybe this will help someone
* in the future, below is a bunch of examples i made, i tested about 75 percent,
* strictly here for information purposes ...
*
* ... you can read and write GPIO_IN & GPIO_OUT for your application.
*
*
* ... Addition - all SDK function available in arduino using earlphilhower pico library
*
* --------------------------------------------------------------------------------------
*
* for HELP UNDERSTANDING I/O REGISTERS LOOK AT THE CODE in the following files:
* > 3-RP2040_GPIO_16_LED_registers.ino <
* > 3-RP2040_GPIO_8_LED_registers_3.ino <
* > 3-RP2040_GPIO_8_LED_registers_4.ino <
*
* --------------------------------------------------------------------------------------
*
* https://forum.arduino.cc/t/pi-pico-port-registers/1022778/33?page=2
*
* [RP2040-datasheet.pdf, pg.30 of 639]
* 2.3.1.2. GPIO Control
* The processors have access to GPIO registers for fast and direct control of pins with GPIO functionality.
* There are two identical sets of registers:
* - GPIO_x for direct control of IO bank 0 (user GPIOs 0 to 29, starting at the LSB)
* - GPIO_HI_x for direct control of the QSPI IO bank (in the order SCLK, SSn, SD0, SD1, SD2, SD3, starting at the LSB)
*
* ------------------------------------------------------------------------------------
* - NOTE -
* - To drive a pin with the SIO’s GPIO registers, the GPIO multiplexer for this pin -
* - must first be configured to select the SIO GPIO function. See Table 278. -
* ------------------------------------------------------------------------------------
*
* These GPIO registers are shared between the two cores, and both cores can access them simultaneously.
* There are three registers for each bank:
* - Output registers, GPIO_OUT and GPIO_HI_OUT, are used to set the output level of the GPIO (1/0 for high/low)
* - Output enable registers, GPIO_OE and GPIO_HI_OE, are used to enable the output driver. 0 for high-impedance, 1
* for drive high/low based on GPIO_OUT and GPIO_HI_OUT.
* - Input registers, GPIO_IN and GPIO_HI_IN, allow the processor to sample the current state of the GPIOs
* Reading GPIO_IN returns all 30 GPIO values (or 6 for GPIO_HI_IN) in a single read.
* Software can then mask out individual pins it is interested in.
*
* NOTE: -OE- stands for Output Enable
* -OVER- stands for override
*
*
* first you have to set the pin mode, which for gpio is 5 or GPIO_FUNC_SIO,
* it works both ways that looks like this :
*
* ------------------------------------------------------------------------------------
*
* [RP2040-datasheet.pdf, pg.43 of 639]
* 2.3.1.7. List of Registers
*
* We can assign each one to a bit in a 32-bit hardware register which is mapped to 32-bits of memory
* in the RP2040’s address space. The GPIO functions are controlled by writing a 1 bit to the correct
* position in the GPIO register. There is one register to turn on a GPIO pin and a different register
* to turn it off, this means you don’t need to read the register, change one bit and then write it back.
* It’s quite easy to program these since you just place one in a CPU register, shift it over by the
* pin number and then write it to the correct memory location. These registers start at memory location
* 0xd0000000 and are defined in sio.h. Note there are two sio.h files, one in hardware_regs which
* contains the offsets and is better for Assembly Language usage and then one in hardware_structs
* which contains a C structure to map over the registers. Following are the GPIO registers, note that
* there are a few other non-GPIO related registers at this location and a few unused gaps in case
* you are wondering why the addresses aren’t contiguous.
*
* The SIO registers start at a base address of 0xd0000000 (defined as SIO_BASE in SDK) through 0xd000017c
*
* |------------|-----------------|---------------------------|
* | Address | Register Name | Info |
* |------------|-----------------|---------------------------|
* | 0xd0000000 | CPUID | Processor core identifier |
* |------------|-----------------|---------------------------|
* NOTE: here, Core 0 reads a value of 0 when accessing this address, and core 1 reads a
* value of 1. This is a convenient method for software to determine on which core it is running.
*
* --------------------------------------------------------------------------------------------
*
* ## ## ## IMPORTANT ## ## ## IMPORTANT ## ## ## IMPORTANT ## ## ## IMPORTANT ## ## ##
* ## ##
* ## CPUID should not be confused with the Cortex-M0+ CPUID register on each processor’s ##
* ## internal Private Peripheral Bus, which lists the processor’s part number and version. ##
* ## ##
* ## ## ## IMPORTANT ## ## ## IMPORTANT ## ## ## IMPORTANT ## ## ## IMPORTANT ## ## ##
*
* --------------------------------------------------------------------------------------------
*
* |------------|-----------------|---------------------------|
* | 0xd0000004 | GPIO_IN | Input value for GPIO pins |
* |------------|-----------------|---------------------------|
* Note: returns all 30 GPIO values (or 6 for GPIO_HI_IN) in a single read.
* Software can then mask out individual pins it is interested in.
*
* |------------|-----------------|---------------------------|
* | 0xd0000008 | GPIO_HI_IN | Input value for QSPI pins | QSPI
* |------------|-----------------|---------------------------|
*
*
* |------------|-----------------|---------------------------|
* | Address | Register Name | Info |
* |------------|-----------------|---------------------------|
* | 0xd0000010 | GPIO_OUT | GPIO output value |
* | 0xd0000014 | GPIO_OUT_SET | GPIO output value set |
* | 0xd0000018 | GPIO_OUT_CLR | GPIO output value clear |
* | 0xd000001c | GPIO_OUT_XOR | GPIO output value XOR |
* |------------|-----------------|---------------------------|
* | 0xd0000020 | GPIO_OE | GPIO output enable |
* | 0xd0000024 | GPIO_OE_SET | GPIO output enable set |
* | 0xd0000028 | GPIO_OE_CLR | GPIO output enable clear |
* | 0xd000002c | GPIO_OE_XOR | GPIO output enable XOR |
* |------------|-----------------|---------------------------|
* NOTE: -OE- stands for Output Enable
* NOTE: The OUT and OE registers also have atomic SET, CLR, and XOR aliases,
* which allows software to update a subset of the pins in one operation.
* This is vital also for safe parallel GPIO access between the two cores.
*
*
*
* |------------|-----------------|---------------------------|
* | Address | Register Name | Info |
* |------------|-----------------|---------------------------|
* | 0xd0000030 | GPIO_HI_OUT | QSPI output value | QSPI
* | 0xd0000034 | GPIO_HI_OUT_SET | QSPI output value set | QSPI
* | 0xd0000038 | GPIO_HI_OUT_CLR | QSPI output value clear | QSPI
* | 0xd000003c | GPIO_HI_OUT_XOR | QSPI output value XOR | QSPI
* |------------|-----------------|---------------------------|
* | 0xd0000040 | GPIO_HI_OE | QSPI output enable | QSPI
* | 0xd0000044 | GPIO_HI_OE_SET | QSPI output enable set | QSPI
* | 0xd0000048 | GPIO_HI_OE_CLR | QSPI output enable clear | QSPI
* | 0xd000004c | GPIO_HI_OE_XOR | QSPI output enable XOR | QSPI
* |------------|-----------------|---------------------------|
* NOTE: -OE- stands for Output Enable
* NOTE: The OUT and OE registers also have atomic SET, CLR, and XOR aliases,
* which allows software to update a subset of the pins in one operation.
* This is vital also for safe parallel GPIO access between the two cores.
*
*
* -----------------------------------------------------------------------------------
* - NOTE -
* - To drive a pin with the SIO’s GPIO registers, the GPIO multiplexer for this pin -
* - must first be configured to select the SIO GPIO function. See Table 278. -
* -----------------------------------------------------------------------------------
*
* [RP2040-datasheet.pdf, pg.29 of 639]
* SIO registers are mapped to word-aligned addresses in the range 0xd0000000 - 0xd000017c
*
* [ 0xd0000000 - 0xd000017c ]
* [11010000 00000000 00000000 00000000 - 11010000 00000000 00000001 01111100]
*
*
* for (uint8_t i = 0; i < 30; ++i) {
* //
* gpio_set_function(i, GPIO_FUNC_SIO);
* //
* if (i >= 26) {
* //
* gpio_disable_pulls(i);
* gpio_set_input_enabled(i, false);
* //
* } // if
* //
* } // for
*
* It is convenient (and allowed) to mix Arduino calls and sdk calls.
*
* // leave serial pins, analog pins, and "board use" pins alone.
* for (uint8_t i=2; i <= 22; i++) pinMode(i, INPUT);
* allbits = gpio_get_all();
*
* // if the pins had been set to outputs...
* gpio_put_masked(0b00000000011111111111111111111100, 0x1230); // 0x1230 --> 0001.0010|0011.0000
* // 0001001000110000
*
*
*
* --------------------------------------------------------------------------------------
*
*
* Please refer to: >>> https://forum.arduino.cc/t/optional-parameters-in-a-function/607525/12
*
* Inconsistency between the variable name in the prototype vs function definition:
* the compiler doesn't actually care about the variable name in the prototype.
* It just needs to know the function signature. In fact, you can leave the
* variable name out of the prototype altogether.
*
* NOTE: exceptions are parameters passed as void, REFERENCE(&), POINTER(*) or >>default val.<<
* You should specify the default parameter >> ONLY << in the function prototype.
*
*
* --------------------------------------------------------------------------------------
*
*
*/
// ======================================================================================
// start of functions prototypes declarations
//
void setOE(uint32_t);
uint8_t countMidNums(uint8_t, uint8_t);
uint32_t getAllPinDirections();
uint32_t makeBitMaskOutAll();
uint32_t makeBitMaskInAll();
uint32_t makeBitMaskRange(uint8_t pins[], uint8_t, bool);
uint32_t makeBitMaskRangeNonClobber(uint8_t pins[], uint8_t, bool);
uint32_t makePutMask(uint8_t vals[], uint8_t);
// port/pin registers operations:
void setAllDigital();
void setAllOutput();
void setAllInput();
void setRangeDigital(uint8_t pins[], uint8_t);
void setRangeOutput(uint8_t pins[], uint8_t);
void setRangeInput(uint8_t pins[], uint8_t);
void setPortRange(uint8_t, uint8_t, bool);
void setPortRangeNonClobber(uint8_t, uint8_t, bool);
uint32_t readAllPorts();
uint32_t readPortRange(uint8_t, uint8_t);
uint32_t readPort1(uint8_t pins[], uint8_t);
//
// Read/Write SINGLE GPIO (port registers operations):
uint8_t readGPIOport(uint8_t); // my addition: use of Pi Pico C++ SDK
void writeGPIOport(uint8_t, bool); // my addition: use of Pi Pico C++ SDK
//
//
void writeAllPorts(uint32_t);
void writeAllPorts1(uint8_t pinValues[], uint8_t);
void writePortRange(uint8_t pins[], uint8_t, uint8_t pinValues[], uint8_t);
void writePortRange1(uint8_t, uint8_t, uint8_t pinValues[], uint8_t);
// utilities:
void diagnosePinDir();
uint32_t reverseBits(uint32_t);
// console print:
void printBinary8(uint8_t, bool, bool);
void printBinary32(uint32_t, bool, bool);
void checkBits(uint8_t, bool);
//
// end of functions prototypes declarations
// ======================================================================================
// --------------------------------------------------------------------------------------
void setOE(uint32_t bitMask) {
//
for (uint8_t i = 0; i <= 31; i++) {
//
if ( ((i < 23) || (i > 25)) && ((i < 29) || (i > 31)) ) { // <SYSTEM> pins
//
if (bitRead(bitMask, i)) {
gpio_set_input_enabled(i, false); // output
} else {
gpio_set_input_enabled(i, true); // input
} // if-else
//
} // if
} // for
//
} // setOE()
uint8_t countMidNums(uint8_t a, uint8_t b) {
//
uint8_t c;
//
for (uint8_t i = a; i < b; i++) c = i;
//
return (c);
//
} // countMidNums()
uint32_t getAllPinDirections() {
//
uint32_t powResult = 0;
//
for (uint8_t i = 31; i >= 0; i--) {
//
if ( ((i < 23) || (i > 25)) && ((i < 29) || (i > 31)) ) { // <SYSTEM> pins
//
if (gpio_get_dir (i)) {
//powResult += pow(2, i); // use this to set an individual bit
bitWrite(powResult, 31 - i, 1);
//
} // if
//
} // if
//
} // for
//
return (powResult);
//
} // getAllPinDirections()
uint32_t makeBitMaskOutAll() {
//
uint32_t powResult = 0;
//
for (uint8_t i = 0; i <= 31; i++) {
//
if ( ((i < 23) || (i > 25)) && ((i < 29) || (i > 31)) ) { // <SYSTEM> pins
powResult += pow(2, i); //use this to set an individual bit
} // if
//
} // for
//
return (powResult);
//
} // makeBitMaskOutAll()
uint32_t makeBitMaskInAll() {
//
uint32_t powResult = 0b00011100011111111111111111111111; // bit-mask
//
for (uint8_t i = 0; i <= 31; i++) {
//
if ( ((i < 23) || (i > 25)) && ((i < 29) || (i > 31)) ) { // <SYSTEM> pins
powResult -= pow(2, i); //use this to set an individual bit
} // if
//
} // for
//
return (powResult);
//
} // makeBitMaskInAll()
uint32_t makeBitMaskRange(uint8_t pins[], uint8_t pinCount, bool IO) {
//
uint8_t val = 0;
uint32_t powResult = 0;
//
for (uint8_t i = 0; i < pinCount; i++) {
//
val = pins[i];
//
if ( ((val < 23) || (val > 25)) && ((val < 29) || (val > 31)) ) { // <SYSTEM> pins
//
if (IO) {
bitWrite(powResult, pins[i], 1); // output
} else {
bitWrite(powResult, pins[i], 0); // input
} // if-else
//
} // if
//
} // for
//
return (powResult);
//
} // makeBitMaskRange()
uint32_t makeBitMaskRangeNonClobber(uint8_t pins[], uint8_t pinCount, bool IO) {
//
uint8_t val = 0;
uint32_t powResult = getAllPinDirections();
//
for (uint8_t i = 0; i < pinCount; i++) {
//
val = pins[i];
//
if ( ((val < 23) || (val > 25)) && ((val < 29) || (val > 31)) ) { // <SYSTEM> pins
//
if (IO) {
bitWrite(powResult, pins[i], 1); // output
} else {
bitWrite(powResult, pins[i], 0); // input
} // if-else
//
} // if
//
} // for
//
return (powResult);
//
} // makeBitMaskRangeNonClobber()
uint32_t makePutMask(uint8_t vals[], uint8_t pinVals) {
//
uint32_t powResult;
//
for (uint8_t i = 0; i < pinVals; i++) {
//
if ( ((i < 23) || (i > 25)) && ((i < 29) || (i > 31)) ) { // <SYSTEM> pins
//
if (vals[i]) {
bitWrite(powResult, i, 1); // output
} else {
bitWrite(powResult, i, 0); // input
} // if-else
//
} // if
//
} // for
//
return (powResult);
//
} // makePutMask()
void diagnosePinDir() {
//
for (uint8_t i = 0; i < 30; i++) {
//
if (i == 8 || i == 16 || i == 24) Serial1.println();
//
Serial1.print("GPIO");
Serial1.print(i);
Serial1.print(": ");
//
if (i <= 9) Serial1.print(" ");
//
Serial1.print(gpio_get_function(i));
Serial1.print(" ");
Serial1.print(gpio_get_dir(i));
Serial1.print(" ");
//
} // for
//
Serial1.println();
//
} // diagnosePinDir()
void setAllDigital() {
//
for (uint8_t i = 0; i < 31; i++) {
//
if ( ((i < 23) || (i > 25)) && ((i < 29) || (i > 31)) ) { // <SYSTEM> pins
//
gpio_set_function(i, GPIO_FUNC_SIO);
_gpio_init(i); // original written as: gpio_init(), but not accepted on <wokwi.com>
//
} // if
//
} // for
//
} // setAllDigital()
void setAllOutput() {
//
gpio_set_dir_all_bits(makeBitMaskOutAll());
setOE(makeBitMaskOutAll());
//
} // setAllOutput()
void setAllInput() {
//
gpio_set_dir_all_bits(makeBitMaskInAll());
setOE(makeBitMaskInAll());
//
} // setAllInput()
void setRangeDigital(uint8_t pins[], uint8_t pinCount) {
//
uint8_t val = 0;
//
for (uint8_t i = 0; i < pinCount; i++) {
//
val = pins[i];
//
if ( ((val < 23) || (val > 25)) && ((val < 29) || (val > 31)) ) { // <SYSTEM> pins
//
gpio_set_function(pins[i], GPIO_FUNC_SIO);
_gpio_init(pins[i]); // original written as: gpio_init(), but not accepted on <wokwi.com>
//
} // if
//
} // for
//
} // setRangeDigital()
void setRangeOutput(uint8_t pins[], uint8_t pinCount) {
//
gpio_set_dir_all_bits(makeBitMaskRange(pins, pinCount, 1));
setOE(makeBitMaskRange(pins, pinCount, 1));
//
} // setRangeOutput()
void setRangeInput(uint8_t pins[], uint8_t pinCount) {
//
gpio_set_dir_all_bits(makeBitMaskRange(pins, pinCount, 0));
setOE(makeBitMaskRange(pins, pinCount, 0));
//
} // setRangeInput()
void setPortRange(uint8_t startPin, uint8_t endPin, bool IO) {
// port direction 0 for input 1 for output:
uint8_t pinCount = countMidNums(startPin, endPin);
//
uint8_t portPins2[pinCount];
for (uint8_t i = startPin; i <= endPin; i++) portPins2[i] = i;
//
if (IO) {
//output
//gpio_set_dir_all_bits(makeBitMaskRange(pins, pinCount, 1)); // Note: -pins- isn't declared here
//setOE(makeBitMaskRange(pins, pinCount, 1)); // Note: -pins- isn't declared here
gpio_set_dir_all_bits(makeBitMaskRange(portPins2, pinCount, 1));
setOE(makeBitMaskRange(portPins2, pinCount, 1));
//
} else {
//input
//gpio_set_dir_all_bits(makeBitMaskRange(pins, pinCount, 0)); // Note: -pins- isn't declared here
//setOE(makeBitMaskRange(pins, pinCount, 0)); // Note: -pins- isn't declared here
gpio_set_dir_all_bits(makeBitMaskRange(portPins2, pinCount, 0));
setOE(makeBitMaskRange(portPins2, pinCount, 0));
//
} // if-else
//
} // setPortRange()
void setPortRangeNonClobber(uint8_t startPin, uint8_t endPin, bool IO) {
// port direction 0 for input 1 for output:
uint8_t pinCount = countMidNums(startPin, endPin);
//
uint8_t portPins2[pinCount];
for (uint8_t i = startPin; i <= endPin; i++) portPins2[i] = i;
//
if (IO) {
//output
//gpio_set_dir_all_bits(makeBitMaskRangeNonClobber(pins, pinCount, 1)); // Note: -pins- isn't declared here
//setOE(makeBitMaskRangeNonClobber(pins, pinCount, 1)); // Note: -pins- isn't declared here
gpio_set_dir_all_bits(makeBitMaskRangeNonClobber(portPins2, pinCount, 1));
setOE(makeBitMaskRangeNonClobber(portPins2, pinCount, 1));
//
} else {
//input
//gpio_set_dir_all_bits(makeBitMaskRangeNonClobber(pins, pinCount, 0)); // Note: -pins- isn't declared here
//setOE(makeBitMaskRangeNonClobber(pins, pinCount, 0)); // Note: -pins- isn't declared here
gpio_set_dir_all_bits(makeBitMaskRangeNonClobber(portPins2, pinCount, 0));
setOE(makeBitMaskRangeNonClobber(portPins2, pinCount, 0));
//
} // if-else
//
} // setPortRangeNonClobber()
uint32_t readAllPorts() {
//
uint32_t bitMask = gpio_get_all();
return (bitMask);
//
} // readAllPorts()
uint32_t readPortRange(uint8_t startPin, uint8_t endPin) {
//
uint32_t portVal = 0;
//
for (uint8_t i = startPin; i <= endPin; i++) {
// The gpio_get() function is used to get the digital state
// of the GPIO pin (0 for low, non-zero for high).
if (gpio_get(i) == 0) {
bitWrite(portVal, i, 0);
} else {
bitWrite(portVal, i, 1);
} // if-else
//
} // for
//
return (portVal);
//
} // readPortRange()
uint32_t readPort1(uint8_t pins[], uint8_t pinCount) {
//
uint32_t portVal = 0;
//
for (uint8_t i = 0; i < pinCount; i++) {
// The gpio_get() function is used to get the digital state
// of the GPIO pin (0 for low, non-zero for high).
if (gpio_get(pins[i]) == 0) {
bitWrite(portVal, i, 0);
} else {
bitWrite(portVal, i, 1);
} // if-else
//
} // for
//
return (portVal);
//
} // readPort1()
uint8_t readGPIOport(uint8_t gpio) {
//
// create a mask with ONLY the bit at position -gpio- set to -1-
uint32_t GPIOmask32 = 1UL << gpio;
// overlay the mask over all GPIO states ('bitwise' AND operator)
uint32_t GPIOstates32 = gpio_get_all() & GPIOmask32; // Pi Pico C++ SDK
// read the state of the bit at position -gpio-
return bitRead(GPIOstates32, gpio); // returns 0 or 1
//
} // readGPIOport()
void writeGPIOport(uint8_t gpio, bool value) {
//
// create a mask with ONLY the bit at position -gpio- set to -1-
uint32_t GPIOmask32 = 1UL << gpio;
//
if (value) {
// set to ONE the bit at position -gpio-
gpio_set_mask(GPIOmask32); // Pi Pico C++ SDK
//
} else {
// set to ZERO the bit at position -gpio-
gpio_clr_mask(GPIOmask32); // Pi Pico C++ SDK
//
} // if-else
//
} // writeGPIOport()
void writeAllPorts(uint32_t bitMask) {
//
gpio_put_all(bitMask);
//
} // writeAllPorts()
void writeAllPorts1(uint8_t pinValues[], uint8_t pinValuesCount) {
//
gpio_put_all(makePutMask(pinValues, pinValuesCount));
//
} // writeAllPorts1()
void writePortRange(uint8_t pins[], uint8_t pinCount, uint8_t pinValues[], uint8_t pinValuesCount) {
//
if (pinCount != pinValuesCount) return;
//
for (uint8_t i = 0; i < pinCount; i++) {
// <SYSTEM> pins
if ( ((i < 23) || (i > 25)) && ((i < 29) || (i > 31)) ) gpio_put(pins[i], pinValues[i]);
//
} // for
//
} // writePortRange()
void writePortRange1(uint8_t startPin, uint8_t endPin, uint8_t pinValues[], uint8_t pinValuesCount) {
//
uint8_t pinCount = countMidNums(startPin, endPin);
uint8_t portPins2[pinCount];
//
for (uint8_t i = startPin; i <= endPin; i++) portPins2[i] = i;
//
if (pinCount != pinValuesCount) return;
//
for (uint8_t i = startPin; i <= endPin; i++) gpio_put(portPins2[i], pinValues[i]);
//
} // writePortRange1()
uint32_t reverseBits(uint32_t inBits) {
//
uint32_t outBits = 0;
//
for (uint8_t i = 0; i < 31; i++) bitWrite(outBits, 31 - i, bitRead(inBits, i));
//
return (outBits);
//
} // reverseBits()
void checkBits(uint8_t bInput, bool lineEnd) {
//00011100011111111111111000000000
//
Serial1.print("Bit0: ");
if (bitRead(bInput, 0)) {
Serial1.print("True ");
} else {
Serial1.print("False ");
} // if-else
//
Serial1.print("Bit1: ");
if (bitRead(bInput, 1)) {
Serial1.print("True ");
} else {
Serial1.print("False ");
} // if-else
//
Serial1.print("Bit2: ");
if (bitRead(bInput, 2)) {
Serial1.print("True ");
} else {
Serial1.print("False ");
} // if-else
//
Serial1.print("Bit3: ");
if (bitRead(bInput, 3)) {
Serial1.print("True ");
} else {
Serial1.print("False ");
} // if-else
//
Serial1.print("Bit4: ");
if (bitRead(bInput, 4)) {
Serial1.print("True ");
} else {
Serial1.print("False ");
} // if-else
//
Serial1.print("Bit5: ");
if (bitRead(bInput, 5)) {
Serial1.print("True ");
} else {
Serial1.print("False ");
} // if-else
//
Serial1.print("Bit6: ");
if (bitRead(bInput, 6)) {
Serial1.print("True ");
} else {
Serial1.print("False ");
} // if-else
//
Serial1.print("Bit7: ");
if (bitRead(bInput, 7)) {
Serial1.print("True ");
} else {
Serial1.print("False ");
} // if-else
//
if (lineEnd) Serial1.println();
//
} // checkBits()
void printBinary8(uint8_t inByte, bool lineEnd, bool MSB) {
//
if (MSB) {
for (uint8_t b = 7; b >= 0; b--) Serial1.print(bitRead(inByte, b)); //bit 7-0
} else {
for (uint8_t b = 0; b < 8; b++) Serial1.print(bitRead(inByte, b)); //bit 0-7
} // if-else
//
if (lineEnd) Serial1.println();
//
} // printBinary8()
void printBinary32(uint32_t inByte, bool lineEnd, bool MSB) {
//
if (MSB) {
for (uint8_t b = 31; b >= 0; b--) Serial1.print(bitRead(inByte, b)); //bit 31-0
} else {
for (uint8_t b = 0; b < 32; b++) Serial1.print(bitRead(inByte, b)); //bit 0-31
} // if-else
//
if (lineEnd) Serial1.println();
//
} // printBinary32()
// --------------------------------------------------------------------------------------
void setup() {
//
Serial1.begin(115200);
//
/* *** NOTE: in the REAL world, the SERIAL MUST BE >>> Serial.xx() <<< -NOT- Serial1.xx() **** */
/* *** NOTE: in the REAL world, the SERIAL MUST BE >>> Serial.xx() <<< -NOT- Serial1.xx() **** */
/* *** NOTE: In the REAL world, the SERIAL MUST BE >>> Serial.xx() <<< -NOT- Serial1.xx() **** */
//
// in the REAL world, WHITOUT THIS FOLLOWING LINE OF CODE, the serial monitor does not work!!!
//while (! Serial); // in the REAL world, WHITOUT THIS LINE OF CODE, the serial monitor does not work!!!
// in the REAL world, WHITOUT THE PREVIOUS LINE OF CODE, the serial monitor does not work!!!
//
/* *** NOTE: in the REAL world, the SERIAL MUST BE >>> Serial.xx() <<< -NOT- Serial1.xx() **** */
/* *** NOTE: in the REAL world, the SERIAL MUST BE >>> Serial.xx() <<< -NOT- Serial1.xx() **** */
/* *** NOTE: in the REAL world, the SERIAL MUST BE >>> Serial.xx() <<< -NOT- Serial1.xx() **** */
//
Serial1.println("setup() ended...\n");
//
} // setup()
void loop() {
//
delay(10);
//
} // loop()