Shop OBEX P1 Docs P2 Docs Learn Events
Priority Queue with BS2 — Parallax Forums

Priority Queue with BS2

NZmbeNZmbe Posts: 7
edited 2010-09-26 16:56 in BASIC Stamp
Is it possible to write a priority queue within PBasic? Honestly I'm not even sure that I'm asking the right question here. Still very new to this realm and I'm hitting walls head on left and right with this project.

The idea is I'd like to take a 9 LED array (3 rows of 3), with one push button per row, and have the order in which a button is pressed show up on the array. Example: When button 'a' is pressed the first LED of its corresponding row goes high. When the next button is pressed (whether it be 'B' or 'C') the second LED for the corresponding row goes High. And the last button would illuminate LED 3.

The reason I ask about priority queueing is when button 'a' in this case goes low, the LED (in the case position 1) should go low and the remaining "high" LED's shift positions to reflect the new order of priority.

Is this type of code even possible in PBasic? Any help would be greatly appreciated.

Comments

  • ercoerco Posts: 20,256
    edited 2010-09-20 16:03
    I think you want each new keypress (of 3 buttons) to light the corresponding LED in the leftmost column and shift the previous entries one column to the right. Is that correct? Sure, easily done in PBasic with a Stamp. You're only using 3 inputs and 9 outputs (a total of 12) so you could even add another column of 3 LEDs since BS2-class Stamps have 16 I/Os.

    x=button 0=LED

    x oooo
    x oooo
    x oooo
  • NZmbeNZmbe Posts: 7
    edited 2010-09-21 09:28
    Right, but thats where I hit the "wall". Thats the first half to this, and like you said, pretty simple. But what if I wanted the columns to shift to the left one position after I let go (open) the first button that was pressed?

    So for example

    a-c=button LED=1 / 0

    a 1000
    b 0100
    c 0010

    then button 'a' is released

    a 0000
    b 1000
    c 0100

    Its that shift thats got me stumped:confused:
  • ercoerco Posts: 20,256
    edited 2010-09-21 09:40
    Shifting left? So are you pushing buttons to follow the LEDs, like a game?
  • NZmbeNZmbe Posts: 7
    edited 2010-09-21 11:19
    erco wrote: »
    Shifting left? So are you pushing buttons to follow the LEDs, like a game?

    No, actually the opposite. The LEDs need to follow the buttons, following FIFO.

    Think of having three boxes in which you are going to place objects in with random order over an extended period of time. You need to know which order the items went in so that they can be removed in order of FIFO (thus three LEDs per box/ button) To keep the cycle flowing without pulling all the items and reseting, you'd want to be able to cancle the 'priority' setting of the item you pulled, and in doing so shift the priority of the other boxes to reflect said action. I know the easiest way to achieve this is to have timers on the boxes but this is not a project based on time sensitivity, just priority sensitive.
  • ercoerco Posts: 20,256
    edited 2010-09-21 14:46
    I'm missing something. I think you want to indicate which of 3 buttons was pressed in the LED array, but as drawn, the data will need to move to the RIGHT, not left. Each time you press a key, that LED comes on on the leftmost column, and the previous LED in the leftmost column moves to the center column, and the previous center LED moves to the rightmost column.

    As you decribed most recently (columns shifting left), older data on the right is moving left toward the buttons. Not sure what that is supposed to indicate or where that data came from.

    Am I confused?
  • NZmbeNZmbe Posts: 7
    edited 2010-09-21 16:50
    I'm sorry erco, I had no intention of making this confusing. Let me try one more time...

    'P = Priority Level

    'inputs - 'led array
    .......'p1 'p2 'p3
    IN1 - 0...0...1
    IN2 - 1...0...0
    IN3 - 0...1...0

    Ok so, if this were the real thing, what just happened was IN2 was set High before IN1 and IN3, then IN3 was set High, then IN1 was set High last out of all three. So, by looking at the array we can see the order in which the buttons where pressed. Now, if I were to set IN2 Low, it would turn its corresponding LED low, and shift the other two priority columns like this:

    .......'p1 'p2 'p3
    IN1 - 0...1...0
    IN2 - 0...0...0
    IN3 - 1...0...0

    Creating what I want to call a cycle although I know thats not PBasic correct. What I mean is, if I were to set IN2 High again it would show up on its row as Priority 3. Creating a cycle of 'priority' commands. If IN3 is set low, then what ever button/s are still set High will shift to accomodate the new priority status.

    I hope that makes sence. Thanks again
  • ercoerco Posts: 20,256
    edited 2010-09-21 17:26
    OK, sounds like you want the most recent entry on the rightmost column, shifting leftward with each new keystroke. That's where you lost me, it just seems a bit counterintuitive.

    Still easily done, except I think your expectations on the high/low might need adjusting. If all your switches are normally low, they will momentarily go high when pushed. So pressing a button will instantly light the corresponding LED in the rightmost column, and the previous data shifts left. Nothing happens when you release the button, that just advances the program to the "scan keyboard" portion of the program.

    Can you live with that?
  • NZmbeNZmbe Posts: 7
    edited 2010-09-21 18:38
    Hey, at this point I'm down for anything!
  • ercoerco Posts: 20,256
    edited 2010-09-21 20:06
    Have you started writing your program yet with your I/O pin assignments? Let's see what you have so far, working or not. This is a learning exercise, right? :)
  • RiJoRiRiJoRi Posts: 157
    edited 2010-09-22 05:19
    This is an interesting problem!

    I thought it over last night, and came up with a "flow sketch."
    L1:
        [Read Keys]
        <Keys Changed?>-- No --> goto L1
            Yes |
        <Key Down?>-- Yes --> goto L2
             No |
        [Clear all bits for this
          key in the queue]
                 |
        [Crunch the queue]
                 |
        [goto L3]
    
    L2:
        [Save the keys in the queue]
                 |
    L3:
        [Copy the queue to the LEDs]
                 |
        [goto L1]
    

    "Crunching" means to remove all '0' values in the queue by shifting non-zero values down.
    Copying the queue to the LEDs may need to be done in the L1 section.
    The case of one key being down steady as a second key goes up and down needs to be addressed, OR just the changed key will need to be saved to the queue (L2).

    HTH,
    --Rich
  • NZmbeNZmbe Posts: 7
    edited 2010-09-26 16:56
    Alright, I've been trying to modify a button scan code I found online and I got a few questions.

    I can't figure out how to 'link' the I/O pins to specific constants.

    e.g.:
    Rooma = dig0todig2
    Roomb = dig3todig5
    Roomc = dig6todig8

    The idea being that Rooma display cant spill into roomb display. I was trying to accomplish this though an Alias/Mod but its not going anywhere. Or, can I make three different counters??? hmmm

    Second question: To RiJoRi, thanks for the input! I understand the concept but not the application. Like I said before I'm still very new at this and thus I have no idea how to 'crunch the queue':smilewinkgrin: Are your 'queue' ideas done through Write/Read?

    (n00b alert) If I'm running 9 LEDs out OUTH how can I get the remaining LED to follow suit? OUTH=8-15 so how can get out7 involved?

    Plus I'm all ears for any other suggestions that you may have.

    Thanks again for the help!
    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    
    
    
    ' -----[ I/O Definitions ]-------------------------------------------------
    
    
    Segments        VAR     OUTH                    ' output on pins 8-15
    
    
    Rooma           PIN     0                       ' Room 1
    Roomb           PIN     1                       ' Room 2
    Roomc           PIN     2                       ' Room 3
    
    ' -----[ Constants ]-------------------------------------------------------
    
    
    Dig0            CON     %100000000               ' segment data for Priority
    Dig1            CON     %010000000
    Dig2            CON     %001000000
    Dig3            CON     %000100000
    Dig4            CON     %000010000
    Dig5            CON     %000001000
    Dig6            CON     %000000100
    Dig7            CON     %000000010
    Dig8            CON     %000000001
    
    Pressed         CON     1                       ' button states
    NotPressed      CON     0
    
    
    ' -----[ Variables ]-------------------------------------------------------
    
    btns            VAR     NIB                     ' button holder
    btn1            VAR     btns.BIT0               ' debounced button value
    btn2            VAR     btns.BIT1               ' deboucned button value
    btn3            VAR     btns.BIT2               ' debounced button value
    idx             VAR     Nib                     ' Priority index
    counter         VAR     Nib                     ' current priority to display
    
    
    ' -----[ Initialization ]--------------------------------------------------
    
    Setup:
      DIRH = %0111111111                            ' P8 - P15 are outputs
      GOSUB Show_Prio                               ' initialize display
    
    
    ' -----[ Program Code ]----------------------------------------------------
    
    Main:
      DEBUG CLS,
            "Button & Display Test", CR, CR,
            "Rooma (P0).......... ", CR,
            "Roomb (P1).......... ", CR,
            "Roomc (P2).......... "
    
      DO
        GOSUB Get_Buttons                           ' scan buttons
        GOSUB Show_Buttons                          ' show states
        IF (btns > %000) AND (btns < %111) THEN     ' pressed?
          counter = counter + btn1 // 10            ' increment if Button1 = 1
          counter = counter + btn2 // 10            ' increment if Button2 = 1
          counter = counter + btn3 // 10            ' increment if button3 = 1
          GOSUB Show_Prio                           ' update display
          PAUSE 250
        ENDIF
      LOOP
    
    
    ' -----[ Subroutines ]-----------------------------------------------------
    
    'Show prio via LED
    
    Show_Prio:
      DEBUG CRSRXY, 0, 5, DEC ?counter              ' update DEBUG screen
      LOOKUP counter, [Dig0, Dig1, Dig2, Dig3, Dig4,
                       Dig5, Dig6, Dig7, DIG8], Segments
      RETURN
    
    
    ' Scan and debounce buttons
    
    Get_Buttons:
      btns = %000111
      FOR idx = 1 TO 5
        btns.BIT0 = btns.BIT0 & Rooma               ' scan button
        btns.BIT1 = btns.BIT1 & Roomb               ' scan button
        btns.BIT2 = btns.BIT2 & roomc               ' scan button
        PAUSE 5                                     ' debounce delay
      NEXT
      RETURN
    
    
    ' Show current button states
    
    Show_Buttons:
      FOR idx = 0 TO 1
        DEBUG CRSRXY, 20, 2 + idx                   ' move cursor
        IF (btns.LOWBIT(idx) = Pressed) THEN        ' check and display status
          DEBUG "Pressed", CLREOL
        ELSE
          DEBUG "Not Pressed"
        ENDIF
      NEXT
      RETURN
    
Sign In or Register to comment.