kopia lustrzana https://github.com/pimoroni/pimoroni-pico
commit
1495805d2b
|
@ -22,6 +22,8 @@ jobs:
|
|||
board: RPI_PICO
|
||||
- name: pico_usb
|
||||
board: RPI_PICO_USB
|
||||
- name: pico_ppp
|
||||
board: RPI_PICO_PPP
|
||||
- name: picow
|
||||
board: RPI_PICO_W
|
||||
- name: tiny2040_8mb
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"deploy": [
|
||||
"../deploy.md"
|
||||
],
|
||||
"docs": "",
|
||||
"features": [
|
||||
"Breadboard friendly",
|
||||
"Castellated Pads",
|
||||
"Micro USB"
|
||||
],
|
||||
"id": "rp2-pico",
|
||||
"images": [
|
||||
"rp2-pico.jpg"
|
||||
],
|
||||
"mcu": "rp2040",
|
||||
"product": "Pico",
|
||||
"thumbnail": "",
|
||||
"url": "https://www.raspberrypi.com/products/raspberry-pi-pico/",
|
||||
"vendor": "Raspberry Pi"
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
include("$(PORT_DIR)/boards/manifest.py")
|
||||
|
||||
require("bundle-networking")
|
||||
|
||||
include("../manifest_pico.py")
|
||||
|
||||
freeze("../../modules_py", "lte.py")
|
|
@ -0,0 +1,9 @@
|
|||
# cmake file for Raspberry Pi Pico
|
||||
set(PICO_BOARD "pico")
|
||||
|
||||
set(MICROPY_PY_LWIP ON)
|
||||
|
||||
# Board specific version of the frozen manifest
|
||||
set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)
|
||||
|
||||
set(MICROPY_C_HEAP_SIZE 4096)
|
|
@ -0,0 +1,16 @@
|
|||
// Board and hardware specific configuration
|
||||
#define MICROPY_HW_BOARD_NAME "Raspberry Pi Pico"
|
||||
#define MICROPY_HW_FLASH_STORAGE_BYTES (1024 * 1024)
|
||||
|
||||
// Enable networking.
|
||||
#define MICROPY_PY_NETWORK 1
|
||||
#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "Pico"
|
||||
|
||||
#define MICROPY_PY_NETWORK_PPP_LWIP 1
|
||||
|
||||
#define MICROPY_HW_NIC_PPP { MP_ROM_QSTR(MP_QSTR_PINT), MP_ROM_PTR(&mp_network_ppp_lwip_type) },
|
||||
|
||||
#define MICROPY_BOARD_NETWORK_INTERFACES \
|
||||
MICROPY_HW_NIC_PPP
|
||||
|
||||
#define MICROPY_PY_SOCKET_EXTENDED_STATE 1
|
|
@ -0,0 +1,28 @@
|
|||
GP0,GPIO0
|
||||
GP1,GPIO1
|
||||
GP2,GPIO2
|
||||
GP3,GPIO3
|
||||
GP4,GPIO4
|
||||
GP5,GPIO5
|
||||
GP6,GPIO6
|
||||
GP7,GPIO7
|
||||
GP8,GPIO8
|
||||
GP9,GPIO9
|
||||
GP10,GPIO10
|
||||
GP11,GPIO11
|
||||
GP12,GPIO12
|
||||
GP13,GPIO13
|
||||
GP14,GPIO14
|
||||
GP15,GPIO15
|
||||
GP16,GPIO16
|
||||
GP17,GPIO17
|
||||
GP18,GPIO18
|
||||
GP19,GPIO19
|
||||
GP20,GPIO20
|
||||
GP21,GPIO21
|
||||
GP22,GPIO22
|
||||
GP25,GPIO25
|
||||
GP26,GPIO26
|
||||
GP27,GPIO27
|
||||
GP28,GPIO28
|
||||
LED,GPIO25
|
|
|
@ -31,6 +31,9 @@ include(wakeup/micropython)
|
|||
# Configure wakeup for Enviro
|
||||
target_compile_definitions(usermod_wakeup INTERFACE
|
||||
-DWAKEUP_HAS_RTC=1
|
||||
-DWAKEUP_PIN_MASK=0b01000100
|
||||
-DWAKEUP_PIN_DIR=0b01000100
|
||||
-DWAKEUP_PIN_VALUE=0b01000100
|
||||
)
|
||||
|
||||
# LEDs & Matrices
|
||||
|
|
|
@ -33,6 +33,9 @@ include(wakeup/micropython)
|
|||
target_compile_definitions(usermod_wakeup INTERFACE
|
||||
-DWAKEUP_HAS_RTC=1
|
||||
-DWAKEUP_HAS_SHIFT_REGISTER=1
|
||||
-DWAKEUP_PIN_MASK=0b01000100
|
||||
-DWAKEUP_PIN_DIR=0b01000100
|
||||
-DWAKEUP_PIN_VALUE=0b01000100
|
||||
)
|
||||
|
||||
# LEDs & Matrices
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
include_directories(${CMAKE_CURRENT_LIST_DIR}/../../)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../")
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../")
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
include(micropython-common)
|
||||
|
||||
# C++ Magic Memory
|
||||
include(cppmem/micropython)
|
||||
|
||||
# Disable build-busting C++ exceptions
|
||||
include(micropython-disable-exceptions)
|
|
@ -5,7 +5,6 @@ add_library(usermod_${MOD_NAME} INTERFACE)
|
|||
target_sources(usermod_${MOD_NAME} INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.cpp
|
||||
#${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.S
|
||||
)
|
||||
|
||||
target_include_directories(usermod_${MOD_NAME} INTERFACE
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
|
||||
.syntax unified
|
||||
.cpu cortex-m0plus
|
||||
.thumb
|
||||
|
||||
#include "pico/asm_helper.S"
|
||||
|
||||
// This macro tells the pico runtime to call __wakeup_gpio_latch very early in boot
|
||||
__pre_init __wakeup_gpio_latch, 00000
|
||||
|
||||
.section .data.wakeup_gpio_latch
|
||||
.global wakeup_gpio_state
|
||||
.align 4
|
||||
wakeup_gpio_state:
|
||||
.word 0x00000000
|
||||
|
||||
.section .text
|
||||
.thumb_func
|
||||
__wakeup_gpio_latch:
|
||||
// Read GPIO state for front buttons and store
|
||||
movs r3, 0xd0 // Load 0xd0 into r3
|
||||
lsls r3, r3, 24 // Shift left 24 to get 0xd0000000
|
||||
ldr r1, [r3, 4] // Load GPIO state (0xd0000004) into r1
|
||||
ldr r2, =wakeup_gpio_state // Load output var addr into r2
|
||||
str r1, [r2] // Store r1 to r2
|
||||
|
||||
// Enable 3v3 pin on the badger
|
||||
ldr r1, =0x40014054 // GPIO control register 10
|
||||
movs r2, 5 // SIO function
|
||||
str r2, [r1] // Set Enable 3v3 to SIO // https://github.com/raspberrypi/pico-sdk/blob/2e6142b15b8a75c1227dd3edbe839193b2bf9041/src/rp2_common/hardware_gpio/include/hardware/gpio.h#L96
|
||||
str r2, [r1, 120] // Also set LED (25) to SIO
|
||||
ldr r2, =0x02000400 // Pins 25 and 10
|
||||
str r2, [r3, 36] // Enable pins out
|
||||
str r2, [r3, 20] // Set pins high
|
||||
|
||||
bx lr // Return
|
|
@ -1,18 +1,30 @@
|
|||
#include "hardware/gpio.h"
|
||||
#include "wakeup.config.hpp"
|
||||
|
||||
extern uint32_t runtime_wakeup_gpio_state;
|
||||
|
||||
namespace {
|
||||
struct Wakeup {
|
||||
public:
|
||||
uint8_t shift_register_state = 0b0;
|
||||
uint32_t gpio_state = 0;
|
||||
|
||||
Wakeup() {
|
||||
// Assert wakeup pins (indicator LEDs, VSYS hold etc)
|
||||
//gpio_init_mask(WAKEUP_PIN_MASK);
|
||||
//gpio_set_dir_masked(WAKEUP_PIN_MASK, WAKEUP_PIN_DIR);
|
||||
//gpio_put_masked(WAKEUP_PIN_MASK, WAKEUP_PIN_VALUE);
|
||||
gpio_init_mask(WAKEUP_PIN_MASK);
|
||||
gpio_set_dir_masked(WAKEUP_PIN_MASK, WAKEUP_PIN_DIR);
|
||||
gpio_put_masked(WAKEUP_PIN_MASK, WAKEUP_PIN_VALUE);
|
||||
|
||||
// Init all GPIOS not specified in the wakeup mask
|
||||
#if PICO_RP2350
|
||||
gpio_init_mask(~WAKEUP_PIN_MASK);
|
||||
gpio_set_dir_in_masked(~WAKEUP_PIN_MASK);
|
||||
#endif
|
||||
gpio_state = gpio_get_all();
|
||||
sleep_ms(5);
|
||||
gpio_state |= gpio_get_all();
|
||||
#if PICO_RP2350
|
||||
gpio_init_mask(~WAKEUP_PIN_MASK);
|
||||
#endif
|
||||
|
||||
#if WAKEUP_HAS_RTC==1
|
||||
// Set up RTC I2C pins and send reset command
|
||||
|
@ -59,11 +71,11 @@ extern "C" {
|
|||
#include "wakeup.h"
|
||||
|
||||
mp_obj_t Wakeup_get_gpio_state() {
|
||||
return mp_obj_new_int(runtime_wakeup_gpio_state);
|
||||
return mp_obj_new_int(wakeup.gpio_state);
|
||||
}
|
||||
|
||||
mp_obj_t Wakeup_reset_gpio_state() {
|
||||
runtime_wakeup_gpio_state = 0;
|
||||
wakeup.gpio_state = 0;
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,205 @@
|
|||
import time
|
||||
|
||||
from machine import UART, Pin
|
||||
from network import PPP
|
||||
|
||||
from micropython import const
|
||||
|
||||
DEFAULT_PIN_RST = 35
|
||||
DEFAULT_PIN_NETLIGHT = 34
|
||||
DEFAULT_PIN_RX = 33
|
||||
DEFAULT_PIN_TX = 32
|
||||
DEFAULT_UART_ID = 0
|
||||
|
||||
DEFAULT_UART_TIMEOUT = const(1)
|
||||
DEFAULT_UART_TIMEOUT_CHAR = const(1)
|
||||
DEFAULT_UART_RXBUF = const(1024)
|
||||
DEFAULT_UART_STARTUP_BAUD = const(115200)
|
||||
DEFAULT_UART_BAUD = const(460800)
|
||||
|
||||
|
||||
class CellularError(Exception):
|
||||
def __init__(self, message=None):
|
||||
self.message = "CellularError: " + message
|
||||
|
||||
|
||||
class LTE():
|
||||
def __init__(self, apn, uart=None, reset_pin=None, netlight_pin=None, netlight_led=None, skip_reset=False):
|
||||
self._apn = apn
|
||||
self._reset = reset_pin or Pin(DEFAULT_PIN_RST, Pin.OUT)
|
||||
self._uart = uart or UART(
|
||||
DEFAULT_UART_ID,
|
||||
tx=Pin(DEFAULT_PIN_TX, Pin.OUT),
|
||||
rx=Pin(DEFAULT_PIN_RX, Pin.OUT))
|
||||
|
||||
# Set PPP timeouts and rxbuf
|
||||
self._uart.init(
|
||||
timeout=DEFAULT_UART_TIMEOUT,
|
||||
timeout_char=DEFAULT_UART_TIMEOUT_CHAR,
|
||||
rxbuf=DEFAULT_UART_RXBUF)
|
||||
|
||||
if not skip_reset:
|
||||
self._reset.value(0)
|
||||
time.sleep(1.0)
|
||||
self._reset.value(1)
|
||||
|
||||
if netlight_led:
|
||||
self._led = netlight_led
|
||||
self._netlight = netlight_pin or Pin(DEFAULT_PIN_NETLIGHT, Pin.IN)
|
||||
self._netlight.irq(self._netlight_irq)
|
||||
|
||||
def _netlight_irq(self, pin):
|
||||
self._led.value(pin.value())
|
||||
|
||||
def ipconfig(self, *args, **kwargs):
|
||||
if len(args):
|
||||
return self._ppp.ipconfig(*args)
|
||||
else:
|
||||
return self._ppp.ipconfig(**kwargs)
|
||||
|
||||
def iccid(self):
|
||||
try:
|
||||
return self._send_at_command("AT+CICCID", 1)
|
||||
except CellularError:
|
||||
return None
|
||||
|
||||
def status(self):
|
||||
lte_status = self._send_at_command("AT+CEREG?", 1)
|
||||
gsm_status = self._send_at_command("AT+CGREG?", 1)
|
||||
return lte_status, gsm_status
|
||||
|
||||
def signal_quality(self):
|
||||
try:
|
||||
response = self._send_at_command("AT+CSQ", 1)
|
||||
quality = int(response.split(":")[1].split(",")[0])
|
||||
# Conversion as per AT command set datasheet
|
||||
db = -113 + (2 * quality)
|
||||
return db
|
||||
except CellularError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def stop_ppp(self):
|
||||
self._ppp.disconnect()
|
||||
self._send_at_command(f"AT+IPR={DEFAULT_UART_STARTUP_BAUD}")
|
||||
self._flush_uart()
|
||||
|
||||
def start_ppp(self, baudrate=DEFAULT_UART_BAUD, connect=True):
|
||||
self._wait_ready(poll_time=1.0, timeout=30)
|
||||
|
||||
# Switch to a faster baudrate
|
||||
self._send_at_command(f"AT+IPR={baudrate}")
|
||||
self._flush_uart()
|
||||
self._uart.init(
|
||||
baudrate=baudrate,
|
||||
timeout=DEFAULT_UART_TIMEOUT,
|
||||
timeout_char=DEFAULT_UART_TIMEOUT_CHAR,
|
||||
rxbuf=DEFAULT_UART_RXBUF)
|
||||
self._wait_ready(poll_time=1.0)
|
||||
|
||||
# Connect!
|
||||
if connect:
|
||||
self.connect()
|
||||
|
||||
# Force PPP to use modem's default settings...
|
||||
self._flush_uart()
|
||||
self._uart.write("ATD*99#\r")
|
||||
self._uart.flush()
|
||||
|
||||
self._ppp = PPP(self._uart)
|
||||
self._ppp.connect()
|
||||
while self._ppp.status() != 4:
|
||||
time.sleep(1.0)
|
||||
|
||||
return self._ppp.ifconfig()
|
||||
|
||||
def connect(self, timeout=60):
|
||||
print(" - setting up cellular uart")
|
||||
# Connect to and flush the uart
|
||||
# Discard any unsolicited messages first, we don't need those
|
||||
self._flush_uart()
|
||||
|
||||
print(" - waiting for cellular module to be ready")
|
||||
|
||||
# Wait for the cellular module to respond to AT commands
|
||||
self._wait_ready()
|
||||
|
||||
self._send_at_command("ATE0") # Disable local echo
|
||||
self._send_at_command(f"AT+CGDCONT=1,\"IP\",\"{self._apn}\"") # Set apn and activate pdp context
|
||||
|
||||
# Wait for roaming lte connection to be established
|
||||
giveup = time.time() + timeout
|
||||
status = None
|
||||
while status != "+CEREG: 0,5" and status != "+CEREG: 0,1":
|
||||
status = self._send_at_command("AT+CEREG?", 1)
|
||||
time.sleep(0.25)
|
||||
if time.time() > giveup:
|
||||
raise CellularError("timed out getting network registration")
|
||||
|
||||
# Disable server and client certification validation
|
||||
self._send_at_command("AT+CSSLCFG=\"authmode\",0,0")
|
||||
self._send_at_command("AT+CSSLCFG=\"enableSNI\",0,1")
|
||||
|
||||
print(f" - SIM ICCID is {self.iccid()}")
|
||||
|
||||
def _wait_ready(self, poll_time=0.25, timeout=10):
|
||||
giveup = time.time() + timeout
|
||||
while time.time() <= giveup:
|
||||
try:
|
||||
self._send_at_command("AT")
|
||||
return # If __send_at_command doesn't throw an exception then we're good!
|
||||
except CellularError as e:
|
||||
print(e)
|
||||
time.sleep(poll_time)
|
||||
|
||||
raise CellularError("timed out waiting for AT response")
|
||||
|
||||
def _flush_uart(self):
|
||||
self._uart.flush()
|
||||
time.sleep(0.25)
|
||||
while self._uart.any():
|
||||
self._uart.read(self._uart.any())
|
||||
time.sleep(0.25)
|
||||
|
||||
def _send_at_command(self, command, result_lines=0, timeout=5.0):
|
||||
# Discard any unsolicited messages first, we don't need those
|
||||
self._flush_uart()
|
||||
|
||||
self._uart.write(command + "\r")
|
||||
self._uart.flush()
|
||||
status, data = self._read_result(result_lines, timeout=timeout)
|
||||
|
||||
print(" -", command, status, data)
|
||||
|
||||
if status == "TIMEOUT":
|
||||
raise CellularError(f"cellular module timed out for command {command}")
|
||||
|
||||
if status not in ["OK", "DOWNLOAD"]:
|
||||
raise CellularError(f"non 'OK' or 'DOWNLOAD' result for command {command}")
|
||||
|
||||
if result_lines == 1:
|
||||
return data[0]
|
||||
if result_lines > 1:
|
||||
return data
|
||||
return None
|
||||
|
||||
def _read_result(self, result_lines, timeout=1.0):
|
||||
status = None
|
||||
result = []
|
||||
start = time.ticks_ms()
|
||||
timeout *= 1000
|
||||
while len(result) < result_lines or status is None:
|
||||
if (time.ticks_ms() - start) > timeout:
|
||||
return "TIMEOUT", []
|
||||
|
||||
line = self._uart.readline()
|
||||
|
||||
if line:
|
||||
line = line.strip()
|
||||
if line in [b"OK", b"ERROR", b"DOWNLOAD"]:
|
||||
status = line.decode("ascii")
|
||||
elif line != b"":
|
||||
result.append(str(line, "ascii"))
|
||||
start = time.ticks_ms()
|
||||
|
||||
return status, result
|
Ładowanie…
Reference in New Issue