Skip to content

add morse code background example #45

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 5, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions examples/pioasm_background_morse.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# 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 time
import array
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 = DAH + LETTER_SPACE
O = DAH + DAH + DAH + LETTER_SPACE
S = DIT + DIT + DIT + LETTER_SPACE
T = DIT + LETTER_SPACE
SOS = S + O + S + WORD_SPACE
TEST = T + E + S + T + WORD_SPACE

# 8 slots of the shortest possible led-off time
# A background write is 'complete' as soon as all data has been placed
# in the StateMachine's FIFO. This FIFO has either 4 or 8 entries.
# By adding 8 very short "led off" times, we can have our 'sm.writing' test
# tell us when the actual letter data has all been
FILLER = array.array("H", [LED_OFF | 1]) * 8

sm = StateMachine(
pio_code.assembled,
frequency=1_000_000,
first_out_pin=LED,
pull_threshold=16,
auto_pull=True,
out_shift_right=False,
)

# 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 + FILLER)
while sm.writing:
print(end=".")
time.sleep(0.1)
print()
print("Message all sent to StateMachine")
time.sleep(1)
print()