2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
28 #if defined(USE_CMS) && defined(USE_VTX_SMARTAUDIO)
30 #include "common/printf.h"
31 #include "common/utils.h"
34 #include "cms/cms_types.h"
35 #include "cms/cms_menu_vtx_smartaudio.h"
37 #include "drivers/vtx_common.h"
39 #include "fc/config.h"
41 #include "io/vtx_string.h"
42 #include "io/vtx_smartaudio.h"
47 // Operational Model and RF modes (CMS)
49 #define SACMS_OPMODEL_UNDEF 0 // Not known yet
50 #define SACMS_OPMODEL_FREE 1 // Freestyle model: Power up transmitting
51 #define SACMS_OPMODEL_RACE 2 // Race model: Power up in pit mode
53 uint8_t saCmsOpmodel
= SACMS_OPMODEL_UNDEF
;
55 #define SACMS_TXMODE_NODEF 0
56 #define SACMS_TXMODE_PIT_OUTRANGE 1
57 #define SACMS_TXMODE_PIT_INRANGE 2
58 #define SACMS_TXMODE_ACTIVE 3
60 uint8_t saCmsRFState
; // RF state; ACTIVE, PIR, POR XXX Not currently used
62 uint8_t saCmsBand
= 0;
63 uint8_t saCmsChan
= 0;
64 uint8_t saCmsPower
= 0;
66 // Frequency derived from channel table (used for reference in band/channel mode)
67 uint16_t saCmsFreqRef
= 0;
69 uint16_t saCmsDeviceFreq
= 0;
71 uint8_t saCmsDeviceStatus
= 0;
73 uint8_t saCmsPitFMode
; // Undef(0), In-Range(1) or Out-Range(2)
75 uint8_t saCmsFselMode
; // Channel(0) or User defined(1)
76 uint8_t saCmsFselModeNew
; // Channel(0) or User defined(1)
78 uint16_t saCmsORFreq
= 0; // POR frequency
79 uint16_t saCmsORFreqNew
; // POR frequency
81 uint16_t saCmsUserFreq
= 0; // User defined frequency
82 uint16_t saCmsUserFreqNew
; // User defined frequency
84 void saCmsUpdate(void)
86 // XXX Take care of pit mode update somewhere???
87 if (saCmsOpmodel
== SACMS_OPMODEL_UNDEF
) {
88 // This is a first valid response to GET_SETTINGS.
89 saCmsOpmodel
= (saDevice
.mode
& SA_MODE_GET_PITMODE
) ? SACMS_OPMODEL_RACE
: SACMS_OPMODEL_FREE
;
91 saCmsFselMode
= (saDevice
.mode
& SA_MODE_GET_FREQ_BY_FREQ
) ? 1 : 0;
93 saCmsBand
= vtxSettingsConfig()->band
;
94 saCmsChan
= vtxSettingsConfig()->channel
;
95 saCmsFreqRef
= vtxSettingsConfig()->freq
;
96 saCmsDeviceFreq
= saCmsFreqRef
;
98 if ((saDevice
.mode
& SA_MODE_GET_PITMODE
) == 0) {
99 saCmsRFState
= SACMS_TXMODE_ACTIVE
;
100 } else if (saDevice
.mode
& SA_MODE_GET_IN_RANGE_PITMODE
) {
101 saCmsRFState
= SACMS_TXMODE_PIT_INRANGE
;
103 saCmsRFState
= SACMS_TXMODE_PIT_OUTRANGE
;
106 saCmsPower
= vtxSettingsConfig()->power
;
108 // if user-freq mode then track possible change
109 if (saCmsFselMode
&& vtxSettingsConfig()->freq
) {
110 saCmsUserFreq
= vtxSettingsConfig()->freq
;
113 saCmsFselModeNew
= saCmsFselMode
; //init mode for menu
116 saUpdateStatusString();
119 char saCmsStatusString
[31] = "- -- ---- ---";
123 static long saCmsConfigOpmodelByGvar(displayPort_t
*, const void *self
);
124 static long saCmsConfigPitFModeByGvar(displayPort_t
*, const void *self
);
125 static long saCmsConfigBandByGvar(displayPort_t
*, const void *self
);
126 static long saCmsConfigChanByGvar(displayPort_t
*, const void *self
);
127 static long saCmsConfigPowerByGvar(displayPort_t
*, const void *self
);
129 void saUpdateStatusString(void)
131 if (saDevice
.version
== 0)
134 // XXX These should be done somewhere else
135 if (saCmsDeviceStatus
== 0 && saDevice
.version
!= 0)
136 saCmsDeviceStatus
= saDevice
.version
;
137 if (saCmsORFreq
== 0 && saDevice
.orfreq
!= 0)
138 saCmsORFreq
= saDevice
.orfreq
;
139 if (saCmsUserFreq
== 0 && saDevice
.freq
!= 0)
140 saCmsUserFreq
= saDevice
.freq
;
142 if (saDevice
.version
== 2) {
143 if (saDevice
.mode
& SA_MODE_GET_OUT_RANGE_PITMODE
)
149 saCmsStatusString
[0] = "-FR"[saCmsOpmodel
];
151 if (saCmsFselMode
== 0) {
152 saCmsStatusString
[2] = "ABEFR"[saDevice
.channel
/ 8];
153 saCmsStatusString
[3] = '1' + (saDevice
.channel
% 8);
155 saCmsStatusString
[2] = 'U';
156 saCmsStatusString
[3] = 'F';
159 if ((saDevice
.mode
& SA_MODE_GET_PITMODE
)
160 && (saDevice
.mode
& SA_MODE_GET_OUT_RANGE_PITMODE
))
161 tfp_sprintf(&saCmsStatusString
[5], "%4d", saDevice
.orfreq
);
162 else if (saDevice
.mode
& SA_MODE_GET_FREQ_BY_FREQ
)
163 tfp_sprintf(&saCmsStatusString
[5], "%4d", saDevice
.freq
);
165 tfp_sprintf(&saCmsStatusString
[5], "%4d",
166 vtx58frequencyTable
[saDevice
.channel
/ 8][saDevice
.channel
% 8]);
168 saCmsStatusString
[9] = ' ';
170 if (saDevice
.mode
& SA_MODE_GET_PITMODE
) {
171 saCmsStatusString
[10] = 'P';
172 if (saDevice
.mode
& SA_MODE_GET_IN_RANGE_PITMODE
) {
173 saCmsStatusString
[11] = 'I';
175 saCmsStatusString
[11] = 'O';
177 saCmsStatusString
[12] = 'R';
178 saCmsStatusString
[13] = 0;
180 tfp_sprintf(&saCmsStatusString
[10], "%3d", (saDevice
.version
== 2) ? saPowerTable
[saDevice
.power
].rfpower
: saPowerTable
[saDacToPowerIndex(saDevice
.power
)].rfpower
);
184 void saCmsResetOpmodel()
186 // trigger data refresh in 'saCmsUpdate()'
187 saCmsOpmodel
= SACMS_OPMODEL_UNDEF
;
190 static long saCmsConfigBandByGvar(displayPort_t
*pDisp
, const void *self
)
195 if (saDevice
.version
== 0) {
196 // Bounce back; not online yet
201 if (saCmsBand
== 0) {
202 // Bouce back, no going back to undef state
207 if ((saCmsOpmodel
== SACMS_OPMODEL_FREE
) && !saDeferred
)
208 saSetBandAndChannel(saCmsBand
- 1, saCmsChan
- 1);
210 saCmsFreqRef
= vtx58frequencyTable
[saCmsBand
- 1][saCmsChan
- 1];
215 static long saCmsConfigChanByGvar(displayPort_t
*pDisp
, const void *self
)
220 if (saDevice
.version
== 0) {
221 // Bounce back; not online yet
226 if (saCmsChan
== 0) {
227 // Bounce back; no going back to undef state
232 if ((saCmsOpmodel
== SACMS_OPMODEL_FREE
) && !saDeferred
)
233 saSetBandAndChannel(saCmsBand
- 1, saCmsChan
- 1);
235 saCmsFreqRef
= vtx58frequencyTable
[saCmsBand
- 1][saCmsChan
- 1];
240 static long saCmsConfigPowerByGvar(displayPort_t
*pDisp
, const void *self
)
245 if (saDevice
.version
== 0) {
246 // Bounce back; not online yet
251 if (saCmsPower
== 0) {
252 // Bouce back; no going back to undef state
257 if (saCmsOpmodel
== SACMS_OPMODEL_FREE
&& !saDeferred
) {
258 vtxSettingsConfigMutable()->power
= saCmsPower
;
264 static long saCmsConfigPitFModeByGvar(displayPort_t
*pDisp
, const void *self
)
269 if (saDevice
.version
== 1) {
270 // V1 device doesn't support PIT mode; bounce back.
275 dprintf(("saCmsConfigPitFmodeByGbar: saCmsPitFMode %d\r\n", saCmsPitFMode
));
277 if (saCmsPitFMode
== 0) {
283 if (saCmsPitFMode
== 1) {
284 saSetMode(SA_MODE_SET_IN_RANGE_PITMODE
);
286 saSetMode(SA_MODE_SET_OUT_RANGE_PITMODE
);
292 static long saCmsConfigFreqModeByGvar(displayPort_t
*pDisp
, const void *self
); // Forward
294 static long saCmsConfigOpmodelByGvar(displayPort_t
*pDisp
, const void *self
)
299 if (saDevice
.version
== 1) {
300 if (saCmsOpmodel
!= SACMS_OPMODEL_FREE
)
301 saCmsOpmodel
= SACMS_OPMODEL_FREE
;
305 uint8_t opmodel
= saCmsOpmodel
;
307 dprintf(("saCmsConfigOpmodelByGvar: opmodel %d\r\n", opmodel
));
309 if (opmodel
== SACMS_OPMODEL_FREE
) {
310 // VTX should power up transmitting.
311 // Turn off In-Range and Out-Range bits
313 } else if (opmodel
== SACMS_OPMODEL_RACE
) {
314 // VTX should power up in pit mode.
315 // Default PitFMode is in-range to prevent users without
316 // out-range receivers from getting blinded.
318 saCmsConfigPitFModeByGvar(pDisp
, self
);
320 // Direct frequency mode is not available in RACE opmodel
321 saCmsFselModeNew
= 0;
322 saCmsConfigFreqModeByGvar(pDisp
, self
);
324 // Trying to go back to unknown state; bounce back
325 saCmsOpmodel
= SACMS_OPMODEL_UNDEF
+ 1;
331 #ifdef USE_EXTENDED_CMS_MENUS
332 static const char * const saCmsDeviceStatusNames
[] = {
338 static OSD_TAB_t saCmsEntOnline
= { &saCmsDeviceStatus
, 2, saCmsDeviceStatusNames
};
340 static OSD_Entry saCmsMenuStatsEntries
[] = {
341 { "- SA STATS -", OME_Label
, NULL
, NULL
, 0 },
342 { "STATUS", OME_TAB
, NULL
, &saCmsEntOnline
, DYNAMIC
},
343 { "BAUDRATE", OME_UINT16
, NULL
, &(OSD_UINT16_t
){ &sa_smartbaud
, 0, 0, 0 }, DYNAMIC
},
344 { "SENT", OME_UINT16
, NULL
, &(OSD_UINT16_t
){ &saStat
.pktsent
, 0, 0, 0 }, DYNAMIC
},
345 { "RCVD", OME_UINT16
, NULL
, &(OSD_UINT16_t
){ &saStat
.pktrcvd
, 0, 0, 0 }, DYNAMIC
},
346 { "BADPRE", OME_UINT16
, NULL
, &(OSD_UINT16_t
){ &saStat
.badpre
, 0, 0, 0 }, DYNAMIC
},
347 { "BADLEN", OME_UINT16
, NULL
, &(OSD_UINT16_t
){ &saStat
.badlen
, 0, 0, 0 }, DYNAMIC
},
348 { "CRCERR", OME_UINT16
, NULL
, &(OSD_UINT16_t
){ &saStat
.crc
, 0, 0, 0 }, DYNAMIC
},
349 { "OOOERR", OME_UINT16
, NULL
, &(OSD_UINT16_t
){ &saStat
.ooopresp
, 0, 0, 0 }, DYNAMIC
},
350 { "BACK", OME_Back
, NULL
, NULL
, 0 },
351 { NULL
, OME_END
, NULL
, NULL
, 0 }
354 static CMS_Menu saCmsMenuStats
= {
355 #ifdef CMS_MENU_DEBUG
356 .GUARD_text
= "XSAST",
357 .GUARD_type
= OME_MENU
,
361 .entries
= saCmsMenuStatsEntries
363 #endif /* USE_EXTENDED_CMS_MENUS */
365 static OSD_TAB_t saCmsEntBand
= { &saCmsBand
, VTX_SMARTAUDIO_BAND_COUNT
, vtx58BandNames
};
367 static OSD_TAB_t saCmsEntChan
= { &saCmsChan
, VTX_SMARTAUDIO_CHANNEL_COUNT
, vtx58ChannelNames
};
369 static OSD_TAB_t saCmsEntPower
= { &saCmsPower
, VTX_SMARTAUDIO_POWER_COUNT
, saPowerNames
};
371 static OSD_UINT16_t saCmsEntFreqRef
= { &saCmsFreqRef
, 5600, 5900, 0 };
373 static const char * const saCmsOpmodelNames
[] = {
379 static const char * const saCmsFselModeNames
[] = {
384 static const char * const saCmsPitFModeNames
[] = {
390 static OSD_TAB_t saCmsEntPitFMode
= { &saCmsPitFMode
, 1, saCmsPitFModeNames
};
392 static long sacms_SetupTopMenu(void); // Forward
394 static long saCmsConfigFreqModeByGvar(displayPort_t
*pDisp
, const void *self
)
399 // if trying to do user frequency mode in RACE opmodel then
400 // revert because user-freq only available in FREE opmodel
401 if (saCmsFselModeNew
!= 0 && saCmsOpmodel
!= SACMS_OPMODEL_FREE
) {
402 saCmsFselModeNew
= 0;
405 // don't call 'saSetBandAndChannel()' / 'saSetFreq()' here,
406 // wait until SET / 'saCmsCommence()' is activated
408 sacms_SetupTopMenu();
413 static long saCmsCommence(displayPort_t
*pDisp
, const void *self
)
418 const vtxSettingsConfig_t prevSettings
= {
419 .band
= vtxSettingsConfig()->band
,
420 .channel
= vtxSettingsConfig()->channel
,
421 .freq
= vtxSettingsConfig()->freq
,
422 .power
= vtxSettingsConfig()->power
,
423 .lowPowerDisarm
= vtxSettingsConfig()->lowPowerDisarm
,
425 vtxSettingsConfig_t newSettings
= prevSettings
;
427 if (saCmsOpmodel
== SACMS_OPMODEL_RACE
) {
429 // Setup band, freq and power.
431 newSettings
.band
= saCmsBand
;
432 newSettings
.channel
= saCmsChan
;
433 newSettings
.freq
= vtx58_Bandchan2Freq(saCmsBand
, saCmsChan
);
434 // If in pit mode, cancel it.
436 if (saCmsPitFMode
== 0)
437 saSetMode(SA_MODE_CLR_PITMODE
|SA_MODE_SET_IN_RANGE_PITMODE
);
439 saSetMode(SA_MODE_CLR_PITMODE
|SA_MODE_SET_OUT_RANGE_PITMODE
);
442 // Setup band and freq / user freq
443 if (saCmsFselModeNew
== 0) {
444 newSettings
.band
= saCmsBand
;
445 newSettings
.channel
= saCmsChan
;
446 newSettings
.freq
= vtx58_Bandchan2Freq(saCmsBand
, saCmsChan
);
448 saSetMode(0); //make sure FREE mode is setup
449 newSettings
.band
= 0;
450 newSettings
.freq
= saCmsUserFreq
;
454 newSettings
.power
= saCmsPower
;
456 if (memcmp(&prevSettings
, &newSettings
, sizeof(vtxSettingsConfig_t
))) {
457 vtxSettingsConfigMutable()->band
= newSettings
.band
;
458 vtxSettingsConfigMutable()->channel
= newSettings
.channel
;
459 vtxSettingsConfigMutable()->power
= newSettings
.power
;
460 vtxSettingsConfigMutable()->freq
= newSettings
.freq
;
461 saveConfigAndNotify();
464 return MENU_CHAIN_BACK
;
467 static long saCmsSetPORFreqOnEnter(void)
469 if (saDevice
.version
== 1)
470 return MENU_CHAIN_BACK
;
472 saCmsORFreqNew
= saCmsORFreq
;
477 static long saCmsSetPORFreq(displayPort_t
*pDisp
, const void *self
)
482 saSetPitFreq(saCmsORFreqNew
);
487 static char *saCmsORFreqGetString(void)
491 tfp_sprintf(pbuf
, "%4d", saCmsORFreq
);
496 static char *saCmsUserFreqGetString(void)
500 tfp_sprintf(pbuf
, "%4d", saCmsUserFreq
);
505 static long saCmsSetUserFreqOnEnter(void)
507 saCmsUserFreqNew
= saCmsUserFreq
;
512 static long saCmsConfigUserFreq(displayPort_t
*pDisp
, const void *self
)
517 saCmsUserFreq
= saCmsUserFreqNew
;
519 return MENU_CHAIN_BACK
;
522 static OSD_Entry saCmsMenuPORFreqEntries
[] = {
523 { "- POR FREQ -", OME_Label
, NULL
, NULL
, 0 },
525 { "CUR FREQ", OME_UINT16
, NULL
, &(OSD_UINT16_t
){ &saCmsORFreq
, 5000, 5999, 0 }, DYNAMIC
},
526 { "NEW FREQ", OME_UINT16
, NULL
, &(OSD_UINT16_t
){ &saCmsORFreqNew
, 5000, 5999, 1 }, 0 },
527 { "SET", OME_Funcall
, saCmsSetPORFreq
, NULL
, 0 },
529 { "BACK", OME_Back
, NULL
, NULL
, 0 },
530 { NULL
, OME_END
, NULL
, NULL
, 0 }
533 static CMS_Menu saCmsMenuPORFreq
=
535 #ifdef CMS_MENU_DEBUG
536 .GUARD_text
= "XSAPOR",
537 .GUARD_type
= OME_MENU
,
539 .onEnter
= saCmsSetPORFreqOnEnter
,
541 .entries
= saCmsMenuPORFreqEntries
,
544 static OSD_Entry saCmsMenuUserFreqEntries
[] = {
545 { "- USER FREQ -", OME_Label
, NULL
, NULL
, 0 },
547 { "CUR FREQ", OME_UINT16
, NULL
, &(OSD_UINT16_t
){ &saCmsUserFreq
, 5000, 5999, 0 }, DYNAMIC
},
548 { "NEW FREQ", OME_UINT16
, NULL
, &(OSD_UINT16_t
){ &saCmsUserFreqNew
, 5000, 5999, 1 }, 0 },
549 { "SET", OME_Funcall
, saCmsConfigUserFreq
, NULL
, 0 },
551 { "BACK", OME_Back
, NULL
, NULL
, 0 },
552 { NULL
, OME_END
, NULL
, NULL
, 0 }
555 static CMS_Menu saCmsMenuUserFreq
=
557 #ifdef CMS_MENU_DEBUG
558 .GUARD_text
= "XSAUFQ",
559 .GUARD_type
= OME_MENU
,
561 .onEnter
= saCmsSetUserFreqOnEnter
,
563 .entries
= saCmsMenuUserFreqEntries
,
566 static OSD_TAB_t saCmsEntFselMode
= { &saCmsFselModeNew
, 1, saCmsFselModeNames
};
568 static OSD_Entry saCmsMenuConfigEntries
[] = {
569 { "- SA CONFIG -", OME_Label
, NULL
, NULL
, 0 },
571 { "OP MODEL", OME_TAB
, saCmsConfigOpmodelByGvar
, &(OSD_TAB_t
){ &saCmsOpmodel
, 2, saCmsOpmodelNames
}, DYNAMIC
},
572 { "FSEL MODE", OME_TAB
, saCmsConfigFreqModeByGvar
, &saCmsEntFselMode
, DYNAMIC
},
573 { "PIT FMODE", OME_TAB
, saCmsConfigPitFModeByGvar
, &saCmsEntPitFMode
, 0 },
574 { "POR FREQ", OME_Submenu
, (CMSEntryFuncPtr
)saCmsORFreqGetString
, &saCmsMenuPORFreq
, OPTSTRING
},
575 #ifdef USE_EXTENDED_CMS_MENUS
576 { "STATX", OME_Submenu
, cmsMenuChange
, &saCmsMenuStats
, 0 },
577 #endif /* USE_EXTENDED_CMS_MENUS */
579 { "BACK", OME_Back
, NULL
, NULL
, 0 },
580 { NULL
, OME_END
, NULL
, NULL
, 0 }
583 static CMS_Menu saCmsMenuConfig
= {
584 #ifdef CMS_MENU_DEBUG
585 .GUARD_text
= "XSACFG",
586 .GUARD_type
= OME_MENU
,
590 .entries
= saCmsMenuConfigEntries
593 static OSD_Entry saCmsMenuCommenceEntries
[] = {
594 { "CONFIRM", OME_Label
, NULL
, NULL
, 0 },
596 { "YES", OME_Funcall
, saCmsCommence
, NULL
, 0 },
598 { "BACK", OME_Back
, NULL
, NULL
, 0 },
599 { NULL
, OME_END
, NULL
, NULL
, 0 }
602 static CMS_Menu saCmsMenuCommence
= {
603 #ifdef CMS_MENU_DEBUG
604 .GUARD_text
= "XVTXCOM",
605 .GUARD_type
= OME_MENU
,
609 .entries
= saCmsMenuCommenceEntries
,
612 static OSD_Entry saCmsMenuFreqModeEntries
[] = {
613 { "- SMARTAUDIO -", OME_Label
, NULL
, NULL
, 0 },
615 { "", OME_Label
, NULL
, saCmsStatusString
, DYNAMIC
},
616 { "FREQ", OME_Submenu
, (CMSEntryFuncPtr
)saCmsUserFreqGetString
, &saCmsMenuUserFreq
, OPTSTRING
},
617 { "POWER", OME_TAB
, saCmsConfigPowerByGvar
, &saCmsEntPower
, 0 },
618 { "SET", OME_Submenu
, cmsMenuChange
, &saCmsMenuCommence
, 0 },
619 { "CONFIG", OME_Submenu
, cmsMenuChange
, &saCmsMenuConfig
, 0 },
621 { "BACK", OME_Back
, NULL
, NULL
, 0 },
622 { NULL
, OME_END
, NULL
, NULL
, 0 }
625 static OSD_Entry saCmsMenuChanModeEntries
[] =
627 { "- SMARTAUDIO -", OME_Label
, NULL
, NULL
, 0 },
629 { "", OME_Label
, NULL
, saCmsStatusString
, DYNAMIC
},
630 { "BAND", OME_TAB
, saCmsConfigBandByGvar
, &saCmsEntBand
, 0 },
631 { "CHAN", OME_TAB
, saCmsConfigChanByGvar
, &saCmsEntChan
, 0 },
632 { "(FREQ)", OME_UINT16
, NULL
, &saCmsEntFreqRef
, DYNAMIC
},
633 { "POWER", OME_TAB
, saCmsConfigPowerByGvar
, &saCmsEntPower
, 0 },
634 { "SET", OME_Submenu
, cmsMenuChange
, &saCmsMenuCommence
, 0 },
635 { "CONFIG", OME_Submenu
, cmsMenuChange
, &saCmsMenuConfig
, 0 },
637 { "BACK", OME_Back
, NULL
, NULL
, 0 },
638 { NULL
, OME_END
, NULL
, NULL
, 0 }
641 static OSD_Entry saCmsMenuOfflineEntries
[] =
643 { "- VTX SMARTAUDIO -", OME_Label
, NULL
, NULL
, 0 },
645 { "", OME_Label
, NULL
, saCmsStatusString
, DYNAMIC
},
646 #ifdef USE_EXTENDED_CMS_MENUS
647 { "STATX", OME_Submenu
, cmsMenuChange
, &saCmsMenuStats
, 0 },
648 #endif /* USE_EXTENDED_CMS_MENUS */
650 { "BACK", OME_Back
, NULL
, NULL
, 0 },
651 { NULL
, OME_END
, NULL
, NULL
, 0 }
654 CMS_Menu cmsx_menuVtxSmartAudio
; // Forward
656 static long sacms_SetupTopMenu(void)
658 if (saCmsDeviceStatus
) {
659 if (saCmsFselModeNew
== 0)
660 cmsx_menuVtxSmartAudio
.entries
= saCmsMenuChanModeEntries
;
662 cmsx_menuVtxSmartAudio
.entries
= saCmsMenuFreqModeEntries
;
664 cmsx_menuVtxSmartAudio
.entries
= saCmsMenuOfflineEntries
;
670 CMS_Menu cmsx_menuVtxSmartAudio
= {
671 #ifdef CMS_MENU_DEBUG
672 .GUARD_text
= "XVTXSA",
673 .GUARD_type
= OME_MENU
,
675 .onEnter
= sacms_SetupTopMenu
,
677 .entries
= saCmsMenuOfflineEntries
,