Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

ASM: Cure a 202 Warning - Argument out of range. Least significant bits used.

augustinetez

Active Member
This is more me being OCD rather than something not working (for a change :D ).

I found the following macro in Ron Kreymborgs 32-bit Binary to BCD to ASCII routines which will be quite useful in something I'm playing with at the moment.

It works fine, but gives the '(202) Argument out of range. Least significant bits used' warning at the points marked in the listing.

Anyone see a way of curing that?

Code:
number    equ 123456789

load32    macro    arg1,arg2
    movlw    arg1 >> 24
    movwf    arg2
    movlw    arg1 >> 16    ; Warning (202) Argument out of range.  Least significant bits used.
    movwf    arg2+1
    movlw    arg1 >> 8    ; Warning (202) Argument out of range.  Least significant bits used.
    movwf    arg2+2
    movlw    arg1        ; Warning (202) Argument out of range.  Least significant bits used.
    movwf    arg2+3
    endm

    CBLOCK    0x0c
    bin:4        ; 32-bit binary number (unsigned)
    bcd:10        ; 10 BC digits or 10 ascii chars
    pti,pto        ; pointers
    ii
    temp
    cnt
    ENDC
    
    load32    number,bin    ; load test value (number)
 
Would an AND 0xff fix it?
I.E. movlw (arg1>>24)&0xff

Might be completely wrong as it's many years since I did asm.

Mike.
 
Worked, just need to try it with a random selection of numbers to make sure it didn't introduce a different problem.

Code:
load32    macro    arg1,arg2
    movlw    arg1 >> 24
    movwf    arg2
    movlw    (arg1&0xff0000)>>16
    movwf    arg2+1
    movlw    (arg1&0xff00) >> 8
    movwf    arg2+2
    movlw    (arg1&0xff)
    movwf    arg2+3
    endm
 
Ran a stack of the numbers I know I will be using and all good.

Thanks Mike.
I presume you are aware that adding the extra instructions will make the routine slightly larger and slower?, I imagine the original author deliberately wrote it that way to make it as small and fast as possible. It's just a warning, not an error, and it's there to let you know what's happening, so you can confirm that's what you were trying to do.

It will make no difference to the routine, other than very slightly decreasing performance.
 
I presume you are aware that adding the extra instructions will make the routine slightly larger and slower?, I imagine the original author deliberately wrote it that way to make it as small and fast as possible. It's just a warning, not an error, and it's there to let you know what's happening, so you can confirm that's what you were trying to do.

It will make no difference to the routine, other than very slightly decreasing performance.
There is no extra instructions. It's loading a literal value. Seems you're forgetting your asm upbringing.:)

Mike.
 
A slower response would definitely have been a problem as I have either 2 or up to 22 compares to do.

If that didn't make sense here's the pseudo code - numbers are frequency in MHz:-

Code:
is freq > 52.000        ; Is freq above top limit
    yes retlw 0        ; 0 = error/out of range, other #'s = table entry reference
no
is freq < 1.810            ; Is freq below bottom limit
    yes retlw 0
no
is freq >= 50.000 & <= 52.000    ; Is freq in this band
    yes retlw 7
no
is freq >= 28.000 & <= 29.700    ; Is freq in this band
    yes retlw 6
no
is freq >= 24.890 & <= 24.990    ; Is freq in this band
    yes retlw 6
no
is freq >= 21.000 & <= 21.450    ; Is freq in this band
    yes retlw 5
no
is freq >= 18.068 & <= 18.168    ; Is freq in this band
    yes retlw 5
no
is freq >= 14.000 & <= 14.350    ; Is freq in this band
    yes retlw 4
no
is freq >= 10.100 & <= 10.150    ; Is freq in this band
    yes retlw 4
no
is freq >= 7.000 & <= 7.200    ; Is freq in this band
    yes retlw 3
no
is freq >= 3.500 & <= 3.800    ; Is freq in this band
    yes retlw 2
no
is freq >= 1.810 & <= 2.000    ; Is freq in this band
    yes retlw 1
no
    retlw 0            ; Freq does not match any of the above
 
slower response would definitely have been a problem as I have either 2 or up to 22 compares to do.

Use a binary tree style comparison - above or below centre of the possible ranges to two different sequences, using the lower frequency value of the upper choice.

And again in each of those, keep halving the number and branching as appropriate.

Five comparisons gives up to 32 selections (or 8 comparisons for 256 etc., 2^n).

At each end branch end, you need one more comparison to verify the upper limit for that band.

No more than six comparisons for any band result.
 
Think I learned that as the "Newton Raphson" method. Yes? Seems kinda obvious now but at the time, in BC (Before Computers) it was pretty amazing.
It was over 40 years ago so I could easily be mistaken.

Mike.
 
I did look at that last night, but the brain was so tired it refused to understand the bit after 'Use...' :sorry:

One thing that does need to happen is that if the frequency is outside of the set bands, an error code is returned and the whole process starts again - > measure frequency, compare to get a correct band, set appropriate output.

This is part of a request to update my Frequency Dependent Switch project on my website with better precision frequency switching points.
 
This is part of a request to update my Frequency Dependent Switch project on my website with better precision frequency switching points.
Got a link? I'd love to see your project. I designed a programmable antenna switch that listened to frequency change broadcasts over the serial CI/V interface from my ICOM 756PRO-II transeiver way back in 2005.

Antenna Switch.png
 
Last edited:
Had a day away from all this yesterday, finally got to bed last night and the brain decided it was going to decipher RJ's post.

I think I understand it properly as in compare against a frequency halfway between 1.8MHz and 52MHz, check if incoming frequency is above or below that point, and continue doing the same to narrow down to the final area the frequency is in and do final test to determine actual frequency band - yes?
 
I'm curious if you could reduce the number of range compares required for your project? In a very old project I compared the radio frequency to each entry in a 'range table' in EPROM (below) and output BCD 'band data' for a radio frequency less than the table enty. Would there be any advantage using the much broader frequency ranges in a table like this in your project?

Code:
;
;  CI-V to BCD Band Data Decoder 3-byte "memories" in EEPROM
;
;  Memory 00 contains the target radio CI-V address in byte
;  number 0 (a value of 00 = "any radio")
;
;  Memory 01 through 15 contain CI-V "Frequency-To-BCD" data
;  MegaHertz, KiloHertz (x10), and the BCD band data output
;
;  When a frequency record is received from the target radio
;  over the CI-V bus its 16-bit frequency (MHz and KHz x10)
;  is compared to the 16-bit frequency value in our memories
;
;
        org     h'2100'         ; 3-byte memories in eeprom

        de      0x00,0x00,0x00  ; target radio CI-V address
        de      0x03,0x40,0x01  ; 160m 00.000-03.399 (0001)
        de      0x05,0x00,0x02  ;  80m 03.400-04.999 (0010)
        de      0x06,0x90,0x02  ;  60m 05.000-06.899 (0010)
        de      0x10,0x00,0x03  ;  40m 06.900-09.999 (0011)
        de      0x13,0x90,0x04  ;  30m 10.000-13.899 (0100)
        de      0x17,0x97,0x05  ;  20m 13.900-17.969 (0101)
        de      0x20,0x90,0x06  ;  17m 17.970-20.899 (0110)
        de      0x24,0x79,0x07  ;  15m 29.900-24.789 (0111)
        de      0x27,0x90,0x08  ;  12m 24.790-27.899 (1000)
        de      0x49,0x90,0x09  ;  10m 27.900-49.899 (1001)
        de      0x60,0x10,0x0A  ;   6m 49.900-60.099 (1010)
        de      0x00,0x00,0x0B  ;
        de      0x00,0x00,0x0C  ;
        de      0x00,0x00,0x0D  ;
        de      0x00,0x00,0x0E  ;
EOMEM   equ     $-2100h
Code:
;
;  match 16-bit CI-V frequency (CIVMHZ and CIVKHZ) to a frequency
;  range in the data/eeprom "memories".  we have a range match
;  when the CI-V frequency is less than the "memory" frequency.
;
EVAL    movlw   h'03'           ; skip memory 00                  |B0
        movwf   ESR             ; index eeprom memory 01          |B0
EVTST   call    RD_EE           ; get MEMMHZ value                |B0
        incf    ESR,f           ;                                 |B0
        subwf   CIV_MHZ,W       ; subtract CIVMHZ value           |B0
        bnc     BANDTST         ; branch if CIVMHZ < MEMMHZ       |B0
        bnz     EVNXT           ; branch if CIVMHZ > MEMMHZ       |B0
        call    RD_EE           ; CIVMHZ = MEMMHZ, get MEMKHZ     |B0
        subwf   CIV_KHZ,W       ; subtract CIVKHZ value           |B0
        bnc     BANDTST         ; branch if CIVKHZ < MEMKHZ       |B0
EVNXT   incf    ESR,f           ; next memory address             |B0
        incf    ESR,f           ;                                 |B0
        movf    ESR,W           ;                                 |B0
        xorlw   EOMEM           ; last memory?                    |B0
        bnz     EVTST           ; no, evaluate another, else      |B0
        goto    NewRec          ; start over (no match)           |B0
;
;  exit if the newly decoded band is the same as the current
;  band, else update BAND variable and BCD band data output.
;
BANDTST incf    ESR,f           ; point to BCD data field         |B0
        call    RD_EE           ; get BCD band data value         |B0
        xorwf   BAND,W          ; same as current band?           |B0
        bz      NewRec          ; yes, exit & start over, else    |B0
        xorwf   BAND,f          ; save new band (01..15)          |B0
;
;  output BCD data on GP1 (A), GP2 (B), GP4 (C), and GP5 (D)
;
 
Last edited:
The request I received was to refine the switching points to be more precise frequency wise (I've done quite a few things for this person) but said person only has a very rudimentary grasp of PIC programming and he does like to fiddle, and I have no idea why he wants it to be more precise.

The original program is very broad as it uses a timing loop of 150μS which results in TMR0 holding a number between 1 & 17 for the range 1.810MHz to 52MHz which is the reference in to a table to set the output (1 of 8) or send back an error code and works well enough to my mind.

I should add he homebrews a lot of gear which is where this is being used.

So I need to keep this to a simple format that I can explain easily via email as we are a couple of continents apart.

On that basis, my current thinking is, having come across the macro that was the basis of this thread, I can at the head of the program use something like

Band1H equ 200000

Band1L equ 181000

and so on with the full list of frequencies as per my post #10 and use the macro to pull that list in to the compare routine one at a time. That way he can easily change the switching points.

The odd looking numbers are as a result of using a 10mS timing loop to measure the frequency, it measures to the nearest 100Hz.

If I went down RJ's route (post #11), I can see me getting questions of "what is this number for. It's not in the right band or any band" etc.

The other thing I will have to look at is the total time to do all the read/calculate process with possibly dropping back to a 1mS timing loop - I'm stuck with using a 16F628A rather than a faster PIC, as that is what he has.
 
If I went down RJ's route (post #11), I can see me getting questions of "what is this number for. It's not in the right band or any band" etc.

??? You would be using exactly the same numbers you are now!

Just the comparison order is optimised.
 

Latest threads

New Articles From Microcontroller Tips

Back
Top