Unverified Commit 916c31d9 authored by Pontus Oldberg's avatar Pontus Oldberg Committed by GitHub

Adds iLabs RP2040 Connectivity (LTE/WIFI/BLE) board. (#1936)

parent 403c147f
This diff is collapsed.
......@@ -140,6 +140,9 @@
{
"name": "iLabs Challenger 2040 UWB"
},
{
"name": "iLabs Connectivity 2040 LTE/WiFi/BLE"
},
{
"name": "iLabs RPICO32"
},
......
{
"build": {
"arduino": {
"earlephilhower": {
"boot2_source": "boot2_w25q080_2_padded_checksum.S",
"usb_vid": "0x2E8A",
"usb_pid": "0x107B"
}
},
"core": "earlephilhower",
"cpu": "cortex-m0plus",
"extra_flags": "-D ARDUINO_CONNECTIVITY_2040_LTE_WIFI_BLE_RP2040 -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=500 -DWIFIESPAT2",
"f_cpu": "133000000L",
"hwids": [
[
"0x2E8A",
"0x00C0"
],
[
"0x2E8A",
"0x107B"
]
],
"mcu": "rp2040",
"variant": "connectivity_2040_lte_wifi_ble"
},
"debug": {
"jlink_device": "RP2040_M0_0",
"openocd_target": "rp2040.cfg",
"svd_path": "rp2040.svd"
},
"frameworks": [
"arduino"
],
"name": "Connectivity 2040 LTE/WiFi/BLE",
"upload": {
"maximum_ram_size": 270336,
"maximum_size": 8388608,
"require_upload_port": true,
"native_usb": true,
"use_1200bps_touch": true,
"wait_for_upload_port": false,
"protocol": "picotool",
"protocols": [
"blackmagic",
"cmsis-dap",
"jlink",
"raspberrypi-swd",
"picotool",
"picoprobe",
"pico-debug"
]
},
"url": "https://www.raspberrypi.org/products/raspberry-pi-pico/",
"vendor": "iLabs"
}
......@@ -9,7 +9,7 @@
},
"core": "earlephilhower",
"cpu": "cortex-m0plus",
"extra_flags": "-D ARDUINO_ILABS_2040_RPICO32_RP2040 -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=250",
"extra_flags": "-D ARDUINO_ILABS_2040_RPICO32_RP2040 -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=250 -DWIFIESPAT2",
"f_cpu": "133000000L",
"hwids": [
[
......
......@@ -407,7 +407,8 @@ MakeBoard("challenger_nb_2040_wifi", "iLabs", "Challenger NB 2040 WiFi", "0x2e8a
MakeBoard("challenger_2040_sdrtc", "iLabs", "Challenger 2040 SD/RTC", "0x2e8a", "0x102d", 250, "CHALLENGER_2040_SDRTC_RP2040", 8, "boot2_w25q080_2_padded_checksum")
MakeBoard("challenger_2040_nfc", "iLabs", "Challenger 2040 NFC", "0x2e8a", "0x1036", 250, "CHALLENGER_2040_NFC_RP2040", 8, "boot2_w25q080_2_padded_checksum")
MakeBoard("challenger_2040_uwb", "iLabs", "Challenger 2040 UWB", "0x2e8a", "0x1052", 500, "CHALLENGER_2040_UWB_RP2040", 8, "boot2_w25q080_2_padded_checksum")
MakeBoard("ilabs_rpico32", "iLabs", "RPICO32", "0x2e8a", "0x1010", 250, "ILABS_2040_RPICO32_RP2040", 8, "boot2_w25q080_2_padded_checksum")
MakeBoard("connectivity_2040_lte_wifi_ble", "iLabs", "Connectivity 2040 LTE/WiFi/BLE", "0x2e8a", "0x107b", 500, "CONNECTIVITY_2040_LTE_WIFI_BLE_RP2040", 8, "boot2_w25q080_2_padded_checksum", ["WIFIESPAT2"])
MakeBoard("ilabs_rpico32", "iLabs", "RPICO32", "0x2e8a", "0x1010", 250, "ILABS_2040_RPICO32_RP2040", 8, "boot2_w25q080_2_padded_checksum", ["WIFIESPAT2"])
# Melopero
MakeBoard("melopero_cookie_rp2040", "Melopero", "Cookie RP2040", "0x2e8a", "0x1011", 250, "MELOPERO_COOKIE_RP2040", 8, "boot2_w25q080_2_padded_checksum")
......
/*
UBlox SARA/ESP helper class for the Connectivity RP2040 LTE/WIFI/BLE board
Copyright (c) 2024 P. Oldberg <pontus@ilabs.se>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <Arduino.h>
#include <Connectivity.h>
iLabsConnectivityClass::iLabsConnectivityClass(HardwareSerial* espSerial, HardwareSerial* modemSerial) {
_espSerial = espSerial;
_modemSerial = modemSerial;
/* SARA pins */
pinMode(PIN_SARA_ON, OUTPUT);
digitalWrite(PIN_SARA_ON, LOW); // Output register must always be low
pinMode(PIN_SARA_ON, INPUT_PULLUP);
pinMode(PIN_SARA_RST, INPUT_PULLUP); // Keep as input for now
pinMode(PIN_SARA_PWR, OUTPUT);
digitalWrite(PIN_SARA_PWR, LOW); // No power to SARA yet
pinMode(PIN_SARA_DTR, OUTPUT);
digitalWrite(PIN_SARA_PWR, HIGH); // Make sure DTR is low on the R412M
modemSerialPortConfigured = false;
/* ESP Pins */
pinMode(PIN_ESP_RST, OUTPUT);
digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset
pinMode(PIN_ESP_MODE, OUTPUT);
digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start
espSerialPortConfigured = false;
}
// Do a HW reset by applying a low pulse to the reset line for 1mSec
bool iLabsConnectivityClass::doModemPowerOn() {
bool ret;
digitalWrite(PIN_SARA_PWR, HIGH); // Make sure LDO is on
delay(100); // let the power stabilize
pinMode(PIN_SARA_ON, OUTPUT); // Pull power on control low
delay(150); // For 150mS
pinMode(PIN_SARA_ON, INPUT_PULLUP); // before releasing it again.
delay(1000); // Now wait for 1 second
SARA_SERIAL_PORT.setRTS(PIN_SERIAL2_RTS); // Enable hardware handshaking
SARA_SERIAL_PORT.setCTS(PIN_SERIAL2_CTS);
SARA_SERIAL_PORT.begin(DEFAULT_SARA_BAUDRATE);
modemSerialPortConfigured = true;
ret = isModemAlive(); // Make sure the modem is up and running
delay(250); // Allow for any extra characters
// before flushing the input buffer
while (SARA_SERIAL_PORT.available()) {
SARA_SERIAL_PORT.read();
}
return ret;
}
// Checks to see if the modem responds to the "AT" poll command.
bool iLabsConnectivityClass::isModemAlive(uint32_t timeout) {
SARA_SERIAL_PORT.setTimeout(100);
SARA_SERIAL_PORT.println(F("AT"));
String rdy = SARA_SERIAL_PORT.readStringUntil('\n');
while (!rdy.startsWith(F("OK")) && --timeout) {
SARA_SERIAL_PORT.println(F("AT"));
rdy = SARA_SERIAL_PORT.readStringUntil('\n');
//Serial.println(rdy);
}
SARA_SERIAL_PORT.setTimeout(1000); // Restore serial timeout
if (timeout) {
return true;
}
return false;
}
// Return the current MNO profile
// Returns -1 if the serial port is not yet setup or the number of the current
// MNO profile setting from the modem.
int iLabsConnectivityClass::getModemMNOProfile() {
if (!modemSerialPortConfigured) {
return -1;
}
SARA_SERIAL_PORT.println(F("AT+UMNOPROF?"));
String resp = getModemResponse();
return resp.substring(resp.indexOf("+UMNOPROF: ") + 11).toInt();
}
// Set a new MNO profile
// Returns false if the serial port is not yet setup or if an error
// is detected during the communication with the modem.
// This call is synchronous and will wait for the modem to start after
// the soft restart which takes about 10 seconds.
bool iLabsConnectivityClass::setModemMNOProfile(int profile) {
if (!modemSerialPortConfigured) {
return false;
}
// Disconnect from the network
SARA_SERIAL_PORT.println("AT+COPS=2");
if (!getModemResponse().endsWith("OK")) {
return false;
}
String cmd = "AT+UMNOPROF=" + String(profile) + ",1";
SARA_SERIAL_PORT.println(cmd);
if (!getModemResponse().endsWith("OK")) {
return false;
}
// Restart the modem to apply the new MNO profile
SARA_SERIAL_PORT.println("AT+CFUN=15");
if (!getModemResponse().endsWith("OK")) {
return false;
}
return isModemAlive(15000);
}
// Disable power save features
bool iLabsConnectivityClass::enableModemPS(bool enable) {
if (!modemSerialPortConfigured) {
return false;
}
if (enable) {
SARA_SERIAL_PORT.println(F("AT+CPSMS=1"));
} else {
SARA_SERIAL_PORT.println(F("AT+CPSMS=0"));
}
if (!getModemResponse().endsWith("OK")) {
return false;
}
return true;
}
// Get a response from SARA
// A default serial timeout of 2 seconds allow for reading really slow
// responses which should accommodate most replies. Replies are then trimmed
// from control characters and appended with a tab character as a separator.
//
String iLabsConnectivityClass::getModemResponse(int timeout) {
SARA_SERIAL_PORT.setTimeout(2000); // allow for really slow responses
String resp = SARA_SERIAL_PORT.readStringUntil('\n');
resp.trim();
String acc = resp;
while (resp.indexOf("OK") == -1 && resp.indexOf("ERROR") == -1 && --timeout) {
resp = SARA_SERIAL_PORT.readStringUntil('\n');
resp.trim();
if (resp.length()) {
acc += "\t" + resp;
}
}
return acc;
}
// Do a HW reset by applying a low pulse to the reset line for 1mSec
void iLabsConnectivityClass::doEspHWReset() {
digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset
delay(1);
digitalWrite(PIN_ESP_RST, HIGH); // Release ESP reset
}
// Set the mode flag high to indicate normal run operation and do a HW
// reset.
void iLabsConnectivityClass::runEspReset() { // Prepare ESP for normal op
digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start
doEspHWReset();
}
// Set the mode flag low to indicate flash operation and do a HW
// reset.
void iLabsConnectivityClass::flashEspReset() { // Prepare ESP for flashing
digitalWrite(PIN_ESP_MODE, LOW); // Prepare for normal start
doEspHWReset();
}
// Wait for the modem to reply with a "ready" prompt. This can be done
// after a sw or hw reset have been performed to ensure that the AT
// interpreter is up and running.
bool iLabsConnectivityClass::waitForEspReady() {
int timeout = 20; // Aprox max 2 sec
_espSerial->setTimeout(100);
String rdy = _espSerial->readStringUntil('\n');
while (!rdy.startsWith("ready") && timeout--) {
rdy = _espSerial->readStringUntil('\n');
}
_espSerial->setTimeout(1000); // Reset default timeout to 1000
if (timeout) {
return true;
}
return false;
}
// Reset the ESP and wait for the "ready" prompt to be returned.
bool iLabsConnectivityClass::resetEsp() {
runEspReset();
_espSerial->begin(DEFAULT_ESP_BAUDRATE);
return waitForEspReady();
}
// Checks to see if the modem responds to the "AT" poll command.
bool iLabsConnectivityClass::isEspAlive() {
int timeout = 100;
_espSerial->setTimeout(250);
_espSerial->println(F("AT"));
String rdy = _espSerial->readStringUntil('\n');
while (!rdy.startsWith(F("OK")) && timeout--) {
_espSerial->println(F("AT"));
rdy = _espSerial->readStringUntil('\n');
}
_espSerial->setTimeout(1000);
if (timeout) {
return true;
}
return false;
}
// Change the baud rate of the ESP device as well as the local UART.
// No checking is done on the input baud rate so the user must know what
// baud rates are valid. The function ends by checking if the ESP is
// reachable by doing an "AT" poll.
bool iLabsConnectivityClass::changeEspBaudRate(int baud) {
_espSerial->print(F("AT+UART_CUR="));
_espSerial->print(baud);
_espSerial->println(F(",8,1,0,0"));
delay(100);
_espSerial->end();
_espSerial->begin(baud);
return isEspAlive();
}
// This method should be called if the builtin object isn't needed any more
// It basically just releases the UART pins for other use.
void iLabsConnectivityClass::releaseEsp() {
_espSerial->end();
}
// We can assign a new hardware serial port to accommodate the ESP device here.
// The function will release the previously used serial port and assign the
// new port. The ESP will be left in a reset state ready to start normal
// operation when exiting the function.
// This function is useful for when using the PIO serial ports to communicate
// with the ESP instead of the built in hardware serial port.
void iLabsConnectivityClass::setEspSerial(HardwareSerial* serial) {
releaseEsp();
_espSerial = serial;
pinMode(PIN_ESP_RST, OUTPUT);
digitalWrite(PIN_ESP_RST, LOW); // Hold ESP in reset
pinMode(PIN_ESP_MODE, OUTPUT);
digitalWrite(PIN_ESP_MODE, HIGH); // Prepare for normal start
}
// Return the current serial object
HardwareSerial* iLabsConnectivityClass::getEspSerial() {
return _espSerial;
}
iLabsConnectivityClass iLabsConnectivity;
/*
UBlox SARA/ESP helper class for the Connectivity RP2040 LTE/WIFI/BLE board
Copyright (c) 2024 P. Oldberg <pontus@ilabs.se>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#define DEFAULT_SARA_BAUDRATE 115200
#define DEFAULT_ESP_BAUDRATE 115200
class iLabsConnectivityClass {
public:
iLabsConnectivityClass(HardwareSerial* = &ESP_SERIAL_PORT, HardwareSerial* = &SARA_SERIAL_PORT);
// Modem stuff
bool doModemPowerOn();
bool isModemAlive(uint32_t timeout = 50);
int getModemMNOProfile();
bool setModemMNOProfile(int profile);
bool enableModemPS(bool enable = true);
String getModemResponse(int timeout = 5);
// ESP stuff
void doEspHWReset();
void runEspReset();
void flashEspReset();
bool waitForEspReady();
bool resetEsp();
bool isEspAlive();
bool changeEspBaudRate(int);
void releaseEsp();
void setEspSerial(HardwareSerial*);
HardwareSerial* getEspSerial();
private:
bool modemSerialPortConfigured;
bool espSerialPortConfigured;
HardwareSerial* _espSerial;
HardwareSerial* _modemSerial;
};
extern iLabsConnectivityClass iLabsConnectivity;
#pragma once
// LEDs
#define PIN_LED (19u)
// Serial1, (UART0) Connected to ESP32 chip)
#define PIN_SERIAL1_TX (16u)
#define PIN_SERIAL1_RX (17u)
#define PIN_ESP32_RST (24u)
#define PIN_ESP32_MODE (25u)
#define ESP32_SERIAL Serial1
// Uart define esp serial abstraction pins
#define PIN_ESP_TX PIN_SERIAL1_TX
#define PIN_ESP_RX PIN_SERIAL1_RX
#define PIN_ESP_RST PIN_ESP32_RST
#define PIN_ESP_MODE PIN_ESP32_MODE
#define ESP_SERIAL_PORT ESP32_SERIAL
// Serial2, (UART1) connected to SARA-R4XX modem
#define PIN_SERIAL2_TX (4u)
#define PIN_SERIAL2_RX (5u)
#define PIN_SERIAL2_CTS (6u)
#define PIN_SERIAL2_RTS (7u)
#define PIN_SARA_DTR (12u)
#define PIN_SARA_ON (13u)
#define PIN_SARA_RST (14u)
#define PIN_SARA_PWR (15u)
#define SARA_SERIAL_PORT Serial2
// SPI
#define PIN_SPI0_MISO (20u)
#define PIN_SPI0_MOSI (23u)
#define PIN_SPI0_SCK (22u)
#define PIN_SPI0_SS (21u)
// Not pinned out
#define PIN_SPI1_MISO (31u)
#define PIN_SPI1_MOSI (31u)
#define PIN_SPI1_SCK (31u)
#define PIN_SPI1_SS (31u)
// Wire
#define PIN_WIRE0_SDA (0u)
#define PIN_WIRE0_SCL (1u)
// Not pinned out
#define PIN_WIRE1_SDA (31u)
#define PIN_WIRE1_SCL (31u)
#define SERIAL_HOWMANY (2u)
#define SPI_HOWMANY (1u)
#define WIRE_HOWMANY (1u)
#include "../generic/common.h"
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment