# Copyright 2025 PostalPortal LLC and Netsyms Technologies LLC
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that
# the following conditions are met:
#   1. Redistributions of source code must retain
#      the above copyright notice, this list of conditions
#      and the following disclaimer.
#   2. Redistributions in binary form must reproduce
#      the above copyright notice, this list of conditions
#      and the following disclaimer in the documentation
#      and/or other materials provided with the distribution.
#   3. Neither the name of the copyright holder
#       nor the names of its contributors may be used
#       to endorse or promote products derived from
#       this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
# CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
# WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.

#
# Some functions live here so they don't clutter up the main program file.
#

import sys

class DeltaError(ValueError):
    pass

def getUnitsAsByte(units):
    units = units.lower()
    if units == "mm":
        return 0x01
    elif units == "cm":
        return 0x02
    elif units == "in":
        return 0x03
    elif units == "ft":
        return 0x04
    else:
        return 0x00

def getUnitsFromByte(byte):
    if byte == 0x01:
        return "mm"
    elif byte == 0x02:
        return "cm"
    elif byte == 0x03:
        return "in"
    elif byte == 0x04:
        return "ft"
    else:
        return "mm"
    
def convertMMToUnits(mm, units="in"):
    units = units.lower()
    val = mm
    if units == "mm":
        val = mm
    elif units == "cm":
        val = mm / 10.0
    elif units == "in":
        val = mm / 25.4
    elif units == "ft":
        val = convertMMToUnits(mm, "in") / 12.0
    else:
        return 0
    return roundUnits(val, units)

# Round off the amount to a hardcoded precision suitable for the units used..
def roundUnits(x, units):
    units = units.lower()
    precision = 5
    if units == "mm":
        precision = 5
    elif units == "cm":
        precision = .5
    elif units == "in":
        precision = .25
    elif units == "ft":
        precision = .05
    return precision * round(x/precision)

#
#
# Serial communication
#
#

def printSerial(data, end = "\n"):
    print(data, end)
    
def readlineSerial():
    return sys.stdin.readline().strip()