Menu

Counting problem

Help
Willem
2023-11-04
2024-04-13
  • Willem

    Willem - 2023-11-04

    Can someone please translate this PICbasic code into GCB code;
    COUNT Portb.2, 100, W1 'Count pulses on pin B.2 in 100 milliseconds
    Thank you very much.

     
  • Willem

    Willem - 2023-11-07

    Hi Anobium, Thanks for the fast answer, but Pulsein is not the right thing , it gives you time duration of pulse in, I would like to count the number of in coming pulses on a pin , like number of pulses per a time frame, exactly like Picbasic does it.:
    COUNT Portb.2, 100, W1 'Count pulses on pin B.2 in 100 milliseconds
    Thanks
    Willem

     
  • Willem

    Willem - 2023-11-08

    Wow, I can not believe that it must be so difficult, I only need to count a few positive going pulses on a pin coming from a button being pressed a few times??

    Willem

     
  • Anobium

    Anobium - 2023-11-08

    COUNT in PICBASIC code may have implementation that uses or does not use timers.

    Do you have any ASM from PICBASIC with COUNT() implemented ?


    Meanwhile... use millis(). Millis() counts 1ms, so, you need 100 ms. Then, count the transistion/pulses during that 100 ms.

    There are many demos for the implementation of millis().

    
    
     
  • Anobium

    Anobium - 2023-11-10

    Does anyone know the PICBASIC implementation in terms of Count(). Does it use a timer? is it blocking or non-blocking? Is it a macro or library function ?

    The documentation, shown below, does not provide me many clues to the implementation.

    An ASM or LST file from a PICBASIC project would tell me definitively how this is implemented.


    PICBASIC PRO Compiler REFERENCE MANUAL
    COUNT
    
    COUNT Pin, Period, Var 
    Count the number of pulses that occur on Pin during the Period and stores the 
    result in Var. Pin is automatically made an input. Pin may be a constant, 0-15, or a 
    variable that contains a number 0-15 (e.g. B0) or a pin name (e.g. PORTA.0). 
    The resolution of Period is in milliseconds. It tracks the oscillator frequency based 
    on the DEFINEd OSC. 
    COUNT checks the state of Pin in a tight loop and counts the low to high 
    transitions. With a 4MHz oscillator it checks the pin state every 20us. With a 
    20MHz oscillator it checks the pin state every 4us. From this, it can be determined 
    that the highest frequency of pulses that can be counted is 25KHz with a 4MHz 
    oscillator and 125KHz with a 20MHz oscillator, if the frequency has a 50% duty 
    cycle (the high time is the same as the low time). 
    ' Count # of pulses on Pin1 in 100 milliseconds
    COUNT PORTB.1,100,W1 
    ' Determine frequency on a pin
    COUNT PORTA.2, 1000, W1 ' Count for 1 second
    Serout PORTB.0,N2400,[W1]
    

    The GCBASIC can support Count() using many methods. These include use a timer (could be an issue with some timer constrained chips [ how did PICBASIC handle this ? ], use a sub routine and a set of macros that examine the clock frequency and simply uses a wait() but this would be a blocking command, or, a method to estimate the sample period for a given number of clock cycles.

    GCBASIC does need a new capability with respect to this type of 'action'. Hugh and I spoke of a do while timer_period_not_expired loop. The intent could be independent of the timers and would be a calculation of the instructions within the do-loop.

    This could take some time to develop, so, I could implement simple function using a script and a macro. This would be timer independent. This would use the same approach as the url in @mmotte's post.


    Your thoughts please.

     
  • Willem

    Willem - 2023-11-10

    Thank you very much Anobium, I really appreciate all the effort to help me . I shall wait for the development, unfortunately with my limited knowledge of programing, I shall not be of any help

    Willem

     
  • Jerry Messina

    Jerry Messina - 2023-11-10

    Here's the PBP implementation of Count() for an 18FxxQ43... it just counts transitions for the specified time period.

    There's a little more to it ( reg definitions, front-end parameter manipulation to set the "registers". etc), but it should be enough to give you a clue. If not, let me know...

    ;****************************************************************
    ;* COUNT      : Count pulses on a pin                           *
    ;*                                                              *
    ;* Input      : RM1, W = bit mask or W = pin                    *
    ;*            : RS1, RR1 = port                                 *
    ;*            : R1 = period                                     *
    ;* Output     : R1, W = count                                   *
    ;*                                                              *
    ;* Notes      :                                                 *
    ;****************************************************************
    
        ifdef COUNT_USED
    COUNT
        call    PINR1           ; Convert pin to FSR and bit mask
    PINR1_USED = 1
    COUNTT_USED = 1
        endif
    
        ifdef COUNTT_USED
          if (OSC == 3)
    COUNT_DELAY = 45
          else
    COUNT_DELAY = (50 * (OSC)) / 4
          endif
    COUNTT
            MOVE?FF   RS1, FSR0H      ; Point to TRIS
            movf    RR1, W
            addlw   DD_OFFSET
            movwf   FSR0L
            movf    RM1, W          ; Get bit mask
            iorwf   INDF0, F        ; Set pin to input
            MOVE?FF   RR1, FSR0L      ; Point back to port
            movlw   low (COUNT_DELAY)       ; Calculate count time based on OSC
            movwf   R3
            movlw   (COUNT_DELAY) >> 8
            movwf   R3 + 1
            call    MUL             ; Time is R0 + 1, R0, R2 + 1, R2 (hi to lo)
            clrf    R1              ; Zero count
            clrf    R1 + 1
            movf    INDF0, W        ; Read pin
            andwf   RM1, W          ; Isolate it
            movwf   R3              ; Save starting state as last
    countloop 
            CLRWDT?NOP        ; 1 (20) Keep Watchdog happy
            bra    $ + 2        ; 2 Waste some time
            movf    INDF0, W        ; 1 Read pin
            andwf   RM1, W          ; 1 Isolate it
            xorwf    RM1, W        ; 1 Only count low to high transitions
            iorwf    R3, F        ; 1 Compare with last time
            btfsc   STATUS, Z       ; 1 / 2
            incf    R1, F           ; 1 / 0 Count pulse
            btfsc   STATUS, Z       ; 1 / 2
            incf    R1 + 1, F       ; 1 / 0
            xorwf    RM1, W        ; 1 Flip current state back
            movwf   R3              ; 1 Save as new last state
            clrf    WREG        ; 1 Count time
            decf    R2, F           ; 1
            subwfb    R2 + 1, F    ; 1
            subwfb    R0, F        ; 1
            subwfb    R0 + 1, F    ; 1
            bc    countloop    ; 2
            movf    R1, W           ; Result to W
            goto    DUNN        ; exit
    DUNN_USED = 1
    MUL_USED = 1
        endif
    
     
  • Willem

    Willem - 2023-11-10

    Hi Jerry, thanks but ASM is almost like English to me, like Greek man, but I am sure Anobium can make something of it.
    Thanks for the help

    Willem

     
    • Anobium

      Anobium - 2023-11-10

      @Williem.

      I will create a new function asap.

      Watch this space over the weekend.


      I will guess what OSC=3 means in the PHP example.

       
  • Anobium

    Anobium - 2023-11-10

    @JerryM

    That helps. It tells me.... It is rough calculation ( not timer based, or interrupt based ), it is using a script to do some calcs.

    Question. OSC == 3

    ~~~
    if (OSC == 3)
    COUNT_DELAY = 45
    else
    COUNT_DELAY = (50 * (OSC)) / 4
    endif
    ~~~

    Why just 3Mhz? So, specific. All other frequencies for COUNT_DELAY are calculated. Seems wrong. Able to shed any light on this calc?

     
  • Jerry Messina

    Jerry Messina - 2023-11-10

    From what I can see, OSC == 3 is for a specific freq case...

    if (OSC == 3)
    ; Oscillator is 3.58MHz
    OSC_VALID = 1
    endif
    

    In all the other places OSC is assumed to be in integral MHz (ie 8 = 8MHz, 10=10MHz, etc)

     
  • Anobium

    Anobium - 2023-11-11

    @Jerry. Any idea why the special case? Is this specific to the Q43?

     
  • Jerry Messina

    Jerry Messina - 2023-11-11

    No it's not specific to the Q43... that assignment for COUNT_DELAY is the same for all devices.

    The special case for OSC=3 is because it really treats that as meaning "OSC=3.58" (for an exact xtal value), but since OSC has to be an integer the calculation "COUNT_DELAY = (50 * (OSC)) / 4" wouldn't be correct for "3", so it just assigns it directly as "COUNT_DELAY = 45", where 45=50x3.58/4.

    It does the same sort of special case for UART baudrate calculations.
    I guess using an xtal = 3.58MHz was popular at one time.

     

    Last edit: Jerry Messina 2023-11-11
  • Geoffrey Younger

    Hi,
    Every color TV set made in the USA had a 3.58MHz crystal in it. It is possibly the most manufactured xtal in history. Look [here] (https://https://en.wikipedia.org/wiki/NTSC) for more info. In the History part , approx half way down , starting at " In 1953 ----is a good explanation of why 3.58MHz was used.
    Regards,
    Geoffrey Younger

     
    • Anobium

      Anobium - 2023-11-12

      Thank you for this insight. This does explain the adaption in the code.

       
  • JB

    JB - 2024-04-12

    it's seem a function as PBP3 Pro (COUNT Pin, Period, Var ) is in development or not.
    Like to know if any.
    Tkx

     
    • Anobium

      Anobium - 2024-04-13

      Not that I am aware of.

      But, you could use thr code shown above as the basis of a solution.

       

Log in to post a comment.