Here's a quick tour: 1. Stamp Pin Map. This section establishes the pin #'s for the various input/output lines. You probably won't have to make any changes here, but if you do, you won't have to hunt through the program looking for references to the pin you need to change. 2. Band Names. Bands is a symbol used by the program to locate text to be displayed on the LCD for the each of the bands. The names are fixed-width and arranged in the same order as the FT990's band data encoding. That is, when the radio is tuned to the 160 meter band, the band data encoding is 1, so 160 meters is listed first (0 only appears when the radio is off). The FT990 is an HF radio and all the HF bands are listed, but for completeness I also listed other values that could appear on the band data jack. I labeled them 'UNK' but I assume they have some meaning for VHF or UHF radios. MaxBands is used as array dimensions later to remember the last antenna and amplifier segment used for each band. It is set to 9 to save Stamp memory space. 3. Antenna Names and Numbers. Antennas is a symbol indicating the start of the list of antennas. You'll want to customize this to match your setup. Each antenna is two data items -- the physical antenna number of the antenna on the switch, and a fixed-width name to display on the LCD when that antenna is selected. LIST_END is an important symbol -- it is a 'marker' used by the antenna cycling routines to 'wrap around' from the last antenna to the first when you press the up/down buttons. 4. Band to Antenna Map. This section (BandAnts) maps antennas to the bands they work on. For each pair, the first number is the band number (from the Bands list above) and the second is the antenna number. The controller will prevent transmission to an antenna not defined for the current band. Change this to match your station. The structure of the program itself is pretty simple. When the Stamp is powered up, it starts executing from the top, which begins with a pause to let the LCD settle. All variables start off initialized to 0 so the current antenna will be 0. The current band comes from the band data jack of the radio so the first thing that needs to happen is process this 'band change' at RadioBandChanged. This selects an appropriate antenna for this band (either by selecting the last one we used or picking the first one in the BandAnts list for this band. Once selected, we tell the antenna switch about it and update the display. Then we drop into the loop, and the Stamp is doomed to repeat forever. It constantly cycles looking for changes in its inputs: 1. UP or DOWN buttons cause the antenna to change. These cycle through the Antennas list sending change commands to the switch and enabling or disabling the transmitter according to the BandAnts map. 2. Band data change to detect band QSYs on the radio. 3. Each time the LCD is updated, its backlight comes on and then goes out after a short delay. You can adjust the length of the delay by changing the value of the constant BkLitTime. Each increment of 25 is roughly a second but depends on the processing in the loop. 4. Poll the amplifier serial line to see if it is announcing anything. The Stamp's serial input command allows for a time out (50 milliseconds in this case) so it is ok if the amplifier is not on, we'll just skip over any amplifier processing. If a message does come in, it is parsed and checked against the current antenna. Antenna change commands may be sent to the amplifier if need be at this point. Note that if you customize this code you will want to keep the processing inside the loop lightweight, because if too much is going on, you might miss a message from the amplifier. The Stamp does not do any buffering, so if it is not waiting for a message, it will be lost. '{ $STAMP BS2 } ' Automatic Antenna switch ' STAMP PIN MAP: ' Symbol PIN I/O Purpose RadBand VAR INA ' I (pins 0-3) Band-data (radio) ABCD TxInhPin CON 4 ' O TX-inhibit line - slaved from XmitOk UpBtnPin CON 6 ' O UP button DownBtnPin CON 7 ' O DOWN button LCD_PIN CON 11 ' O LCD communications LCD_BkLit CON 12 ' O Backlight control AmpSerIn CON 13 ' I Serial inbound comms from amplifier AmpSerOut CON 14 ' O Serial outbound comms to amplifier AntSerOut CON 15 ' O Serial outbound comms to antenna switch ' Define bands & antennas. ' Band names - define an 'array' of band names, indexed starting ' at 1. Band name strings must all be the same length. ' There is no 0 - it means radio is off! Bands DATA "160m" ' Band #1... Band1 DATA " 80m" DATA " 40m" DATA " 30m" DATA " 20m" DATA " 17m" DATA " 15m" DATA " 12m" DATA " 10m" ' Last band we care about DATA " UNK" ' These are bands not returned DATA " UNK" ' By the FT990. DATA " UNK" ' VHF/UHF bands?? DATA " LF" DATA " AM" MaxBands CON 9 ' We care about band #1-10 ' No 15! BandSize CON Band1 - Bands ' Size of each band entry LIST_END CON 255 ' Flag constant for begin/end of lists ' LIMIT: There shouldn't be more than 15 antennas - the list of memorized ' antennas is a nibble array (4 bits). ' PLUS, the ACOM 2000S/2000A only understand 10! ' Antenna name sizes all have to be the same! DATA LIST_END ' Beginning of list Antennas DATA 1,"N1217" Antenna1 DATA 3,"XM240" DATA 4,"C3-EU" LastAnt DATA 5,"C31XR" ' Last one always needs LastAnt! DATA LIST_END ' End of list AntSize CON Antenna1 - Antennas ' Size of each antenna entry ' Map bands to antennas. These are pairs: Band,Ant# ' Bands that are missing are not supported. ' List order is increasing. ' Band#LIST_END = end of list BandAnts DATA 3,3 ' 40m on XM240 DATA 5,4, 5,5 ' 20m on C3-EU & C31XR DATA 6,1 ' 17m on N1217 DATA 7,4, 7,5 ' 15m on C3-EU & C31XR DATA 8,1 ' 12m on N1217 DATA 9,4, 9,5 ' 10m on C3-EU & C31XR DATA LIST_END ' End of list, beginning of next list BandAntsSize CON 2 ' Size of each entry ' Antenna/Band state CurBand VAR NIB ' Currently selected band we're on CurAnt VAR NIB ' Current antenna we're using XmitOk VAR BIT ' Flag - ok to xmit on this antenna? ChgDir VAR BIT ' Direction something is changing: ' 1= forward, 0=backward LastAnts VAR NIB(MaxBands) ' List of last antennas used by band LastSegs VAR BYTE(MaxBands) ' List of last amp segments used by band ' Button-Support variables BtnPin VAR NIB ' Pin # for button to examine BtnPressed VAR BIT ' T/F: Button pressed BtnWork VAR BYTE ' BUTTON working variable ' Amp/Antenna switch support AcomNetAmp CON $41 ' ACOM-Net amplifier address AcomNetAnt CON $51 ' ACOM-Net selector address AcomNetUs CON $71 ' ACOM-Net 'PC controller' address (us) N1200 CON 813 ' 1200 baud, no parity, 8 bits, 1 stop, TRUE ' 17197 works for direct (non-driven) AmpSegText VAR BYTE(2) ' 'Encrypted' amplifier segment AmpSegAnt VAR NIB ' Current antenna for a segment Segment VAR BYTE ' Current amp segment SegNibHi VAR Segment.HIGHNIB SegNibLo VAR Segment.LOWNIB ' LCD parameters BkLitTimer VAR BYTE ' Countdown for LCD backlight BkLitTime CON 100 ' 'Countdown' starter (~4 seconds) ' General-purpose; clobbered by many subs :) Addr VAR WORD ' EEPROM address for READing data. AddrByte VAR BYTE ' Value read from Addr AddrLookup VAR NIB ' Something to look for AddrChgDir VAR BIT ' Direction to move for NextEntry AddrDelta VAR NIB ' Size of each entry for NextEntry bGenFlag VAR BIT ' General true/false flag ' Pause to let LCD start up (1s total) PAUSE 1000 ' All pins default to input - set some to output OUTPUT TxInhPin ' CurAnt starts out at 0 ' Is the radio turned on? If not, RadBand will also be 0 RadioBandChanged: ' The radio was tuned to a different band! ' Do something for CurBand = 0? Radio was turned off! CurBand = RadBand GOSUB AntennaForBand FinishAntOrBandChange: GOSUB SendAntCmd GOSUB UpdateDisplay ' Loop forever... Loop: ' Check 'UP' button: BtnPin = UpBtnPin GOSUB CheckButton IF BtnPressed THEN UpButtonPressed ' Check 'DOWN' button: BtnPin = DownBtnPin GOSUB CheckButton IF BtnPressed THEN DownButtonPressed ' Band change? IF (RadBand <> CurBand) THEN RadioBandChanged ' Backlight need attention? GOSUB BackLightCountdown ' Skip all this if the radio is off - it is unlikley the ' amp would be sending us any info at this point, but it ' would only be messed up by a bogus CurBand IF (CurBand = 0) THEN Loop ' Check to see if the amp is broadcasting a 'W1' to announce ' a segment change. Back to Loop if we don't see it. ' Try for 50ms - wait too long and the buttons are sluggish. ' Wait to little and we miss it! SERIN AmpSerIn, N1200, 50, Loop, [WAIT(AcomNetAmp), WAIT("W1"), STR AmpSegText\2, DEC1 AmpSegAnt] ' If we got here there was something to see! ' Decode the current segment GOSUB AmpSegTextToSegment ' Is this segment sane for our band? GOSUB CheckAmpSegmentForBand IF (bGenFlag = 0) THEN SkipSaveSegmentForBand ' Save this segment for this band LastSegs(CurBand - 1) = Segment SkipSaveSegmentForBand: ' Is the amp using the antenna we want? IF (AmpSegAnt = CurAnt) THEN Loop ' Need to send antenna change command GOSUB SendAmpCmd ' Back to the loop... GOTO Loop UpButtonPressed: ' UP button pressed! ChgDir = 1 GOTO FinishButtonPress DownButtonPressed: ' DOWN button pressed! ChgDir = 0 FinishButtonPress: ' Validate new antenna GOSUB ChangeAntenna GOTO FinishAntOrBandChange ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ChangeAntenna: ' Move CurAnt one slot in (ChgDir) direction. ' Make sure it is valid by: ' Wrapping around if we go below or above the list ' Move up or down if we select a 'hole' ' Set XmitOk according to the new antenna's relationship to ' CurBand. ' IN Parameters: ' ChgDir = Direction to change antenna (0=down, 1=up). ' CurAnt = Currently selected antenna. ' CurBand = Currently selected band. ' OUT Parameters: ' CurAnt = Newly selected antenna, corrected. ' XmitOk = 0/1 - ok to xmit on this antenna on this band? ' USES Variables: ' Addr = Assorted EEPROM addresses. ' AddrByte = Value read from Addr. ' AddrLookup = Antenna to search for in Antennas list ' AddrDelta = AntSize ' Get entry for CurAnt - if CurAnt is 0, start at the first one! Addr = Antennas IF (CurAnt = 0) THEN ChangeAntenna_Move AddrLookup = CurAnt AddrDelta = AntSize GOSUB LookupEntry ' Addr shouldn't ever be -1 for CurAnt! ChangeAntenna_Move: ' Move to the next entry in the right direction AddrChgDir = ChgDir GOSUB NextEntry IF (Addr <> -1) THEN ChangeAntenna_GotIt ' We fell off the list - need to 'wrap' ' Which direction are we changing? IF ChgDir THEN ChangeAntenna_WrapToFirst ' Get the last entry Addr = LastAnt GOTO ChangeAntenna_GotIt ChangeAntenna_WrapToFirst: ' Get the first entry Addr = Antennas ChangeAntenna_GotIt: ' Addr points to the antenna entry we want! READ Addr, CurAnt ' Look for this antenna in BandAnts to see if our band is listed Addr = BandAnts AddrLookup = CurBand AddrDelta = BandAntsSize GOSUB LookupEntry ' Addr shouldn't ever be -1 for CurBand in BandAnts! ' Assume combination is no good XmitOk = 0 ' Loop looking for this antenna ChangeAntenna_Loop: READ Addr + 1, AddrByte IF (AddrByte = CurAnt) THEN ChangeAntenna_XmitOk ' Next entry - still on our band? GOSUB NextEntry ' AddrChgDir set by LookupEntry! IF (Addr = -1) THEN ChangeAntenna_Exit READ Addr, AddrByte IF AddrByte = CurBand THEN ChangeAntenna_Loop ' Ran out of our band! ChangeAntenna_Exit: ' Return w/XmitOK = 0 RETURN ChangeAntenna_XmitOk: ' Band and antenna are ok! Remember this as the last one... XmitOk = 1 LastAnts(CurBand - 1) = CurAnt RETURN ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' SendAntCmd: ' Send 'change antenna' command to selector. ' Set or clear transmit-inhibit line according to XmitOk flag. ' The 'tx-inhibit' signals from the switch and/or amplifier are ' connected to the emitter of an NPN transistor. LINEAR or ' PIN 8 from the radio's band-data plug is connected to the ' collector. Pin TxInhPin is connected to the base. ' When TxInhPin is high, whatever setting the amp/switch have ' is passed onto the radio. This means _we_ think the antenna ' is ok, so any other reason NOT to transmit comes from them. ' If TxInhPin is low, we don't want the radio to transmit no ' matter what the amp/switch think, so we block their signal. ' Once we tell the switch about it, see if we need to do the ' same with the amplifier. ' IN Parameters: ' CurAnt = Antenna # to set. ' AntSerOut = Constant pin# to communicate w/switch ' AcomNetAnt = Constant 'network' address of antenna switch ' AcomNetUs = Constant 'network' address of 'us' ' XmitOk = Flag for xmit inhibit line. ' TxInhPin = Constant pin# to enable/disable tx ' OUT Parameters: ' None. ' USES Variables: ' None. SEROUT AntSerOut, N1200, [AcomNetAnt, AcomNetUs, "W3", $30 + CurAnt, 0] OUTS.LOWBIT(TxInhPin) = XmitOk ' Fall thru to send amp command if we need to ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' SendAmpCmdIfNeeded: ' We changed antennas. See if the amplifier is in a segment in ' our band, and if so, change its antenna. Otherwise, we'll get ' the chance to change the antenna the next time it 'autotunes'. ' IN Parameters: ' CurAnt = Antenna # to set. ' AmpSerOut = Constant pin# to communicate out to amp ' AmpSerIn = Constant pin# to communicate in from amp ' AcomNetAmp = Constant 'network' address of amplifier ' AcomNetUs = Constant 'network' address of 'us' ' OUT Parameters: ' None. ' USES Variables: ' AddrByte = Lookup band segment ' Ask the amp for the current seg# SEROUT AmpSerOut, N1200, [AcomNetAmp, AcomNetUs, "W7", 0] ' Wait 200ms for the answer. If we don't get one, no sense ' in doing any more. Answer will look like 'XYW1ssaub' where: ' X = Our network address ' Y = Amp's network address ' ss = Funky seg # ' a = Antenna number ' u = 0 for DEF, 1 for USR ' b = 'SubBand' ' We really only care about the 'ss' & 'a' so skip the rest SERIN AmpSerIn, N1200, 200, SendAmpCmdIfNeeded_NotNeeded, [WAIT("W1"), STR AmpSegText\2, DEC1 AmpSegAnt] ' Decode the segment # & see if it makes sense for this band GOSUB AmpSegTextToSegment GOSUB CheckAmpSegmentForBand IF (bGenFlag) THEN SendAmpCmdIfNeeded_AmpSegmentOk ' The segment is outside of the band ' Have we saved a segment for this band before? ' If so, go to it IF (LastSegs(CurBand - 1) <> 0) THEN SendAmpCmd ' We are outside the band, and we don't have a segment to ' recall, so don't do anything. GOTO SendAmpCmdIfNeeded_NotNeeded SendAmpCmdIfNeeded_AmpSegmentOk: ' Ok, we're in the band. Now see if the antennas differ IF (CurAnt <> AmpSegAnt) THEN SendAmpCmd SendAmpCmdIfNeeded_NotNeeded: ' If we get here no command is needed RETURN ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' SendAmpCmd: ' Send 'change antenna' command(s) to amplifier. ' IN Parameters: ' CurAnt = Antenna # to set. ' AmpSerOut = Constant pin# to communicate out to w/amp ' AcomNetAmp = Constant 'network' address of amplifier ' AcomNetUs = Constant 'network' address of 'us' ' OUT Parameters: ' None. ' USES Variables: ' None. ' Bail if CurBand is 0 or we can't xmit IF (CurBand = 0) THEN SendAmpCmd_Done IF (XmitOk = 0) THEN SendAmpCmd_Done ' Are we sending a segment too? IF (LastSegs(CurBand - 1) <> 0) THEN SendAmpCmd_SegmentCmd ' This the same as the command sent to the switch! SEROUT AmpSerOut, N1200, [AcomNetAmp, AcomNetUs, "W3", $30 + CurAnt, 0] GOTO SendAmpCmd_Done SendAmpCmd_SegmentCmd: ' Send segment with antenna Segment = LastSegs(CurBand - 1) GOSUB SegmentToAmpSegText SEROUT AmpSerOut, N1200, [AcomNetAmp, AcomNetUs, "W1", STR AmpSegText\2, $30 + CurAnt, 0] SendAmpCmd_Done: RETURN ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' CheckAmpSegmentForBand: ' Check to see if (Segment) makes sense for CurBand. ' Return 1 or 0 in bGenFlag ' IN Parameters: ' Segment = Current amp segment # ' CurBand = Current radio band ' OUT Parameters: ' bGenFlag = 1=Segment sane ' USES Variables: ' AddrByte = Lookup band segment bGenFlag = 0 ' Check the low-end of our current segment AddrByte = 0 ' Bands: 160 80 40 30 20 17 15 12 10 LOOKUP CurBand, [0,2,43,93,123,163,193,213,231,243], AddrByte IF (AddrByte = 0) THEN CheckAmpSegmentForBand_Return ' Are we in the ballpark? IF (Segment < AddrByte) THEN CheckAmpSegmentForBand_Return ' Ok so far - Check the high-end AddrByte = 0 ' Bands: 160 80 40 30 20 17 15 12 10 LOOKUP CurBand, [0,9,52,95,124,166,194,215,231,249], AddrByte IF (Segment > AddrByte) THEN CheckAmpSegmentForBand_Return ' Segment checks out - ok for this band! bGenFlag = 1 CheckAmpSegmentForBand_Return: RETURN ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' AmpSegTextToSegment: ' Translate 2-byte AmpSegText read from amplifier into Segment ' byte. ' IN Parameters: ' AmpSegText = 2-byte segment text read from amplifier. ' OUT Parameters: ' Segment = 1-byte segment number. ' USES Variables: ' None. SegNibHi = AmpSegText(0) - $30 SegNibLo = AmpSegText(1) - $30 RETURN ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' SegmentToAmpSegText: ' Translate Segment byte into 2-byte AmpSegText ready to send to ' amplifier. ' IN Parameters: ' Segment = 1-byte segment number. ' OUT Parameters: ' AmpSegText = 2-byte segment text read from amplifier. ' USES Variables: ' None. AmpSegText(0) = SegNibHi + $30 AmpSegText(1) = SegNibLo + $30 RETURN ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' UpdateDisplay: ' Update the LCD with the current information ' IN Parameters: ' None. ' OUT Parameters: ' None. ' USES Variables: ' Addr = Assorted EEPROM addresses. ' AddrByte = Value read from Addr. ' AddrLookup = Value to find in list at Addr. ' AddrDelta = Size of entries in lookup lists ' LCD constants N9600 CON $4054 LCD_IPfx CON 254 ' Special command prefix LCD_CLR CON 1 ' Clear screen LCD_CUR_INV CON 12 ' Invisible cursor LCD_CUR_BLK CON 13 ' Blinking cursor LCD_ARROW CON 126 ' Arrow symbol LCD_1ST_LINE CON 128 ' Addr of first line LCD_2ND_LINE CON 192 ' Addr of 2nd line ' Clear screen SEROUT LCD_PIN, N9600, [LCD_IPfx, LCD_CLR] PAUSE 1 ' Clear screen needs a pause ' Clear cursor SEROUT LCD_PIN, N9600, [LCD_IPfx, LCD_CUR_INV] ' Turn on backlight GOSUB BackLightOn ' Is the radio on? IF (CurBand <> 0) THEN UpdateDisplay_Band ' Radio is OFF! ' Move to line 2 for the message... SEROUT LCD_PIN, N9600, [LCD_IPfx, LCD_2ND_LINE, "Radio is OFF"] ' Back to line 1 for the band SEROUT LCD_PIN, N9600, [LCD_IPfx, LCD_1ST_LINE, "NONE"] GOTO UpdateDisplay_Sep UpdateDisplay_Band: ' Display Band - order of math is important... Addr = (CurBand - 1) * BandSize + Bands AddrDelta = BandSize GOSUB TextToLCD UpdateDisplay_Sep: ' Display seperator SEROUT LCD_PIN, N9600, [" ", LCD_ARROW, " "] UpdateDisplay_Antenna: ' Display Antenna - any set? IF (CurAnt <> 0) THEN UpdateDisplay_DispAnt SEROUT LCD_PIN, N9600, ["None"] GOTO UpdateDisplay_XmitFlag UpdateDisplay_DispAnt: SEROUT LCD_PIN, N9600, [DEC CurAnt, "="] Addr = Antennas AddrLookup = CurAnt AddrDelta = AntSize GOSUB LookupEntry ' Check for Addr = -1? Addr = Addr + 1 AddrDelta = AntSize - 1 GOSUB TextToLCD UpdateDisplay_XmitFlag: ' Do we need the blinking cursor for no xmit? IF XmitOk THEN UpdateDisplay_Exit ' Put blinking cursor on top of arrow SEROUT LCD_PIN, N9600, [LCD_IPfx, LCD_1ST_LINE + BandSize + 1, LCD_IPfx, LCD_CUR_BLK] UpdateDisplay_Exit: RETURN ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' BackLightOn: ' Turn on the LCD backlight and start the 'timer' ' IN Parameters: ' None. ' OUT Parameters: ' BkLitTimer set to begin countdown ' USES Variables: ' None HIGH LCD_BkLit BkLitTimer = BkLitTime RETURN ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' BackLightCountdown: ' See if the backlight needs to be turned off ' IN Parameters: ' BkLitTimer - countdown. Backlight is on if this is > 0. ' OUT Parameters: ' None ' USES Variables: ' BkLitTimer ' Is the light even on? IF (BkLitTimer = 0) THEN BackLightCountdown_Exit ' Decrement and check - time to turn it off? BkLitTimer = BkLitTimer - 1 IF (BkLitTimer > 0) THEN BackLightCountdown_Exit LOW LCD_BkLit BackLightCountdown_Exit: RETURN ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' TextToLCD: ' Given text at Addr, send it to the LCD until 0 is found or ' we've displayed AddrDelta characters, whichever comes first. ' IN Parameters: ' Addr = EEPROM address of beginning of text. ' AddrDelta = # of characters to display. CLOBBERED! ' OUT Parameters: ' None. ' USES Variables: ' Addr ' AddrByte = Value read from EEPROM. TextToLCD_Loop: READ Addr, AddrByte ' End of text? IF (AddrByte = 0) THEN TextToLCD_Done ' No - send char SEROUT LCD_PIN, N9600, [AddrByte] Addr = Addr + 1 AddrDelta = AddrDelta - 1 IF (AddrDelta > 0) THEN TextToLCD_Loop TextToLCD_Done: ' All done! RETURN ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' AntennaForBand: ' Given CurBand, lookup the last used antenna for this ' band. Return it in CurAnt. ' IN Parameters: ' CurBand = Band for which to look up antenna. ' OUT Parameters: ' CurAnt = Last antenna used on CurBand. ' USES Variables: ' Addr = EEPROM address. ' AddrByte = Value read from EEPROM. Addr = BandAnts ' Assume failure XmitOk = 0 ' Look for first ocurrance of CurBand. AntennaForBand_Loop READ Addr, AddrByte ' End of list? If so, return unchanged IF (AddrByte = LIST_END) THEN AntennaForBand_Return IF (AddrByte = CurBand) THEN AntennaForBand_FoundFirst ' Not found yet - bump to next Band,Ant pair Addr = Addr + BandAntsSize GOTO AntennaForBand_Loop AntennaForBand_FoundFirst: ' Found the first match for this band XmitOk = 1 ' Have we remembered an antenna on this band? IF (LastAnts(CurBand - 1) = 0) THEN AntennaForBand_UseFirst ' We've remembered one - use it! CurAnt = LastAnts(CurBand - 1) RETURN AntennaForBand_UseFirst: ' Use Addr's antenna - bump one to look at antenna# Addr = Addr + 1 READ Addr, CurAnt ' Remember it! LastAnts(CurBand - 1) = CurAnt AntennaForBand_Return: ' Return CurAnt to caller RETURN ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' NextEntry: ' Addr points to an entry in a list like this: ' #,"text" ' ... ' LIST_END ' AddrChgDir is the direction to go to find the next entry. ' If we go off the end of the list, Addr will be -1. ' Otherwise, it will point to the next entry in that direction. ' IN Parameters: ' Addr = Address to move from. ' AddrChgDir = Direction to move (1=UP, 0=DOWN). ' AddrDelta = Size of each entry ' OUT Parameters: ' Addr = Address of next # or -1 if we fell off the list. ' USES Variables: ' AddrByte = Value read from Addr. ' Which direction are we going? IF AddrChgDir THEN NextEntry_UP ' Move DOWN ' See is the prev spot is LIST_END READ Addr - 1, AddrByte IF (AddrByte = LIST_END) THEN NextEntry_AtEnd ' Go ahead and move DOWN Addr = Addr - AddrDelta RETURN NextEntry_UP: ' Move UP Addr = Addr + AddrDelta ' See if we fell off the list READ Addr, AddrByte IF (AddrByte <> LIST_END) THEN NextEntry_Exit NextEntry_AtEnd: ' Flag the end! Addr = -1 NextEntry_Exit: RETURN ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' LookupEntry: ' Addr points to the beginning of a list like this: ' #,"text" ' ... ' LIST_END ' AddrLookup is the # to look for. If found, Addr will point to ' the byte containing # matching AddrLookup. If not, Addr will be ' -1. ' IN Parameters: ' Addr = EEPROM address to start search. ' AddrLookup = # to look for on list. ' AddrDelta = Size of each entry ' OUT Parameters: ' Addr = Address of # or -1 if not found. ' USES Variables: ' AddrByte = Value read from Addr. ' Tell NextEntry which way to move AddrChgDir = 1 LookupEntry_Loop: READ Addr, AddrByte ' Found ours? IF (AddrByte = AddrLookup) THEN LookupEntry_Found ' Not this one - Move on to the next entry GOSUB NextEntry IF (Addr <> -1) THEN LookupEntry_Loop ' Not found - Fall thru with Addr = -1 LookupEntry_Found: RETURN ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' CheckButton: ' See if a button was pressed, and if so, loop until it is ' released so that it is 'one event'. Note that this will ' consume as much time as it takes for the user to release ' the button, once pressed. ' NOTE: This works for 'pull-down' button - 'ON' = 0 ' Because that sort of circuit is recommended in Edwards' book. ' IN parameters: ' BtnPin = Pin# to poll ' OUT parameters: ' BtnPressed = 1 if pressed, 0 otherwise ' USES Variables: ' BtnWork BtnWork = 0 ' 'Down' state is 0 (pull-up), debounce but no autorepeat BUTTON BtnPin, 0, 255, 0, BtnWork, 1, CheckButton_Pressed ' Button not pressed BtnPressed = 0 RETURN CheckButton_Pressed: ' Button WAS pressed - loop until it is released IF INS.LOWBIT(BtnPin) = 0 THEN CheckButton_Pressed ' Button has been released BtnPressed = 1 RETURN