#include "mungal4.h" #pragma hdrstop #include "l4icom.h" #include "l4host.h" #include "l4app.h" #include "l4grend.h" #include "..\munga\hostmgr.h" //----------------------------------------------------------- // Timing values (in seconds) for CB button control // All values derived experimentally //----------------------------------------------------------- #define SEEK_STEP_TIME 0.28 // seek step delay #define NORMAL_STEP_TIME 0.05 // normal step delay #define BEEP_TIME 0.2 // length of beep //----------------------------------------------------------- // Special code & data to test recalibration: // set to '1' to create and use 'home' button //----------------------------------------------------------- #if 1 # define HOMETEST static ControlsButton resetButton; enum { resetButtonNumber = LBE4ControlsManager::ButtonSecondary6 }; #endif //----------------------------------------------------------- // Debugging aid //----------------------------------------------------------- #if 0 # define LOCAL_TEST # define Test_Tell(n) cout << n << flush; #else # define Test_Tell(n) #endif //----------------------------------------------------------- // Button/lamp assignments //----------------------------------------------------------- static int channelButtonNumber[L4Icom::numberOfChannels] = { LBE4ControlsManager::ButtonAuxUpperCenter1, LBE4ControlsManager::ButtonAuxUpperCenter2, LBE4ControlsManager::ButtonAuxUpperCenter3, LBE4ControlsManager::ButtonAuxUpperCenter4, LBE4ControlsManager::ButtonAuxUpperCenter5, LBE4ControlsManager::ButtonAuxUpperCenter6, LBE4ControlsManager::ButtonAuxUpperCenter7 }; #if 0 enum { // // TEST I/O // pttButtonNumber = LBE4ControlsManager::ButtonAuxUpperCenter8, homeSensorInput = LBE4ControlsManager::ButtonPanic, pttRelayOutput = LBE4ControlsManager::ButtonAuxLowerRight5, ampEnableOutput = LBE4ControlsManager::ButtonAuxLowerRight6, IncrementRelayOutput = LBE4ControlsManager::ButtonAuxLowerRight7, DecrementRelayOutput = LBE4ControlsManager::ButtonAuxLowerRight8 }; #else enum { // // These are the "real" assignments // pttButtonNumber = LBE4ControlsManager::ButtonAuxUpperCenter8, homeSensorInput = LBE4ControlsManager::ButtonIcomSensor, pttRelayOutput = LBE4ControlsManager::LampIcomPTTRelay, ampEnableOutput = LBE4ControlsManager::LampIcomAmpEnable, IncrementRelayOutput = LBE4ControlsManager::LampIcomIncRelay, DecrementRelayOutput = LBE4ControlsManager::LampIcomDecRelay }; #endif //----------------------------------------------------------- // Handy routine to mute audio output //----------------------------------------------------------- void amp_enable(LBE4ControlsManager * controls_manager, Logical on) { controls_manager->SetLamp( ampEnableOutput, (on ? LBE4ControlsManager::LampSolidBright : LBE4ControlsManager::LampSolidOff ) ); Check_Fpu(); } //########################################################################## //############################ L4Icom ################################ //########################################################################## //--------------------------------------------------------------------- // Creator //--------------------------------------------------------------------- L4Icom::L4Icom(HostID host_id, int channel_offset) : Icom(host_id,0) { Test_Tell("L4Icom::L4Icom(" << host_id << ", " << channel_offset << ")\n"); Check_Pointer(this); //-------------------------------------- // Initialize values //-------------------------------------- channelOffset = channel_offset; Check(application); controlsManager = (LBE4ControlsManager *) application->GetControlsManager(); Check(controlsManager); hardwareChannel = Icom::undefinedChannel; previousChannel = Icom::undefinedChannel; previousPTTStatus = False; //-------------------------------------- // Clear controls inputs //-------------------------------------- homeSensor = 0; channelButton = 0; pttButton = 0; //-------------------------------------- // Enable only if allowed //-------------------------------------- char *controlString(getenv("L4INTERCOM")); if (controlString != NULL) { //-------------------------------------- // Seek channel 40, move to 1st channel //-------------------------------------- Recalibrate(); } else { //-------------------------------------- // Don't even try. //-------------------------------------- state = disabled; } Check_Fpu(); } //--------------------------------------------------------------------- // Destructor //--------------------------------------------------------------------- L4Icom::~L4Icom() { Test_Tell("L4Icom::~L4Icom()\n"); Check(this); //-------------------------------------- // Make sure intercom is turned off //-------------------------------------- SetPTTStatusValue(False); amp_enable(controlsManager, False); //-------------------------------------- // Make note of failure state //-------------------------------------- if (state == failed) { Tell("L4Icom::~L4Icom(), Icom had failed!\n"); NotationFile *failureFile = new NotationFile("FAILURE.LOG"); Check(failureFile); failureFile->SetEntry("Intercom","seekError",1); delete failureFile; } //-------------------------------------- // The plug automatically unlinks // from the L4Icom Manager upon deletion. //-------------------------------------- Check_Fpu(); } //--------------------------------------------------------------------- // Test instance //--------------------------------------------------------------------- Logical L4Icom::TestInstance() const { Icom::TestInstance(); Check_Fpu(); return True; } //--------------------------------------------------------------------- // SetChannelValue //--------------------------------------------------------------------- void L4Icom::SetChannelValue(int new_channel) { Test_Tell("L4Icom::SetChannelValue(" << new_channel << ")\n"); Check(this); if ((state != disabled) && (state != failed)) { //-------------------------------------- // Call overridden method //-------------------------------------- Icom::SetChannelValue(new_channel); } Check_Fpu(); } //--------------------------------------------------------------------- // Set PTTStatusValue //--------------------------------------------------------------------- void L4Icom::SetPTTStatusValue(Logical new_ptt) { Test_Tell("L4Icom::SetPTTStatusValue(" << new_ptt << ")\n"); Check(this); if (state == onChannel) { //-------------------------------------- // Call overridden method //-------------------------------------- Icom::SetPTTStatusValue(new_ptt); //-------------------------------------- // Turn on/off PTT output and lamp //-------------------------------------- if (previousPTTStatus != PTTStatus) { previousPTTStatus = PTTStatus; Check(controlsManager); int relay_output = PTTStatus ? LBE4ControlsManager::LampSolidBright : LBE4ControlsManager::LampSolidOff; controlsManager->SetLamp(pttRelayOutput, relay_output); controlsManager->SetLamp( pttButtonNumber, (PTTStatus ? LBE4ControlsManager::LampSolidBright : LBE4ControlsManager::LampSolidDim ) ); } } Check_Fpu(); } //--------------------------------------------------------------------- // SetPACaptiveValue //--------------------------------------------------------------------- void L4Icom::SetPACaptiveValue(Logical new_pa) { Test_Tell("L4Icom::SetPACaptiveValue(" << new_pa << ")\n"); Check(this); //----------------------------------------------- // If entering captivity, disable channel select //----------------------------------------------- if (new_pa && (!PACaptive)) { //-------------------------------------- // Call overridden method //-------------------------------------- Icom::SetPACaptiveValue(new_pa); //-------------------------------------- // turn off PTT lamp //-------------------------------------- controlsManager->SetLamp( pttButtonNumber, LBE4ControlsManager::LampSolidOff ); //-------------------------------------- // Turn off channel indicators //-------------------------------------- ChannelSelectState(False); } //----------------------------------------------- // If exiting captivity, enable channel select //----------------------------------------------- if ((!new_pa) && PACaptive) { //-------------------------------------- // Call overridden method //-------------------------------------- // This must be done BEFORE // attempting to set the PTT status! // (hence the duplicated call) //-------------------------------------- Icom::SetPACaptiveValue(new_pa); ChannelSelectState(True); previousPTTStatus = 2; // non-Logical value, forces update SetPTTStatusValue(PTTStatus); // force hardware update } Check_Fpu(); } //--------------------------------------------------------------------- // Recalibrate //--------------------------------------------------------------------- void L4Icom::Recalibrate() { Test_Tell("L4Icom::Recalibrate()\n"); Check(this); seekRequired = False; timeAccumulator = 0.0; seekCount = 84; // twice around plus a few more ChannelSelectState(False); // Turn off selection lamps amp_enable(controlsManager, False); // turn off the speaker state = seek40; Check_Fpu(); } //--------------------------------------------------------------------- // Update //--------------------------------------------------------------------- void L4Icom::Update(Scalar delta_t) { Test_Tell("L4Icom::Update(" << delta_t << ")\n"); Check(this); //------------------------------------------------------------------ // Do nothing if disabled or failed! //------------------------------------------------------------------ if ((state == disabled) || (state == failed)) { Check_Fpu(); return; } //------------------------------------------------------------------ // PTT control //------------------------------------------------------------------ if (state == onChannel) { if (pttButton > 0) { SetPTTStatus(True); pttButton = 0; } else if (pttButton < 0) { SetPTTStatus(False); pttButton = 0; } } else if (previousPTTStatus) { SetPTTStatus(False); } //------------------------------------------------------------------ // Channel selection //------------------------------------------------------------------ if (channelSelectEnabled) { //-------------------------------------- // Process button if pressed //-------------------------------------- if (channelButton > 0) { //-------------------------------------- // Convert button press to icom channel //-------------------------------------- int button_number = channelButton - 1, // convert to button number new_channel = Icom::undefinedChannel; for(int i=0; i 0) { //------------------------------------------- // Found 40! //------------------------------------------- Test_Tell("--> reachedChannel\n"); hardwareChannel = (40-1); state = reachedChannel; //------------------------------------------- // Display auxiliary intercom labels //------------------------------------------- { Check(application); L4GaugeRenderer *gauge_renderer = ((L4Application *)application)-> GetGaugeRenderer(); Check(gauge_renderer); gauge_renderer->Configure("intercomEnable", (Entity *) NULL); } //------------------------------------------- // Everybody starts up on the 'first' channel //------------------------------------------- if (PACaptive) { channelBeforePA = channelOffset; } else { ChannelSelectState(True); SetChannel(channelOffset); } //------------------------------------------- // Update the lamp display //------------------------------------------- ChannelStatusUpdate(); } //------------------------------------------- // Try next channel //------------------------------------------- else { DecrementChannel(); } } break; //--------------------------------------------------- case offChannel: if (WaitedLongEnough(NORMAL_STEP_TIME)) { int delta = channel - hardwareChannel; if (delta == 0) { state = reachedChannel; } else { //------------------------------------------- // Choose direction, modulo 40 //------------------------------------------- // channel = desired channel // hardwareChannel = current channel //------------------------------------------- if (delta > 20) { delta -= 40; } else if (delta < -20) { delta += 40; } if (delta < 0) { DecrementChannel(); } else { IncrementChannel(); } //------------------------------------------- // Update the lamp display //------------------------------------------- ChannelStatusUpdate(); } } break; //--------------------------------------------------- // reachedChannel: this is a delay to allow to CB // to finish "beeping" before the audio is turned on. //--------------------------------------------------- case reachedChannel: if (WaitedLongEnough(BEEP_TIME)) { Test_Tell("L4Icom::Update, reachedChannel --> onChannel\n"); amp_enable(controlsManager, True); state = onChannel; } break; //--------------------------------------------------- case onChannel: Test_Tell("L4Icom::Update, onChannel\n"); if (channel != hardwareChannel) { state = offChannel; timeAccumulator = NORMAL_STEP_TIME; // bypass the delay amp_enable(controlsManager, False); // mute the output } break; //--------------------------------------------------- case disabled: case failed: break; } Check_Fpu(); } //--------------------------------------------------------------------- // LongEnough //--------------------------------------------------------------------- Logical L4Icom::WaitedLongEnough(Scalar delay_time) { Test_Tell("L4Icom::WaitedLongEnough(" << delay_time >> ") "); Check(this); //------------------------------------------- // Check to see if delayed long enough //------------------------------------------- if (timeAccumulator >= delay_time) { Test_Tell("long enough!\n"); timeAccumulator = 0.0; Check_Fpu(); return True; } else { Test_Tell("\n"); Check_Fpu(); return False; } } //--------------------------------------------------------------------- // IncrementChannel //--------------------------------------------------------------------- void L4Icom::IncrementChannel() { Test_Tell("L4Icom::IncrementChannel()\n"); Check(this); Check(controlsManager); //-------------------------------------- // Increment the channel number counter //-------------------------------------- if (++hardwareChannel > (40-1)) { hardwareChannel = 0; } //-------------------------------------- // Press the 'inc' button on the CB //-------------------------------------- controlsManager->SetLamp( IncrementRelayOutput, LBE4ControlsManager::LampSolidBright ); //-------------------------------------- // ...and again, for a fixed delay //-------------------------------------- controlsManager->SetLamp( IncrementRelayOutput, LBE4ControlsManager::LampSolidBright ); //-------------------------------------- // Release the 'inc' button on the CB //-------------------------------------- controlsManager->SetLamp( IncrementRelayOutput, LBE4ControlsManager::LampSolidOff ); Check_Fpu(); } //--------------------------------------------------------------------- // DecrementChannel //--------------------------------------------------------------------- void L4Icom::DecrementChannel() { Test_Tell("L4Icom::DecrementChannel()\n"); Check(this); Check(controlsManager); //-------------------------------------- // Decrement the channel number counter //-------------------------------------- if (--hardwareChannel < 0) { hardwareChannel = (40-1); } //-------------------------------------- // Press the 'dec' button on the CB //-------------------------------------- controlsManager->SetLamp( DecrementRelayOutput, LBE4ControlsManager::LampSolidBright ); //-------------------------------------- // ...and again, for a fixed delay //-------------------------------------- controlsManager->SetLamp( DecrementRelayOutput, LBE4ControlsManager::LampSolidBright ); //-------------------------------------- // Release the 'dec' button on the CB //-------------------------------------- controlsManager->SetLamp( DecrementRelayOutput, LBE4ControlsManager::LampSolidOff ); Check_Fpu(); } //--------------------------------------------------------------------- // ChannelStatusUpdate //--------------------------------------------------------------------- void L4Icom::ChannelStatusUpdate() { Test_Tell("L4Icom::ChannelStatusUpdate()\n"); Check(this); Check(controlsManager); int logical_channel_number; if (channelSelectEnabled) { //-------------------------------------- // Has the channel changed? //-------------------------------------- if (previousChannel != hardwareChannel) { //---------------------------------------- // Yes. Is the previous channel undefined? //---------------------------------------- if (previousChannel != Icom::undefinedChannel) { //-------------------------------------- // No, set previous button to dim //-------------------------------------- logical_channel_number = previousChannel - channelOffset; if (logical_channel_number < L4Icom::numberOfChannels) { controlsManager->SetLamp( channelButtonNumber[logical_channel_number], LBE4ControlsManager::LampSolidDim ); } } previousChannel = hardwareChannel; //-------------------------------------- // Is the new channel undefined? //-------------------------------------- if (previousChannel != Icom::undefinedChannel) { //-------------------------------------- // No, set current button to bright //-------------------------------------- logical_channel_number = hardwareChannel - channelOffset; if (logical_channel_number < L4Icom::numberOfChannels) { controlsManager->SetLamp( channelButtonNumber[logical_channel_number], LBE4ControlsManager::LampSolidBright ); } } } } Check_Fpu(); } //--------------------------------------------------------------------- // ChannelSelectState //--------------------------------------------------------------------- void L4Icom::ChannelSelectState(Logical state) { Test_Tell("L4Icom::ChannelStatusUpdate(" << state << ")\n"); Check(this); Check(controlsManager); int i, logical_channel_number; if ((state != disabled) && (state != failed)) { channelSelectEnabled = True; for(i=0; iSetLamp( channelButtonNumber[i], (i==logical_channel_number ? LBE4ControlsManager::LampSolidBright : LBE4ControlsManager::LampSolidDim ) ); } } else { channelSelectEnabled = False; for(i=0; iSetLamp( channelButtonNumber[i], LBE4ControlsManager::LampSolidOff ); } } Check_Fpu(); } //########################################################################## //######################## L4IcomManager ############################# //########################################################################## //-------------------------------------------------------------------------- // Virtual Data support // Derivation* L4IcomManager::GetClassDerivations() { static Derivation classDerivations(IcomManager::GetClassDerivations(), "L4IcomManager"); return &classDerivations; } L4IcomManager::SharedData L4IcomManager::DefaultData( L4IcomManager::GetClassDerivations(), L4IcomManager::GetMessageHandlers() ); //-------------------------------------------------------------------------- // Creator // L4IcomManager::L4IcomManager( SharedData &shared_data ): IcomManager(shared_data), localIcom(NULL) { Test_Tell("L4IcomManager::L4IcomManager()\n"); Check_Pointer(this); previousUpdateTime = Now(); Check_Fpu(); } //-------------------------------------------------------------------------- // Destructor // L4IcomManager::~L4IcomManager() { Test_Tell("L4IcomManager::~L4IcomManager()\n"); Check(this); // We don't need to delete the local Icom object: it's a member // of the instanceList in the IcomManager class, which is deleted // by the IcomManager destructor. Check_Fpu(); } //-------------------------------------------------------------------------- Logical L4IcomManager::TestInstance() const { return IsDerivedFrom(*GetClassDerivations()); } //-------------------------------------------------------------------------- L4Icom * L4IcomManager::MakeIcom(HostID host_id, int /*unit_number*/) { Test_Tell("L4IcomManager::MakeIcom(" << host_id << ")\n"); Check(this); //------------------------------------------ // Create, register icom object //------------------------------------------ L4Icom *icom = new L4Icom(host_id, 0); // HACK - eventually set channel offset based on cockpit group! Check(icom); Register_Object(icom); //------------------------------------------ // Add to global list //------------------------------------------ instanceList.Add(icom); //------------------------------------------ // Get local host ID // (we need to do because the local host is // created quite late in the whole process) //------------------------------------------ Check(application); HostManager *host_manager = application->GetHostManager(); Check(host_manager); Host *local_host = host_manager->GetLocalHost(); Check(local_host); HostID local_host_id = local_host->GetHostID(); //------------------------------------------ // If assigned to a local host, make // this intercom object local as well //------------------------------------------ Test_Tell( "L4IcomManager::MakeIcom local_host_id = " << local_host_id << "\n" ); Test_Tell( "L4IcomManager::MakeIcom host_id = " << host_id << "\n" ); if (host_id == local_host_id) { Test_Tell("L4IcomManager::MakeIcom, set local icom\n"); //----------------------------------------------------------------- // Set localIcom socket //----------------------------------------------------------------- Verify(localIcom.GetCurrent() == NULL); localIcom.AddPlug(icom); //----------------------------------------------------------------- // Add connections //----------------------------------------------------------------- #if 0 Check(icom->controlsManager); ControlsUpdateManager *button_pointer; //------------------------------------------ // Add connection to home sensor //------------------------------------------ button_pointer = &icom->controlsManager->buttonGroup[homeSensorInput]; Check(button_pointer); button_pointer->Add( ModeManager::ModeAlwaysActive, &icom->homeSensor, icom ); //------------------------------------------ // Add connections to channel buttons //------------------------------------------ for(int i=0; icontrolsManager->buttonGroup[channelButtonNumber[i]]; Check(button_pointer); button_pointer->Add( L4ModeManager::ModeIntercom, &icom->channelButton, icom ); icom->controlsManager->MakeLinkedLamp(channelButtonNumber[i]); } # if defined(HOMETEST) //------------------------------------------ // Add connection to reset button //------------------------------------------ button_pointer = &icom->controlsManager->buttonGroup[resetButtonNumber]; Check(button_pointer); button_pointer->Add( ModeManager::ModeAlwaysActive, &resetButton, icom ); resetButton = 0; # endif //------------------------------------------ // Add connection to PTT button //------------------------------------------ button_pointer = &icom->controlsManager->buttonGroup[pttButtonNumber]; Check(button_pointer); button_pointer->Add( ModeManager::ModeAlwaysActive, &icom->pttButton, icom ); icom->controlsManager->MakeLinkedLamp(pttButtonNumber); #endif } Check_Fpu(); return icom; } //-------------------------------------------------------------------------- void L4IcomManager::LoadMission(Mission *mission) { Check(this); IcomManager::LoadMission(mission); Check_Fpu(); } //-------------------------------------------------------------------------- void L4IcomManager::Shutdown() { Check(this); IcomManager::Shutdown(); Check_Fpu(); } //-------------------------------------------------------------------------- void L4IcomManager::Execute() { // Test_Tell("L4IcomManager::Execute()\n"); Check(this); Scalar delta_t; Time right_now; # if defined(HOMETEST) //------------------------------------------ // If reset button pressed, recalibrate //------------------------------------------ if (resetButton > 0) { resetButton = 0; L4Icom *local_icom = localIcom.GetCurrent(); if (local_icom != NULL) { std::cout << "L4IcomManager::Execute, Reset!!!!!\n"; local_icom->Recalibrate(); } } # endif //------------------------------------------ // Get time, generate delta_t //------------------------------------------ right_now = Now(); delta_t = (Scalar) (right_now - previousUpdateTime); if (delta_t > 0.0) { previousUpdateTime = right_now; //------------------------------------------ // Process local icom object //------------------------------------------ L4Icom *local_icom = localIcom.GetCurrent(); if (local_icom != NULL) { local_icom->Update(delta_t); } } Check_Fpu(); }