98 lines
3.1 KiB
Python
98 lines
3.1 KiB
Python
# SPDX-FileCopyrightText: 2022 Jeff Epler, written for Adafruit Industries
|
|
#
|
|
# SPDX-License-Identifier: MIT
|
|
|
|
"""Demonstrate background writing, including loop writing, with morse code.
|
|
|
|
On any rp2040 board with board.LED, this will alternately send 'SOS' and 'TEST'
|
|
via the LED, demonstrating that Python code continues to run while the morse
|
|
code data is transmitted. Alternately, change one line below to make it send
|
|
'TEST' forever in a loop, again while Python code continues to run.
|
|
|
|
The combination of "LED status" and duration is sent to the PIO as 16-bit number:
|
|
The top bit is 1 if the LED is turned on and 0 otherwise. The other 15 bits form a delay
|
|
value from 1 to 32767. A subset of the morse code 'alphabit' is created, with everthing
|
|
based on the 'DIT duration' of about 128ms (1MHz / 32 / 4000).
|
|
|
|
https://en.wikipedia.org/wiki/Morse_code
|
|
"""
|
|
|
|
import array
|
|
import time
|
|
from board import LED
|
|
from rp2pio import StateMachine
|
|
from adafruit_pioasm import Program
|
|
|
|
# This program turns the LED on or off depending on the first bit of the value,
|
|
# then delays a length of time given by the next 15 bits of the value.
|
|
# By correctly choosing the durations, a message in morse code can be sent.
|
|
pio_code = Program(
|
|
"""
|
|
out x, 1
|
|
mov pins, x
|
|
out x, 15
|
|
busy_wait:
|
|
jmp x--, busy_wait [31]
|
|
"""
|
|
)
|
|
|
|
|
|
# The top bit of the command is the LED value, on or off
|
|
LED_ON = 0x8000
|
|
LED_OFF = 0x0000
|
|
|
|
# The other 15 bits are a delay duration.
|
|
# It must be the case that 4 * DIT_DURATION < 32768
|
|
DIT_DURATION = 4000
|
|
DAH_DURATION = 3 * DIT_DURATION
|
|
|
|
# Build up some elements of morse code, based on the wikipedia article.
|
|
DIT = array.array("H", [LED_ON | DIT_DURATION, LED_OFF | DIT_DURATION])
|
|
DAH = array.array("H", [LED_ON | DAH_DURATION, LED_OFF | DIT_DURATION])
|
|
# That is, two more DAH-length gaps for a total of three
|
|
LETTER_SPACE = array.array("H", [LED_OFF | (2 * DAH_DURATION)])
|
|
# That is, four more DAH-length gaps (after a letter space) for a total of seven
|
|
WORD_SPACE = array.array("H", [LED_OFF | (4 * DIT_DURATION)])
|
|
|
|
# Letters and words can be created by concatenating ("+") the elements
|
|
E = DIT + LETTER_SPACE
|
|
O = DAH + DAH + DAH + LETTER_SPACE
|
|
S = DIT + DIT + DIT + LETTER_SPACE
|
|
T = DAH + LETTER_SPACE
|
|
SOS = S + O + S + WORD_SPACE
|
|
TEST = T + E + S + T + WORD_SPACE
|
|
|
|
sm = StateMachine(
|
|
pio_code.assembled,
|
|
frequency=1_000_000,
|
|
first_out_pin=LED,
|
|
pull_threshold=16,
|
|
auto_pull=True,
|
|
out_shift_right=False,
|
|
**pio_code.pio_kwargs,
|
|
)
|
|
|
|
# To simply repeat 'TEST' forever, change to 'if True':
|
|
if False: # pylint: disable=using-constant-test
|
|
print("Sending out TEST forever", end="")
|
|
sm.background_write(loop=TEST)
|
|
while True:
|
|
print(end=".")
|
|
time.sleep(0.1)
|
|
|
|
# But instead, let's alternate SOS and TEST, forever:
|
|
|
|
while True:
|
|
for plain, morse in (
|
|
("SOS", SOS),
|
|
("TEST", TEST),
|
|
):
|
|
print(f"Sending out {plain}", end="")
|
|
sm.background_write(morse)
|
|
sm.clear_txstall()
|
|
while not sm.txstall:
|
|
print(end=".")
|
|
time.sleep(0.1)
|
|
print()
|
|
print("Message all sent to StateMachine (including emptying FIFO)")
|
|
print()
|