############################################################################### ## ## Nasal for dual control of a KX165 NavComm radio over the multiplayer ## network. ## ## Copyright (C) 2007 - 2010 Anders Gidenstam (anders(at)gidenstam.org) ## This file is licensed under the GPL license version 2 or later. ## ############################################################################### # Note: # This module MUST be loaded as KX165. # # Slave button presses. var swap_btn = "frq-swap-btn"; var freq_decS = "freq-decS-clicked"; var freq_incS = "freq-incS-clicked"; var freq_decL = "freq-decL-clicked"; var freq_incL = "freq-incL-clicked"; # Settings var freq_selected = "frequencies/selected-mhz"; var freq_standby = "frequencies/standby-mhz"; var comm_base = ["instrumentation/comm[0]", "instrumentation/comm[1]"]; var nav_base = ["instrumentation/nav[0]", "instrumentation/nav[1]"]; ########################################################################### var master_kx165tso = { new : func(n) { var obj = {}; obj.parents = [master_kx165tso]; obj.nav_base = props.globals.getNode("instrumentation/nav[" ~ n ~ "]"); obj.comm_base = props.globals.getNode("instrumentation/comm[" ~ n ~ "]"); return obj; }, swap_nav : func() { var tmp = me.nav_base.getNode(freq_selected).getValue(); me.nav_base.getNode(freq_selected).setValue (me.nav_base.getNode(freq_standby).getValue()); me.nav_base.getNode(freq_standby).setValue(tmp); }, swap_comm : func() { var tmp = me.comm_base.getNode(freq_selected).getValue(); me.comm_base.getNode(freq_selected).setValue (me.comm_base.getNode(freq_standby).getValue()); me.comm_base.getNode(freq_standby).setValue(tmp); }, adjust_nav_frequency : func(d) { adjust_radio_frequency( me.nav_base.getNode(freq_standby), d, 108, 117.95); }, adjust_comm_frequency : func(d) { adjust_radio_frequency( me.comm_base.getNode(freq_standby), d, 118, 135.975); } }; ########################################################################### var slave_kx165tso = { new : func(n, airoot) { var obj = {}; obj.parents = [slave_kx165tso]; obj.root = airoot; obj.nav_base = props.globals.getNode("instrumentation/nav[" ~ n ~ "]"); obj.comm_base = props.globals.getNode("instrumentation/comm[" ~ n ~ "]"); return obj; }, swap_nav : func() { var p = me.nav_base.getNode(swap_btn); # print("KX165tso[?].NAVSWAP"); if (!p.getValue()) { p.setValue(1); settimer(func { p.setValue(0); }, 1.0); } }, swap_comm : func() { var p = me.comm_base.getNode(swap_btn); # print("KX165tso[?].COMMSWAP"); if (!p.getValue()) { p.setValue(1); settimer(func { p.setValue(0); }, 1.0); } }, adjust_nav_frequency : func(d) { var p = 0; if (abs(d) < 0.99) { p = (d < 0) ? me.nav_base.getNode(freq_decS) : me.nav_base.getNode(freq_incS); } else { p = (d < 0) ? me.nav_base.getNode(freq_decL) : me.nav_base.getNode(freq_incL); } if (!p.getValue()) { p.setValue(1); settimer(func { p.setValue(0); }, 1.0); } }, adjust_comm_frequency : func(d) { var p = 0; if (abs(d) < 0.99) { p = (d < 0) ? me.comm_base.getNode(freq_decS) : me.comm_base.getNode(freq_incS); } else { p = (d < 0) ? me.comm_base.getNode(freq_decL) : me.comm_base.getNode(freq_incL); } if (!p.getValue()) { p.setValue(1); settimer(func { p.setValue(0); }, 1.0); } } }; ########################################################################### # The KX-165 pick animations default to master. # NOTE: Use make_master() and make_slave_to(). # Do NOT change kx165tso directly. var kx165tso = [master_kx165tso.new(0), master_kx165tso.new(1)]; ########################################################################### # API for pick animations and dual control setup. ########################################################################### ########################################################################### # n - NavComm# var make_master = func(n) { kx165tso[n] = master_kx165tso.new(n); } ########################################################################### # n - NavComm# var make_slave_to = func(n, airoot) { kx165tso[n] = slave_kx165tso.new(n, airoot); } ########################################################################### # n - NavComm# swap_nav = func(n) { kx165tso[n].swap_nav(); } ########################################################################### # n - NavComm# swap_comm = func(n, b) { kx165tso[n].comm_base.getNode(swap_btn, 1).setValue(b); if (b) kx165tso[n].swap_comm(); } ########################################################################### # n - NavComm# # d - adjustment adjust_nav_frequency = func(n, d) { kx165tso[n].adjust_nav_frequency(d); } ########################################################################### # n - NavComm# # d - adjustment adjust_comm_frequency = func(n, d) { kx165tso[n].adjust_comm_frequency(d); } ########################################################################### # Create aliases to drive a radio 3d model in an AI/MP model. # n - NavComm# var animate_aimodel = func(n, airoot) { # Comm var base = comm_base[n]; var p = "systems/electrical/outputs/comm["~ n ~"]"; airoot.getNode(p, 1).alias(props.globals.getNode(p)); p = "instrumentation/comm["~ n ~"]/serviceable"; airoot.getNode(p, 1).alias(props.globals.getNode(p)); p = base ~ "/" ~ freq_selected; airoot.getNode(p, 1).alias(props.globals.getNode(p)); p = base ~ "/" ~ freq_standby; airoot.getNode(p, 1).alias(props.globals.getNode(p)); p = base ~ "/" ~ swap_btn; props.globals.getNode(p, 1).alias(airoot.getNode(p)); # Nav base = nav_base[n]; p = "systems/electrical/outputs/nav["~ n ~"]"; airoot.getNode(p, 1).alias(props.globals.getNode(p)); p = "instrumentation/nav["~ n ~"]/serviceable"; airoot.getNode(p, 1).alias(props.globals.getNode(p)); p = base ~ "/" ~ freq_selected; airoot.getNode(p, 1).alias(props.globals.getNode(p)); p = base ~ "/" ~ freq_standby; airoot.getNode(p, 1).alias(props.globals.getNode(p)); p = base ~ "/" ~ swap_btn; props.globals.getNode(p, 1).alias(airoot.getNode(p)); } ########################################################################### # Create a TDMEncoder node array for sending the current radio state to # slaves. # n - NavComm# var master_send_state = func(n) { var cb = props.globals.getNode(comm_base[n]); var nb = props.globals.getNode(nav_base[n]); return [ cb.getNode(freq_selected), cb.getNode(freq_standby), nb.getNode(freq_selected), nb.getNode(freq_standby) ]; } ########################################################################### # Create a SwitchDecoder action array for processing button presses # from a slave. # n - Comm# var master_receive_slave_buttons = func(n) { return [ # Comm func (b) { if (b) { swap_comm(n, 1); settimer(func { swap_comm(n, 0); }, 1.0) } }, func (b) { if (b) { adjust_comm_frequency(n, -0.025); } }, func (b) { if (b) { adjust_comm_frequency(n, 0.025); } }, func (b) { if (b) { adjust_comm_frequency(n, -1.0); } }, func (b) { if (b) { adjust_comm_frequency(n, 1.0); } }, # Nav func (b) { if (b) { swap_nav(n); } }, func (b) { if (b) { adjust_nav_frequency(n, -0.05); } }, func (b) { if (b) { adjust_nav_frequency(n, 0.05); } }, func (b) { if (b) { adjust_nav_frequency(n, -1.0); } }, func (b) { if (b) { adjust_nav_frequency(n, 1.0); } } ]; } ########################################################################### # Create a TDMDecoder action array for processing the radio state # from the master. # n - NavComm# var slave_receive_master_state = func(n) { var cb = props.globals.getNode(comm_base[n]); var nb = props.globals.getNode(nav_base[n]); return [ func (v) { cb.getNode(freq_selected).setValue(v); }, func (v) { cb.getNode(freq_standby).setValue(v); }, func (v) { nb.getNode(freq_selected).setValue(v); }, func (v) { nb.getNode(freq_standby).setValue(v); } ]; } ########################################################################### # Create a SwitchEncoder node array for sending button presses # to the master # n - NavComm# var slave_send_buttons = func(n) { var cb = props.globals.getNode(comm_base[n]); var nb = props.globals.getNode(nav_base[n]); return [ # Comm cb.getNode(swap_btn, 1), cb.getNode(freq_decS, 1), cb.getNode(freq_incS, 1), cb.getNode(freq_decL, 1), cb.getNode(freq_incL, 1), # Nav nb.getNode(swap_btn, 1), nb.getNode(freq_decS, 1), nb.getNode(freq_incS, 1), nb.getNode(freq_decL, 1), nb.getNode(freq_incL, 1) ]; } ########################################################################### # Generic frequency stepper. # f - frequency property # d - change # min - min frequency # max - max frequency var adjust_radio_frequency = func(f, d, min, max) { var old = f.getValue(); var new = old + d; if (new < min - 0.005) { new = int(max) + (new - int(new)); } if (new > max + 0.005) { new = int(min) + (new - int(new)); if (int(new + 0.005) > min) new -= 1; } # print("Old: " ~ old ~ " Intermediate: " ~ (old + d) ~ " New: " ~ new); f.setValue(new); }