# 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 = 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

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)
        sm.clear_txstall()
        while not sm.txstall:
            print(end=".")
            time.sleep(0.1)
        print()
        print("Message all sent to StateMachine (including emptying FIFO)")
        print()
