#!/bin/sh

setup_duplex() {
    local DEV=$1
    local FULL_DUPLEX=$2

    [ "$DEV" != "/dev/rs485" ] && return

    gpio_line=$(gpiofind "GPIO_RS485_RX_EN")

    gpioset $gpio_line=$FULL_DUPLEX
}

setup_serial() {
    local DEV=$1
    local BAUD=$2
    local PARITY=$3
    local DATABITS=$4
    local STOPBITS=$5
    local FULL_DUPLEX=$6
    local FLOWCTRL=$7

    case $PARITY in
        "none") PARITY_STR="-parenb" ;;
        "even") PARITY_STR="parenb -parodd" ;;
        "odd") PARITY_STR="parenb parodd" ;;
        "mark") PARITY_STR="parenb cmspar parodd" ;;
        "space") PARITY_STR="parenb cmspar -parodd" ;;
        *) echo "Invalid parity: $PARITY"; exit 1 ;;
    esac

    case $STOPBITS in
        "1") STOPBITS_STR="cstopb" ;;
        "2") STOPBITS_STR="-cstopb" ;;
        *) echo "Invalid stop bits: $STOPBITS"; exit 1 ;;
    esac

    case $FLOWCTRL in
        "none") FLOWCTRL_STR="-ixon -ixoff" ;;
        "rts/cts") FLOWCTRL_STR="crtscts" ;;
        "xon/xoff") FLOWCTRL_STR="ixon ixoff" ;;
        *) echo "Invalid flow control: $FLOWCTRL"; exit 1 ;;
    esac

    stty -F $DEV raw opost
    stty -F $DEV $BAUD $PARITY_STR cs$DATABITS $STOPBITS_STR $FLOWCTRL_STR

    setup_duplex $DEV $FULL_DUPLEX
}

format_time() {
    local FORMAT=$1

    if [ "${FORMAT:0:1}" = "R" ] || [ "${FORMAT:0:1}" = "I" ]; then
        echo "-$FORMAT"
    else
        echo "+$FORMAT"
    fi
}

SERIAL_DEV=$1
SERIAL_BAUD=$2
SERIAL_BITS=$3
SERIAL_PARITY=$4
SERIAL_STOP=$5
SERIAL_FULL_DUPLEX=$6
SERIAL_FLOWCTRL=$7
SEND_INTERVAL=$8
TIME_FORMAT=$9
TIME_UTC=${10}

if [ $# -ne 10 ]; then
    echo "Usage: $0 <serial_device> <baud_rate> <data_bits> <parity> <stop_bits> <full_duplex> <flowcontrol> <interval> <time_format> <utc>"
    exit 1
fi

TIME_FORMAT_FLAG=$(format_time "$TIME_FORMAT")

TIME_UTC_FLAG=""
[ "$TIME_UTC" == "1" ] && TIME_UTC_FLAG="-u"

setup_serial $SERIAL_DEV $SERIAL_BAUD $SERIAL_PARITY $SERIAL_BITS $SERIAL_STOP $SERIAL_FULL_DUPLEX $SERIAL_FLOWCTRL

while true; do
    echo "$(date $TIME_UTC_FLAG "$TIME_FORMAT_FLAG")" > $SERIAL_DEV &

    sleep $SEND_INTERVAL
done

