#!/bin/bash
################################################################################
# Copyright 2026 ModalAI Inc.
#
# 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.
#
# 4. The Software is used solely in conjunction with devices provided by
#    ModalAI Inc.
#
# 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.
################################################################################


# NEW SKU STYLE: MRB-D0012-4-V1-C28-M22-T7-X8
# family: MRB-D0012 Starling 2 Max
# compute board: 4 voxl2
# V1: hardware revision 1
# Camera config 28 (dual hires dual tracking)
# modem config 22 (m0141 with alfa wifi)
# transmitter config 7 (betafpv elrs)
# extras config 8 (lepton) (this is a bitmask)


source /home/root/.profile.d/modalai_sku_definitions.sh
CHIP=$(voxl-chip)
USER=$(whoami)

RESET_ALL="\e[0m"
RED="\e[91m"
YLW="\e[33m"
GRN="\e[32m"
SET_BOLD="\e[1m"

PRINT_ERROR (){
	echo -e "${RED}[ERROR] $@${RESET_ALL}"
}

PRINT_GREEEN_LINE (){
	echo -e "${GRN}${SET_BOLD}------------------------------------------------------------------${RESET_ALL}"
}

## These are the 5 main configuration states set by either a part number OR
## the production-specific arguments
_CONF_FAMILY=""
_CONF_BOARD=""
_CONF_CAM_NUM=""
_CONF_VERSION=""
_CONF_TX=""
_CONF_MODEM=""
_CONF_EXTRAS=""
_DEFAULT_CAM_NUM="" # suggestion given during wizard

## behavior modes
DRY_RUN=""
QUIET=""

print_usage () {
	clear -x
	PRINT_GREEEN_LINE
	echo -e "${GRN}${SET_BOLD}voxl-configure-sku${RESET_ALL}"
	echo -e ""
	echo -e "You provide this tool with a description of the product and it prints"
	echo -e "a formatted and validated SKU to stdout and to disk at "
	echo -e "$SKU_FILENAME for things like voxl-configure-mpa to read."
	echo -e ""
	echo -e "For human-interactive mode you likely want to use the wizard."
	echo -e ""
	echo -e "When running this in a script, you must at least provide the family"
	echo -e "name. All other args are optional. Things like camera configs and"
	echo -e "versions will be assumed to be default if not specified as an arg."
	echo -e ""
	echo -e "${GRN}${SET_BOLD}Arguments:${RESET_ALL}"
	echo -e "-b, --board     specify VOXL board code number or the name"
	echo -e "-c, --cam       specify the camera configuration"
	echo -e "-d, --dry-run   do everything except write sku to disk"
	echo -e "-f, --family    specify product family code number or name"
	echo -e "-h, --help      show this help text"
	echo -e "-m, --modem     set the modem number"
	echo -e "-q, --quiet     quiet mode, only write to disk"
	echo -e "-t, --tx        set transmitter number"
	echo -e "-v, --version   specify product version"
	echo -e "-w, --wizard    run the wizard"
	echo -e ""
	echo -e "${GRN}${SET_BOLD}Families (code - name)${RESET_ALL}"
	voxl-print-family-table
	echo -e ""
	echo -e "${GRN}${SET_BOLD}VOXL Compute Boards (code - name)${RESET_ALL}"
	voxl-print-board-table
	echo -e ""
	echo -e "${GRN}${SET_BOLD}Camera Configs${RESET_ALL}"
	print-camera-configs
	echo -e ""
	echo -e "${GRN}${SET_BOLD}Examples:${RESET_ALL}"
	echo -e "voxl-configure-sku --wizard"
	echo -e "voxl-configure-sku --family starling -v 2"
	echo -e "voxl-configure-sku -f sentinel -v 2"
	echo -e "voxl-configure-sku -f fpv"
	echo -e "voxl-configure-sku -f MRB-D0008"
	echo -e
	PRINT_GREEEN_LINE
	echo -e "Yes, that's a lot of arguments, mostly for scripted use."
	echo -e "For human-interactive mode you likely want to ${GRN}use the wizard:${RESET_ALL}"
	echo -e ""
	echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}voxl-configure-sku -w${RESET_ALL}"
	PRINT_GREEEN_LINE
	exit 0
}



## validate and "fix" the family name argument to a valid code
_validate_family(){
	## already a valid code, nothing to do
	if voxl-is-valid-family-code "$_CONF_FAMILY" ; then
		return
	fi

	## check if it's a valid family name instead
	if ! voxl-is-valid-family-name "$_CONF_FAMILY" ; then
		PRINT_ERROR "Invalid Family Name: $_CONF_FAMILY, exiting"
		exit 1
	fi

	## convert the family name to code
	_CONF_FAMILY=$(voxl-family-name-to-code "$_CONF_FAMILY")
}



## validate and "fix" the board argument to a number
_validate_board(){

	## already a valid code, nothing to do
	if voxl-is-valid-board-code $_CONF_BOARD ; then
		return
	fi

	## check if it's a valid family name instead
	if ! voxl-is-valid-board-name $_CONF_BOARD ; then
		PRINT_ERROR "Invalid board Name: $_CONF_BOARD, exiting"
		exit 1
	fi

	## convert the family name to code
	_CONF_BOARD=$(voxl-board-name-to-code $_CONF_BOARD)
}

_write_platform_name() {
	local platform_name="$1"

	if [[ -z "$platform_name" ]]; then
		echo "Error: No platform name provided."
		return 1
	fi

	echo "$platform_name" | sudo tee /usr/share/platform_name > /dev/null
}

_auto_select_board(){

	if ! type "voxl-platform" &> /dev/null; then
		echo "INFO: voxl-platform is not installed, assuming voxl2"
		_CONF_BOARD=4
		return
	fi


	b=$(voxl-platform)

	case "$b" in
		"M0052")
			_CONF_BOARD=3
			;;
		"M0054")
			_CONF_BOARD=4
			;;
		"M0104"|"M0204")
			_CONF_BOARD=6
			;;
		"M0205")
			_CONF_BOARD=7
			;;
		"M0197")
			_CONF_BOARD=9
			;;
		*)
			## unknown, assume voxl2
			_CONF_BOARD=4
			;;
		esac
}


## TODO auto-generate this from sku-definitions
_suggest_default_cam_for_family(){

	# limited set of cam options for M0197
	if [ $CHIP == "QCS6490" ]; then
		echo -e "${SET_BOLD}Camera configs for M0197 are:${RESET_ALL}"
		echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}53 - m0197 imx664 hires + ar0144 tracking (default)${RESET_ALL}"
		echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}54 - m0197 imx664 hires + ar0144 tracking + boson (option)${RESET_ALL}"
		_DEFAULT_CAM_NUM="53"
		return;
	fi


	case "$_CONF_FAMILY" in

		"MDK-F0001"|"MDK-F0002"|"MRB-D0001")
			echo -e "${SET_BOLD}The default camera config for M500 and Flight Deck is${RESET_ALL}"
			echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}3 (hires+stereo+tracking)${RESET_ALL}"
			_DEFAULT_CAM_NUM="3"
			;;

		"MCM-C0001"|"MRB-D0003")
			echo -e "${SET_BOLD}The default camera config for VOXLCAM and Seeker is${RESET_ALL}"
			echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}7 (TOF+stereo+tracking)${RESET_ALL}"
			echo -e "${SET_BOLD}with an optional version that has an IMX214 Hires cam:${RESET_ALL}"
			echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}3  Hires + Stereo + Tracking${RESET_ALL}"
			_DEFAULT_CAM_NUM="7"
			;;

		"MRB-D0004"|"MRB-D0006"|"MDK-F0006")
			echo -e "${SET_BOLD}The default camera config for RB5-Flight and Sentinel is${RESET_ALL}"
			echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}11 (hires+tracking+dual_stereo)${RESET_ALL}"
			_DEFAULT_CAM_NUM="11"
			;;

		"MRB-D0005")
			echo -e "${SET_BOLD}The default camera config for Starling is${RESET_ALL}"
			echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}6 (hires+TOF+tracking)${RESET_ALL}"
			_DEFAULT_CAM_NUM="6"
			;;

		"MRB-D0008")
			if [ $_CONF_VERSION == "4" ]; then
				echo -e "${SET_BOLD}The default camera configs for Seeker V4 and older are${RESET_ALL}"
				echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}15 (dual_9782_tracking)${RESET_ALL}"
				echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}32 (dual_9782_tracking plus forward 9782)${RESET_ALL}"
				_DEFAULT_CAM_NUM="15"
			else
				echo -e "${SET_BOLD}Camera configs for Seeker 5 are${RESET_ALL}"
				echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}C46 (dual AR0144 tracking plus IMX664) (default)${RESET_ALL}"
				echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}C47 (dual AR0144 tracking plus IMX664 + Boson) (option)${RESET_ALL}"
				_DEFAULT_CAM_NUM="46"
			fi
			;;

		"MRB-D0010")
			echo -e "${SET_BOLD}The default camera config for D0010 is${RESET_ALL}"
			echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}17 (hires+TOF+tracking+stereo)${RESET_ALL}"
			_DEFAULT_CAM_NUM="17"
			;;

		"MRB-D0011")
			echo -e "${SET_BOLD}The default camera config for the PX4 Autonomy Dev Kit is${RESET_ALL}"
			echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}20 (imx412 hires, ar0144 tracking)${RESET_ALL}"
			_DEFAULT_CAM_NUM="20"
			;;

		"MRB-D0012")
			echo -e "${SET_BOLD}The camera configs for Starling 2 Max are${RESET_ALL}"
			echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}28 (dual imx412 hires, dual ar0144 tracking) (default)${RESET_ALL}"
			echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}29 (dual imx412 hires, dual ar0144 tracking, PMD TOF) (option)${RESET_ALL}"
			_DEFAULT_CAM_NUM="28"
			;;

		"MRB-D0013")
			if [ "$_CONF_VERSION" == "1" ]; then
				echo -e "${SET_BOLD}The default camera config for D0013 is${RESET_ALL}"
				echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}33 (IMX664 + Dual AR0144 tracking)${RESET_ALL}"
				_DEFAULT_CAM_NUM="33"
			else
				echo -e "${SET_BOLD}Camera configs for D0013 Stinger are${RESET_ALL}"
				echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}34 (IMX664 + Dual AR0144 tracking + Boson) (option)${RESET_ALL}"
				echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}35 (IMX664 + Dual AR0144 tracking) (default)${RESET_ALL}"
				_DEFAULT_CAM_NUM="35"
			fi
			;;

		"MRB-D0014")
			echo -e "${SET_BOLD}Camera configs for Starling 2 are${RESET_ALL}"
			echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}26 (imx412 hires, dual ar0144 tracking) (default)${RESET_ALL}"
			echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}27 (imx412 hires, triple ar0144 tracking) (option)${RESET_ALL}"
			_DEFAULT_CAM_NUM="26"
			;;

		"MRB-D0016")
			echo -e "${SET_BOLD}The default camera configs for Sparrow is${RESET_ALL}"
			echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}38 (imx664 hires, triple ar0144 tracking)${RESET_ALL}"
			_DEFAULT_CAM_NUM="38"
			;;

		"MRB-D0017")
			echo -e "${SET_BOLD}The default camera config for D0017 is${RESET_ALL}"
			echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}50 (imx664 hires)${RESET_ALL}"
			_DEFAULT_CAM_NUM="50"
			;;
		
		"MRB-D0019")
			echo -e "${SET_BOLD}Camera configs for Seeker 7 are${RESET_ALL}"
			echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}C46 (dual AR0144 tracking plus IMX664) (default)${RESET_ALL}"
			echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}C47 (dual AR0144 tracking plus IMX664 + Boson) (option)${RESET_ALL}"
			_DEFAULT_CAM_NUM="46"
			
			;;
		
		"MRB-D0020")
			if [ "$_CONF_VERSION" == "6" ]; then
				echo -e "${SET_BOLD}Camera configs for Seeker 10 V6 are${RESET_ALL}"
				echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}C46 (dual AR0144 tracking plus IMX664) (default)${RESET_ALL}"
				echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}C47 (dual AR0144 tracking plus IMX664 + Boson) (option)${RESET_ALL}"
				echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}C60 (IMX664 Hires Only) (option)${RESET_ALL}"
			else
				echo -e "${SET_BOLD}Camera configs for Seeker 10 are${RESET_ALL}"
				echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}C46 (dual AR0144 tracking plus IMX664) (default)${RESET_ALL}"
				echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}C47 (dual AR0144 tracking plus IMX664 + Boson) (option)${RESET_ALL}"
			fi
			_DEFAULT_CAM_NUM="46"
			
			;;

		"MVX-T0001")
			echo -e "${SET_BOLD}The default camera config for MVX-T0001 is${RESET_ALL}"
			echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}50 (imx664 hires)${RESET_ALL}"
			_DEFAULT_CAM_NUM="50"
			;;

		"MVX-T0002")
			echo -e "${SET_BOLD}The default camera config for MVX-T0002 is${RESET_ALL}"
			echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}50 (imx664 hires)${RESET_ALL}"
			_DEFAULT_CAM_NUM="50"
			;;


		esac
}


_construct_sku_number_from_conf(){

	############################################################################
	## go through each name and populate the other _CONF_XYZ variables with
	## appropriate defaults if they are missing. Also do sanity and error checks
	############################################################################
	case "$_CONF_FAMILY" in

		"MDK-F0001") # Flight Deck with voxl+fc or voxl-flight
			if [ "$_CONF_BOARD" == "" ]; then
				_CONF_BOARD="2"	# default to voxl-flight all-in-one board
			fi
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="3"	# default hires+stereo+tracking
			fi
			;;


		"MDK-F0002") # VOXL Deck with NO Flight Core!
			if [ "$_CONF_BOARD" == "" ]; then
				_CONF_BOARD="1"	# default blue voxl board
			fi
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="3"	# default hires+stereo+tracking
			fi
			;;


		"MRB-D0001") # M500

			if [ "$_CONF_BOARD" == "" ]; then
				PRINT_ERROR "for MRB-D0001 (M500), you must specify a board"
				PRINT_ERROR "-b 1 for VOXL1 with Flight Core"
				PRINT_ERROR "-b 2 for VOXL1 Flight all-in-one board"
				return 1
			fi
			if [[ ! "$_CONF_BOARD" == "1" ]] && [[ ! "$_CONF_BOARD" == "2" ]]; then
				PRINT_ERROR "invalid MRB-D0001 M500 board: $_CONF_BOARD"
				PRINT_ERROR "must be 1 or 2"
				return 1
			fi
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="3"	# default hires+stereo+tracking
			fi

			_write_platform_name "m500 (D0001)"
			;;


		"MCM-C0001") # voxlcam
			if [ "$_CONF_BOARD" == "" ]; then
				_CONF_BOARD="1"	# default blue voxl board
			fi
			if [[ ! "$_CONF_BOARD" == "1" ]]; then
				PRINT_ERROR "invalid MCM-C0001 (VOXLCAM) board: $_CONF_BOARD"
				PRINT_ERROR "must be 1 (blue VOXL1)"
				return 1
			fi
			if [ "$_CONF_VERSION" == "" ]; then
				_CONF_VERSION="2"	# default version 2
			fi
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="7"	# default tof+stereo+tracking
			fi

			_write_platform_name "voxl-cam (C0001)"
			;;


		"MRB-D0003") # Seeker V1
			if [ "$_CONF_BOARD" == "" ]; then
				_CONF_BOARD="1"	# default blue voxl board
			fi
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="7"	# default tof+stereo+tracking
			fi

			_write_platform_name "seeker-v1 (D0003)"
			;;


		"MRB-D0004") # Qualcomm rb5 flight 5g development drone
			if [ "$_CONF_BOARD" == "" ]; then
				_CONF_BOARD="3"	# m0052 rb5 flight
			fi
			if [[ ! "$_CONF_BOARD" == "3" ]]; then
				PRINT_ERROR "invalid MRB-D0004 (RB5 Flight) board: $_CONF_BOARD"
				PRINT_ERROR "must be 3 (RB5)"
				return 1
			fi
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="11"	# default 6-cam setup
			fi

			_write_platform_name "rb5-flight (D0004)"
			;;


		"MRB-D0005") # starling V2
			if [ "$_CONF_BOARD" == "" ];
				then _CONF_BOARD="4"
			fi
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="6"	# default tof+tracking+hires
			fi

			_write_platform_name "starling (D0005)"
			;;


		"MRB-D0006"|"MDK-F0006") # Sentinel and flight deck with voxl2
			if [ "$_CONF_BOARD" == "" ];
				then _CONF_BOARD="4"
			fi
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="11"	# default 6-cam setup
			fi

			_write_platform_name "sentinel (D0006)"
			;;


		"MRB-D0008") # FPV
			if [ "$_CONF_BOARD" == "" ];
				then _CONF_BOARD="4"
			fi
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="15"	# Stereo(OV9782) as separate mono cams
			fi

			_write_platform_name "seeker (D0008)"
			;;


		"MRB-D0010") # starling V2 with stereo 9782
			if [ "$_CONF_BOARD" == "" ];
				then _CONF_BOARD="4"
			fi
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="17"	# default tof+tracking+hires+stereo
			fi

			_write_platform_name "starling2 (D0010)"
			;;


		"MRB-D0011") # starling PX4 Autonomy Development Kit
			if [ "$_CONF_BOARD" == "" ];
				then _CONF_BOARD="4"
			fi
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="20"	# IMX412+AR0144 special config for D0011
			fi

			_write_platform_name "starling-px4-dev-kit (D0011)"
			;;

		"MRB-D0012") # Starling 2 Max
			if [ "$_CONF_BOARD" == "" ];
				then _CONF_BOARD="4"
			fi
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="28"
			fi

			_write_platform_name "starling2-max (D0012)"
			;;


		"MRB-D0013") # Stinger
			if [ "$_CONF_BOARD" == "" ];
				then _CONF_BOARD="6"
			fi
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="22"	# IMX412+AR0144 special config for D0013
			fi

			_write_platform_name "stinger (D0013)"
			;;

		"MRB-D0014") # Starling 2
			if [ "$_CONF_BOARD" == "" ];
				then _CONF_BOARD="4"
			fi
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="27" #default to the full option
			fi

			_write_platform_name "starling2 (D0014)"
			;;


		"MRB-D0015") # D0015
			if [ "$_CONF_BOARD" == "" ];
				then _CONF_BOARD="4"
			fi
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="20"	# IMX412+AR0144 special config for D0015
			fi

			_write_platform_name "fixed-wing (D0015)"
			;;

		"MRB-D0016") # sparrow
			if [ "$_CONF_BOARD" == "" ];
				then _CONF_BOARD="6"
			fi
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="38"
			fi
			if [ "$_CONF_TX" == "" ]; then
				_CONF_TX="38"
			fi


			_write_platform_name "sparrow (D0016)"
			;;

		"MRB-D0017") # Shikra
			if [ "$_CONF_BOARD" == "" ];
				then _CONF_BOARD="6"
			fi
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="50"	# IMX664
			fi

			if [ "$_CONF_VERSION" == "" ]; then
			_CONF_VERSION="2"		# default version 2
			fi

			_write_platform_name "shikra (D0017)"
			;;

		"MRB-D0019") # Seeker 7
			if [ "$_CONF_BOARD" == "" ];
				then _CONF_BOARD="4"
			fi
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="46"	# dual ar0444 tracking + imx664
			fi
			if [ "$_CONF_VERSION" == "" ]; then
			_CONF_VERSION="5"		# default version 5
			fi

			_write_platform_name "seeker-7 (D0019)"
			;;

		"MRB-D0020") # Seeker 10
			if [ "$_CONF_BOARD" == "" ];
				then _CONF_BOARD="4"
			fi
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="46"	# dual ar0444 tracking + imx664
			fi
			if [ "$_CONF_VERSION" == "" ]; then
			_CONF_VERSION="5"		# default version 5
			fi

			_write_platform_name "seeker-10 (D0020)"
			;;


		"TF-M0054") # voxl2 test fixture
			if [ "$_CONF_BOARD" == "" ];
				then _CONF_BOARD="4"
			fi
			_CONF_VERSION="1"
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="11" # hires, tracking, stereo_front, stereo_rear
			fi

			_write_platform_name "voxl2-test-fixture (TF-M0054)"
			;;

		"TF-M0104") # voxl2-mini test fixture
			if [ "$_CONF_BOARD" == "" ];
				then _CONF_BOARD="6"
			fi
			_CONF_VERSION="1"
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="6" # hires, tof, tracking
			fi

			_write_platform_name "voxl2-mini-test-fixture (TF-M0104)"
			;;

		"MCCA-M0054") # voxl2 board only
			if [ "$_CONF_BOARD" == "" ]; then
				_CONF_BOARD="4"
			fi
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="0"
			fi

			_write_platform_name "voxl2 (M0054)"
			;;

		"MCCA-M0104") # voxl2-mini board only
			if [ "$_CONF_BOARD" == "" ];
				then _CONF_BOARD="6"
			fi
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="0"
			fi

			_write_platform_name "voxl2-mini (M0104)"
			;;

		"MVX-T0001") # vtx
			if [ "$_CONF_BOARD" == "" ];
				then _CONF_BOARD="6"
			fi
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="50"
			fi
			_CONF_VERSION="0"

			_write_platform_name "voxl2-mini-vtx (MVX-T0001)"
			;;
		
		"MVX-R0001") # vrx
			_CONF_BOARD=7
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="0"
			fi
			_CONF_VERSION="0"

			_write_platform_name "voxl2-mini-vrx (MVX-R0001)"
			;;

		"MVX-T0002") # vtx gen 2
			if [ "$_CONF_BOARD" == "" ];
				then _CONF_BOARD="9"
			fi
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="50"
			fi
			_CONF_VERSION="0"
			_CONF_MODEM="26" #m0185 vtx

			_write_platform_name "vtx-gen2 (MVX-T0002)"
			;;

		"MVX-R0002") # vrx gen 2
			if [ "$_CONF_BOARD" == "" ];
				then _CONF_BOARD="9"
			fi
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="0"
			fi
			_CONF_VERSION="0"
			_CONF_MODEM="37" #m0198

			_write_platform_name "vrx-gen2 (MVX-R0002)"
			;;

		"MVX-H0001") # vrx hub
			if [ "$_CONF_BOARD" == "" ];
				then _CONF_BOARD="7"
			fi
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="0"
			fi
			_CONF_VERSION="0"

			_write_platform_name "vrx-hub (MVX-H0001)"
			;;
		
		"MVX-S0001") # vrx spire
			if [ "$_CONF_BOARD" == "" ];
				then _CONF_BOARD="7"
			fi
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="0"
			fi
			_CONF_VERSION="0"

			_write_platform_name "vrx-spire (MVX-S0001)"
			;;

		*)
			PRINT_ERROR "Invalid Family Code: ${_CONF_FAMILY}, valid family codes are:"
			voxl-print-family-table
			return 1
			;;
	esac


	if [ "$_CONF_VERSION" == "" ]; then
		_CONF_VERSION="1"		# default version 1
	fi


	## now make the SKU string
	if [[ "$_CONF_FAMILY" != *"MCCA"* ]]; then
		_CONF_SKU="${_CONF_FAMILY}-${_CONF_BOARD}"
		_CONF_SKU+="-V$_CONF_VERSION"
	else
		_CONF_SKU="${_CONF_FAMILY}"
	fi
	
	if [ "$_CONF_CAM_NUM" != "" ]; then
		if [ "$_CONF_CAM_NUM" == "custom" ]; then
			_CONF_CAM_NUM="C"
		fi
		_CONF_SKU+="-C$_CONF_CAM_NUM"
	fi

	if [ "$_CONF_TX" != "" ]; then
		_CONF_SKU+="-T$_CONF_TX"
	fi

	if [ "$_CONF_MODEM" != "" ]; then
		_CONF_SKU+="-M$_CONF_MODEM"
	fi

	if [ "$_CONF_EXTRAS" != "" ]; then
		_CONF_SKU+="-X$_CONF_EXTRAS"
	fi
}





_wizard(){

	clear -x
	PRINT_GREEEN_LINE
	echo -e "            ${GRN}${SET_BOLD}Welcome to the voxl-configure-sku Wizard!${RESET_ALL}"
	echo -e ""

	## start with some optional things zeroed out
	_CONF_EXTRAS=0
	_CONF_MODEM=0
	_CONF_TX=0


	## do a quick parse, this will migrate old filename to new in case
	if [ -f $SKU_FILENAME ]; then

		if voxl-inspect-sku --quiet; then
			echo "VOXL currently thinks it is in the following hardware:"
			voxl-inspect-sku
			echo "If this is what you want, select 1 (accept and continue) to"
			echo "leave it as-is. Otherwise, select the desired product family:"
			echo ""
		else
			echo ""
			echo "There was an issue parsing the currently saved SKU"
			echo "Please select a family to start making a new one:"
			echo ""
		fi
	else
		echo "VOXL is not yet configured for a particular SKU."
		echo "Please select the new desired product family:"
		echo ""
	fi


	##
	## Ask for the family
	##
	select _CONF_FAMILY in "accept and continue" "${VOXL_FAMILY_NAMES[@]}" "quit"; do
		case $_CONF_FAMILY in
		"accept and continue")
			echo "leaving SKU as-is"
			exit 0
			;;
		"quit")
			echo "quitting"
			exit 0
			;;
		*)
			if ! voxl-is-valid-family-name "$_CONF_FAMILY" ; then
				echo "Invalid selection, try again"
			else
				echo "selected $_CONF_FAMILY"
				break
			fi
		esac
	done
	_validate_family



	##
	## Ask board name for old voxl1 products
	##
	if [ "$_CONF_FAMILY" == "MRB-D0001" ] || [ "$_CONF_FAMILY" == "MDK-F0001" ] || [ "$_CONF_FAMILY" == "MDK-F0002" ]; then
		PRINT_GREEEN_LINE
		echo ""
		echo "for M500 and flight deck, you must specify which board you are using"

		select _CONF_BOARD in "${VOXL_BOARD_NAMES[@]}" "quit"; do
			case $_CONF_BOARD in
			"quit")
				echo "quitting"
				exit 0
				;;
			*)
				if ! voxl-is-valid-board-name $_CONF_BOARD ; then
					echo "Invalid selection, try again"
				else
					echo "selected $_CONF_BOARD"
					break
				fi
			esac
		done
	elif [ $_CONF_FAMILY == "MCM-C0001" ] || [ $_CONF_FAMILY == "MRB-D0003" ]; then
		## voxlcams are all voxl1 boards
		_CONF_BOARD="1"
	else
		## for voxl2 nd newer, just auto detect this instead of asking the question
		_auto_select_board
	fi
	_validate_board


	##
	## Sentinel has 2 hardware revision, ask which one
	##
	if [ "$_CONF_FAMILY" == "MRB-D0006" ] || [ "$_CONF_FAMILY" == "MDK-F0006" ]; then
		PRINT_GREEEN_LINE
		echo ""
		echo "MRB-D0006 Sentinel, and MDK-F0006 Flight Deck have two versions."
		echo "Version 1 with Round Holybro GPS and Spektrum Receiver (pre Oct 2023)"
		echo "Version 2 with Square MRO GPS and ELRS Receiver (Oct 2023 onward)"
		echo -e "\nIf none of these describe your hardware perfectly, don't worry, you will get"
		echo "	a chance to select a custom receiver later."
		echo "Please select the appropriate one."
		echo ""

		select i in "1" "2" "quit"; do
			case $i in
			"1")
				_CONF_VERSION="1"
				break
				;;
			"2")
				_CONF_VERSION="2"
				break
				;;
			"quit")
				echo "quitting"
				exit 0
				;;
			*)
				echo "Invalid selection, try again"
			esac
		done
	fi


	##
	## Ask for Starling version
	##
	if [ "$_CONF_FAMILY" == "MRB-D0005" ]; then
		PRINT_GREEEN_LINE
		echo ""
		echo "MRB-D0005 Starling currently has two versions in circulation."
		echo "Version 2 with silver motors (pre December 2023)"
		echo "Version 3 with black motors  (December 2023 onward)"
		echo "Please select the appropriate one."
		echo ""

		select i in "quit" "2" "3"; do
			case $i in
			"2")
				_CONF_VERSION="2"
				break
				;;
			"3")
				_CONF_VERSION="3"
				break
				;;
			"quit")
				echo "quitting"
				exit 0
				;;
			*)
				echo "Invalid selection, try again"
			esac
		done
	fi

	##
	## Ask for Seeker 5 version
	##
	if [ "$_CONF_FAMILY" == "MRB-D0008" ]; then
		PRINT_GREEEN_LINE
		echo ""
		echo "MRB-D0008 Seeker 5 currently has three versions in circulation."
		echo "Version 4 with small OV9782 tracking cameras"
		echo "Version 5 with larger AR0144 tracking cameras"
		echo "Version 6 (in prototype)"
		echo "Please select the appropriate one."
		echo ""

		while true; do
			read -r -p "Enter version (4, 5, or 6, q to quit): " i
			case $i in
			4)
				_CONF_VERSION="4"
				break
				;;
			5)
				_CONF_VERSION="5"
				break
				;;
			6)
				_CONF_VERSION="6"
				break
				;;
			q|quit)
				echo "quitting"
				exit 0
				;;
			*)
				echo "Invalid selection, try again"
				;;
			esac
		done
	fi

	##
	## Ask for Seeker 10 version
	##
	if [ "$_CONF_FAMILY" == "MRB-D0020" ]; then
		PRINT_GREEEN_LINE
		echo ""
		echo "MRB-D0020 Seeker 10 currently has two versions"
		echo "Version 5 2025 model"
		echo "Version 6 2026 model with GPS on big tower up front"
		echo "Please select the appropriate one."
		echo ""

		while true; do
			read -r -p "Enter version (5 or 6, q to quit): " i
			case $i in
			5)
				_CONF_VERSION="5"
				break
				;;
			6)
				_CONF_VERSION="6"
				break
				;;
			q|quit)
				echo "quitting"
				exit 0
				;;
			*)
				echo "Invalid selection, try again"
				;;
			esac
		done
	fi


	##
	## Ask for Starling 2 Max version
	##
	if [ "$_CONF_FAMILY" == "MRB-D0012" ]; then
		PRINT_GREEEN_LINE
		echo ""
		echo "MRB-D0012 Starling 2 Max currently has three versions in circulation."
		echo "Version 1 with 4mm frame and GPS on top, 2203.5 motors (pre Septemper 2024)"
		echo "Version 2 with 5mm frame and GPS at the back, 2203.5 motors (Sept 2024 - Feb 2026)"
		echo "Version 3 with 5mm frame and ModalAI-branded 2204 motors (Feb 2026 onward)"
		echo "Please select the appropriate one."
		echo ""

		while true; do
			read -r -p "Enter version (1, 2 or 3, q to quit): " i
			case $i in
			1)
				_CONF_VERSION="1"
				break
				;;
			2)
				_CONF_VERSION="2"
				break
				;;
			3)
				_CONF_VERSION="3"
				break
				;;
			q|quit)
				echo "quitting"
				exit 0
				;;
			*)
				echo "Invalid selection, try again"
				;;
			esac
		done
	fi

	##
	## Ask for Stinger version
	##
	if [ "$_CONF_FAMILY" == "MRB-D0013" ]; then
		if [ $CHIP == "QCS6490" ]; then
			_CONF_VERSION=3
		else
			PRINT_GREEEN_LINE
			echo ""
			echo "MRB-D0013 Stinger currently has two versions in circulation."
			echo "Version 1 with LED pills mounted on top of top frame / \ (pre November 2025)"
			echo "Version 2 with LED pills mounted in between top and bottom frame | | (November 2025 onward)"
			echo "Please select the appropriate one."
			echo ""

			while true; do
				read -r -p "Enter version (1 or 2, q to quit): " i
				case $i in
				1)
					_CONF_VERSION="1"
					break
					;;
				2)
					_CONF_VERSION="2"
					break
					;;
				q|quit)
					echo "quitting"
					exit 0
					;;
				*)
					echo "Invalid selection, try again"
					;;
				esac
			done
		fi
	fi

	if [ "$_CONF_FAMILY" != "MVX-R0001" ] && [ "$_CONF_FAMILY" != "MVX-R0002" ] && [ "$_CONF_FAMILY" != "MVX-S0001" ] && [ "$_CONF_FAMILY" != "MVX-H0001" ]; then
		## platforms with only one cam config option
		CAM_VALID=""

		if [ ! $CAM_VALID ]; then
			##
			## ask for the camera config
			##
			PRINT_GREEEN_LINE
			echo -e ""
			echo -e "If you would like to select a special camera config that differs"
			echo -e "from the default for your product family, please select an option."
			echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}Simply hit ENTER to use the default${RESET_ALL}"
			echo -e ""
			print-camera-configs
			echo -e " C - use user-defined custom camera config in"
			echo -e "     (/data/modalai/custom_camera_config.txt)"
			echo -e " q - Quit The Wizard"
			echo -e ""
			_suggest_default_cam_for_family
			echo -e ""
			echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}Simply hit ENTER to use the default${RESET_ALL}"
		fi


		# read and validate camera config if there was an option
		while [ ! $CAM_VALID ]; do

			echo ""
			read -p "selection: " _CONF_CAM_NUM

			if [[ $_CONF_CAM_NUM == "c" ]] || [[ $_CONF_CAM_NUM == "C" ]] || [[ $_CONF_CAM_NUM == "custom" ]]; then
				echo "Selecting custom camera config"
				_CONF_CAM_NUM="C"
				CAM_VALID="true"
			elif [[ $_CONF_CAM_NUM =~ ^[0-9]+$ ]]; then
				echo "Selected numerical camera config"
				CAM_VALID="true"
			elif [[ $_CONF_CAM_NUM == "q" ]] || [[ $_CONF_CAM_NUM == "Q" ]]; then
				echo "quitting"
				exit 0;
			elif [[ $_CONF_CAM_NUM == "" ]]; then
				echo "Selecting default camera config $_DEFAULT_CAM_NUM"
				# select whatever the wizard menu suggested as a default, if no default
				# was provided for that family then it will be left blank or set up by
				# the sku string builder later
				if [ ! $_DEFAULT_CAM_NUM == "" ]; then
					_CONF_CAM_NUM=$_DEFAULT_CAM_NUM
				fi
				CAM_VALID="true"
			else
				echo "invalid entry, please try again"
			fi
		done

	fi

	##
	## Ask for transmitter version (voxl2, voxl2-mini drones only)
	##
	if  [ "$_CONF_FAMILY" == "MRB-D0005" ] ||
		[ "$_CONF_FAMILY" == "MRB-D0006" ] ||
		[ "$_CONF_FAMILY" == "MRB-D0008" ] ||
		[ "$_CONF_FAMILY" == "MRB-D0011" ] ||
		[ "$_CONF_FAMILY" == "MRB-D0012" ] ||
		[ "$_CONF_FAMILY" == "MRB-D0013" ] ||
		[ "$_CONF_FAMILY" == "MRB-D0014" ] ||
		[ "$_CONF_FAMILY" == "MRB-D0016" ] ||
		[ "$_CONF_FAMILY" == "MRB-D0017" ] ||
		[ "$_CONF_FAMILY" == "MRB-D0019" ] ||
		[ "$_CONF_FAMILY" == "MRB-D0020" ] ||
		[ "$_CONF_FAMILY" == "MVX-S0001" ]; then
		PRINT_GREEEN_LINE
		echo ""
		echo "Several RC receiver options."
		echo "Please select the appropriate one."
		echo ""

		while true; do
			echo -e "Select a numeric option:"
			echo -e "0)  none"
			echo -e "1)  Spektrum"
			echo -e "6)  TBS Crossfire"
			echo -e "7)  ELRS Beta FPV"
			echo -e "${GRN}8)  ELRS (ModalAI M0184) (DEFAULT)${RESET_ALL}"
			echo -e "9)  Ghost"
			echo -e "10) ELRS (ModalAI M0193)"
			read -p "#? " choice

			case $choice in
				0)
					_CONF_TX="0"
					break
					;;
				1)
					_CONF_TX="1"
					break
					;;
				6)
					_CONF_TX="6"
					break
					;;
				7)
					_CONF_TX="7"
					break
					;;
				8)
					_CONF_TX="8"
					break
					;;
				9)
					_CONF_TX="9"
					break
					;;
				10)
					_CONF_TX="10"
					break
					;;
				*)
					echo "Invalid selection, try again."
					;;
			esac
		done
	fi



	##
	## Ask for lepton (starling 2 drones only)
	##
	if  [ "$_CONF_FAMILY" == "MRB-D0012" ] ||
		[ "$_CONF_FAMILY" == "MRB-D0014" ]; then
		PRINT_GREEEN_LINE
		echo ""
		echo "For Starling 2 and Starling 2 Max drones, there is an optional lepton sensor."
		echo "Is a lepton sensor installed on your drone? (-X8)."
		echo ""

		select i in "yes" "no"; do
			case $i in
			"yes")
				_CONF_EXTRAS="8"
				break
				;;
			"no")
				break
				;;
			*)
				echo "Invalid selection, try again"
			esac
		done
	fi

	## only ask modem question for sentinel, fpv, and starling Max
	## todo maybe restrict these options to only offered configs
	if  [ "$_CONF_FAMILY" == "MRB-D0006" ] ||
		[ "$_CONF_FAMILY" == "MRB-D0008" ] ||
		[ "$_CONF_FAMILY" == "MRB-D0011" ] ||
		[ "$_CONF_FAMILY" == "MRB-D0012" ] ||
		[ "$_CONF_FAMILY" == "MRB-D0013" ] ||
		[ "$_CONF_FAMILY" == "MRB-D0014" ] ||
		[ "$_CONF_FAMILY" == "MRB-D0017" ] ||
		[ "$_CONF_FAMILY" == "MRB-D0016" ] ||
		[ "$_CONF_FAMILY" == "MRB-D0019" ] ||
		[ "$_CONF_FAMILY" == "MRB-D0020" ] ||
		[ "$_CONF_FAMILY" == "MVX-T0001" ] ||
		[ "$_CONF_FAMILY" == "MVX-R0001" ] ||
		[ "$_CONF_FAMILY" == "MVX-H0001" ] ||
		[ "$_CONF_FAMILY" == "MVX-S0001" ]; then
		
		##
		## ask for the modem config
		##
		PRINT_GREEEN_LINE
		echo -e ""
		echo -e "Select the modem hardware."
		echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}Simply hit ENTER if none${RESET_ALL}"
		echo -e ""
		print-modem-options
		echo -e ""
		echo -e " q - Quit The Wizard"

		echo -e ""
		echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}Simply hit ENTER if none${RESET_ALL}"


		# read and validate modem config
		MODEM_VALID=""
		while [ ! $MODEM_VALID ]; do

			echo ""
			read -p "selection: " _CONF_MODEM

			if [[ $_CONF_MODEM =~ ^[0-9]+$ ]]; then
				echo "Selected numerical modem config"
				MODEM_VALID="true"
			elif [[ $_CONF_MODEM == "q" ]] || [[ $_CONF_MODEM == "Q" ]]; then
				echo "quitting"
				exit 0;
			elif [[ $_CONF_MODEM == "" ]]; then
				echo "Selecting default modem config"
				MODEM_VALID="true"
				_CONF_MODEM=0
			else
				echo "invalid entry, please try again"
			fi
		done
	fi

	## only ask extras question for fpv and stinger
	## todo maybe restrict these options to only offered configs
	if  [ "$_CONF_FAMILY" == "MRB-D0008" ] ||
		[ "$_CONF_FAMILY" == "MRB-D0019" ] ||
		[ "$_CONF_FAMILY" == "MRB-D0013" ] ||
		[ "$_CONF_FAMILY" == "MRB-D0020" ]; then
		##
		## ask for the extras config
		##
		PRINT_GREEEN_LINE
		echo -e ""
		echo -e "Select any extra hardware."
		echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}Simply hit ENTER if none${RESET_ALL}"
		echo -e ""
		print-extras-options
		echo -e ""
		echo -e " q - Quit The Wizard"

		echo -e ""
		echo -e "${GRN}${SET_BOLD}${SET_UNDERLINE}Simply hit ENTER if none${RESET_ALL}"


		# read and validate extras config
		EXTRAS_VALID=""
		while [ ! $EXTRAS_VALID ]; do

			echo ""
			read -p "selection: " _CONF_EXTRAS

			if voxl-extras-code-to-name "$_CONF_EXTRAS" &>/dev/null; then
				echo "Selected extras config"
				EXTRAS_VALID="true"
			elif [[ $_CONF_EXTRAS == "q" ]] || [[ $_CONF_EXTRAS == "Q" ]]; then
				echo "quitting"
				exit 0;
			elif [[ $_CONF_EXTRAS == "" ]]; then
				echo "Selecting default extras config"
				EXTRAS_VALID="true"
				_CONF_EXTRAS=0
			else
				echo "invalid entry, please try again"
			fi
		done
	fi

	## now do all the same validation and construction as would be done
	## with command line args
	if ! _construct_sku_number_from_conf; then
		echo ""
		echo "Would you like to restart the wizard?"
		echo ""
		read -p "Restart? y/n: " input
		case $input in
			[yY]*)
				echo 'Restarting'
				_wizard
				;;
			[nN]*)
				echo 'Ok, exiting'
				exit 0
				;;
			*)
				echo 'Invalid input' >&2
		esac
	fi

	## double check and print results
	PRINT_GREEEN_LINE
	echo ""
	echo "Your answers would construct the following SKU:"
	if ! voxl-inspect-sku --sku $_CONF_SKU; then
		exit 1
	fi


	echo "This sku will be saved to persistent memory so VOXL"
	echo "will remember what it is installed in, even between"
	echo "system image flashes."
	echo ""
	echo -e "${SET_BOLD}${GRN}Press enter to accept and continue.${RESET_ALL}"
	echo "If something is wrong press ctrl-C to quit and try again."

	read


	## write to disk if the user said to continue
	mkdir -p /data/modalai/
	echo $_CONF_SKU > $SKU_FILENAME

	echo ""
	echo -e "${GRN}DONE, $_CONF_SKU has been written to $SKU_FILENAME${RESET_ALL}"
	echo -e "${GRN}Next you will likely want to run ${SET_BOLD}${SET_UNDERLINE}voxl-configure-mpa${RESET_ALL}"
	PRINT_GREEEN_LINE
	exit 0
}







_main(){

	if [ "$#" -eq 0 ]; then
		_wizard
		exit 0
	fi


	while (( "$#" )); do
		case "$1" in

		"-b"|"-B"|"--board"|"--BOARD") # compute board number
			if [ "$_CONF_BOARD" == "" ]; then
				_CONF_BOARD="$2"
				_validate_board
				shift
			else
				PRINT_ERROR "Recieved multiple attempts to set board number, exiting"
				exit 1
			fi
			;;

		"-c"|"-C"|"--cam"|"--CAM") # camera config number
			if [ "$_CONF_CAM_NUM" == "" ]; then
				_CONF_CAM_NUM="$2"
				shift
			else
				PRINT_ERROR "Recieved multiple attempts to set camera config number, exiting"
				exit 1
			fi
			if [ $_CONF_CAM_NUM == "c" ] || [ $_CONF_CAM_NUM == "C" ] || [ $_CONF_CAM_NUM == "custom" ]; then
				echo "Selecting custom camera config"
				_CONF_CAM_NUM="C"
			elif [[ $_CONF_CAM_NUM =~ ^[0-9]+$ ]]; then
				echo "Selected numerical camera config"
			else
				echo "invalid camera config, must be a number or C for custom"
				exit 1
			fi
			;;

		"-d"|"--dry-run")
			DRY_RUN=true
			;;

		"-f"|"-F"|"--family"|"--FAMILY") # family name
			if [ "$_CONF_FAMILY" == "" ]; then
				_CONF_FAMILY="$2"
				_validate_family
				shift
			else
				PRINT_ERROR "Recieved multiple attempts to set family name, exiting"
				exit 1
			fi
			;;

		"-h"|"--help")
			print_usage
			exit 0
			;;

		"-m"|"-M"|"--modem"|"--MODEM") # modem number
			if [ "$_CONF_MODEM" == "" ]; then
				_CONF_MODEM="$2"
				shift
			else
				PRINT_ERROR "Recieved multiple attempts to set modem config number, exiting"
				exit 1
			fi
			;;

		"-q"|"--quiet")
			QUIET=true
			;;

		"-t"|"-T"|"--tx"|"--TX"|"--transmitter"|"--TRANSMITTER") # transmitter number
			if [ "$_CONF_TX" == "" ]; then
				_CONF_TX="$2"
				shift
			else
				PRINT_ERROR "Recieved multiple attempts to set transmitter number, exiting"
				exit 1
			fi
			;;

		"-v"|"-V"|"--version"|"--VERSION") # hardware version number
			if [ "$_CONF_VERSION" == "" ]; then
				_CONF_VERSION="$2"
				shift
			else
				PRINT_ERROR "Recieved multiple attempts to set hardware version number, exiting"
				exit 1
			fi
			;;

		"-w"|"-W"|"wizard"|"--wizard")
			_wizard
			exit 0
			;;

		"-x"|"-X"|"--extras"|"--EXTRAS"|"--misc"|"--MISC") # extrasnumber
			if [ "$_CONF_EXTRAS" == "" ]; then
				_CONF_EXTRAS="$2"
				shift
			else
				PRINT_ERROR "Recieved multiple attempts to set extras config number, exiting"
				exit 1
			fi
			;;

		*)
			PRINT_ERROR "Invalid arg: $1, exiting"
			exit 1
			;;

		esac
		shift
	done

	# no family given
	if [ ! $_CONF_FAMILY ]; then
		PRINT_ERROR "you must provide a family name or run the wizard"
		exit 1;
	fi

	_auto_select_board

	## now we are done validating all the config variables, make a sku number
	## and print the final config we ended up with
	if ! _construct_sku_number_from_conf; then
		exit 1
	fi

	## write to disk, and wipe the old file if it exists
	if [ ! $DRY_RUN ]; then
		if [ -f $FACTORY_FILENAME ]; then
			rm -f $FACTORY_FILENAME
			if [ ! $QUIET ]; then
				echo "${YLW}[WARNING] migrating $FACTORY_FILENAME to $SKU_FILENAME ${RESET_ALL}"
			fi
		fi
		if [ ! $QUIET ]; then
			echo -e "${GRN}[INFO] writing $_CONF_SKU to $SKU_FILENAME${RESET_ALL}"
		fi
		mkdir -p /data/modalai/
		echo $_CONF_SKU > $SKU_FILENAME
	fi

	# when not in quiet mode, print results
	if [ ! $QUIET ]; then
		voxl-inspect-sku --sku $_CONF_SKU
	fi

	exit 0
}




_main "$@"
