Shop OBEX P1 Docs P2 Docs Learn Events
Address is not within lower half of memory page? — Parallax Forums

Address is not within lower half of memory page?

eagletalontimeagletalontim Posts: 1,399
edited 2008-11-16 21:38 in General Discussion
Ok, I am trying to get the digital tachometer working again but i have run into a few issues [noparse]:([/noparse] First, i keep getting the error Address 371 not within lower half of memory page. The error start when it tries to call the MEASURE_HI function. Second. I cannot add anymore variables because it says exceeds ram. Can anyone help clean this up a bit and possibly get it working [noparse]:)[/noparse]

DEVICE          SX28, OSCXT2, TURBO, STACKX, OPTIONX
FREQ            20_000_000
ID              "M-SEG"

RPM_signal    PIN     RC.0 INPUT
TRIS_disp    VAR    TRIS_B
display        VAR    RB
rpm        VAR     WORD
pWidth0        VAR     WORD
pWidth1        VAR     WORD
dividendMSW     VAR     WORD
dividendLSW    VAR     WORD
overflow    VAR     BIT
doneBit        VAR     BIT
digit1        VAR    WORD
currentrpm    VAR    WORD
tmpW1        VAR    WORD
flags        VAR    Byte
isrFlag        VAR    flags.0

INTERRUPT 100_000
  LOW RA.3
  digit1 = currentrpm / 100
  currentrpm = __REMAINDER
  READ SegMap + currentrpm, display
  HIGH RA.3
  LOW RA.2
  digit1 = digit1 / 10
  currentrpm = __REMAINDER
  READ SegMap + currentrpm, display
  HIGH RA.2
  LOW RA.1
  digit1 = digit1 / 10
  currentrpm = __REMAINDER
  READ SegMap + currentrpm, display
  HIGH RA.1
  RETURNINT

PROGRAM Start
MEASURE_LO    FUNC    2
MEASURE_HI    FUNC    2
delay    SUB    1, 2

Start:
  TRIS_disp = %00000000
  rpm = 1

Main:
    pWidth0 = MEASURE_LO
    pWidth1 = MEASURE_HI
'   PULSIN RPM_signal, 0, pWidth0
'   PULSIN RPM_signal, 1, pWidth1
    pWidth0 = pWidth0 + pWidth1
    pWidth0 = pWidth0 * 2
    dividendMSW = $005B
    dividendLSW = $8D80
    rpm = 1
    overflow = 0  
    DO
     doneBit = rpm.15
      rpm = rpm << 1
      IF overflow = 1 THEN
        rpm.0 = 1
        dividendMSW = dividendMSW - pWidth0
      ELSE
        IF dividendMSW >= pWidth0 THEN
          rpm.0 = 1
          dividendMSW = dividendMSW - pWidth0
        ENDIF
      ENDIF
      overflow = dividendMSW.15
      dividendMSW = dividendMSW << 1
      dividendMSW.0 = dividendLSW.15
      dividendLSW = dividendLSW << 1
    LOOP UNTIL doneBit = 1
    rpm = rpm << 1
    rpm.0 = overflow
    IF dividendMSW >= pWidth0 THEN
      rpm.0 = 1
    ENDIF
    currentrpm = rpm
  GOTO Main

SUB delay
    IF __PARAMCNT = 1 THEN   ' byte parameter?
      tmpW1 = __PARAM1
    ELSE
      tmpW1 = __WPARAM12
    ENDIF    
    pause tmpW1
    ENDSUB

FUNC MEASURE_HI
  tmpW1 = 0                    ' clear measurement
  ASM
    JB  RPM_Signal, $                ' wait for low
    JNB RPM_Signal, $                ' wait for 0 -> 1
  ENDASM
  DO WHILE RPM_signal = 1                ' loop while high
    ASM
      CLRB isrFlag                ' clear flag
      JNB  isrFlag, $                ' wait for next
    ENDASM
    INC tmpW1                    ' update timing
    IF tmpW1 = 0 THEN EXIT               ' abort on roll-over
  LOOP
  RETURN tmpW1
  ENDFUNC

FUNC MEASURE_LO
  tmpW1 = 0                    ' clear measurement
  ASM
    JNB RPM_Signal, $                ' wait for high
    JB  RPM_Signal, $                ' wait for 1 -> 0
  ENDASM
  DO WHILE RPM_Signal = 0                ' loop while low
    ASM
      CLRB isrFlag                ' clear flag
      JNB  isrFlag, $                ' wait for next
    ENDASM
    INC tmpW1                    ' update timing
    IF tmpW1 = 0 THEN EXIT               ' abort on roll-over
  LOOP
  RETURN tmpW1
  ENDFUNC

SegMap:                                         ' segments maps
  DATA  %00111111                               ' 0
  DATA  %00000110                               ' 1
  DATA  %01011011                               ' 2
  DATA  %01001111                               ' 3
  DATA  %01100110                               ' 4
  DATA  %01101101                               ' 5
  DATA  %01111101                               ' 6
  DATA  %00000111                               ' 7
  DATA  %01111111                               ' 8
  DATA  %01100111                               ' 9

Comments

  • ZootZoot Posts: 2,227
    edited 2008-11-16 20:22
    Your ISR which uses lots of division is probably pushing the sub/func declarations past address $100 -- the declarations must be in the "lower half" of a memory page; i.e. $000-$0FF. The easiest way to ensure this is to move your ISR to the end of your program with a jump -- this way the code that follows, the sub/func declarations will be in the right spot... this can also make the program a bit easier to read... i.e.

    INTERRUPT 100_000
    GOTO Interrupt _Handler ' jump to where the ISR really is
    
    PROGRAM Start
    MEASURE_LO    FUNC    2
    MEASURE_HI    FUNC    2
    delay    SUB    1, 2
    
    Start:
      TRIS_disp = %00000000
      rpm = 1
    
    Main:
      ' lots more code
    
    Subroutine_And_Functions:
    
    Interrupt_Handler:
      LOW RA.3
      digit1 = currentrpm / 100
      currentrpm = __REMAINDER
      READ SegMap + currentrpm, display
      HIGH RA.3
      LOW RA.2
      digit1 = digit1 / 10
      currentrpm = __REMAINDER
      READ SegMap + currentrpm, display
      HIGH RA.2
      LOW RA.1
      digit1 = digit1 / 10
      currentrpm = __REMAINDER
      READ SegMap + currentrpm, display
      HIGH RA.1
      RETURNINT
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST

    1uffakind.com/robots/povBitMapBuilder.php
    1uffakind.com/robots/resistorLadder.php
  • JonnyMacJonnyMac Posts: 9,214
    edited 2008-11-16 21:38
    Zoot's right -- and you certainly don't need to update your display 100_000 times per second. You should explode out the digits when you re-calculate RPM and let the IS simply display them. The Clock/Timer example in the SX/B Help file does.
Sign In or Register to comment.