Shop OBEX P1 Docs P2 Docs Learn Events
OLED Display Screen Lock Issue — Parallax Forums

OLED Display Screen Lock Issue

Hi Everyone,

I'm having an issue with my OLED display (Color OLED Display Module, 96x64 from Parallax - uses SSD1331 driver chip) locking up on my test box (using the P1 chip). It only ever does it when the test box is in what has been termed "Bit Whack Mode." In this mode the test box (Prop) is acting like a bit whacker for driving attached microelectronic parts using SPI or TTL. There is a USB connection between the computer and the Prop. Originally the issue was that when the test box was not connected to the computer via USB and Bit Whack Mode was entered into, the exit command (a single button press) would not fully work (it always works, and still does, no matter what length of time test box is in Bit Whack Mode if the USB connection with the computer is present). Through fleshing the issue out, I realized that the exit command was partially working by kicking the test box out of Bit Whack Mode (as I could navigate to another mode, evidenced by the LED Bar lighting up as it would in a different mode depending on button presses) but the OLED screen was not clearing. So from that point forward, no matter what mode I was in, no matter what was supposed to be written to the OLED screen, it would always say "Bit Whack," meaning the OLED screen was locked up.

I thought this was interesting since there has never been an issue in any of the other modes, no matter what length of time the test box was in the other mode inactive. It seemed reasonable that part of the issue was the lack of a USB connection. In Bit Whack Mode, the test box is continuously looking for a command from the computer (using Full Duplex Serial), but without the USB connection it never gets anything and the OLED locks up. I tried to think of a way to trick the test box into thinking that there was a USB connection, but I wasn't sure how to trick it into thinking there was 5V and ground coming through the USB port. So I took another tact, keeping the OLED screen busy so that it wouldn't lock up. I added in the repeat loop for this mode a command to write spaces to the OLED screen in every looping. I did it in such a way that it wouldn't interfere with "Bit Whack" being written to the screen but it would still have something continuously written to it. This seemed to work. And it didn't cause too much of a delay for when the test box was actually connected to the computer via USB and receiving data to drive a part. But upon further testing I found that the problem was still there to a degree. The fix worked really well for the first 10-15 seconds in Bit Whack Mode with no USB connected. But from 15-25 seconds, 2-3 button clicks are required for the exit to work, not just one. And after 25 seconds the OLED screen is completely locked up and the prop has to be reset. My initial thought is that the writing of spaces to the OLED screen to keep it from locking up, yes fixes the problem for a little bit, but causes timing issues in the loop that become more pervasive as time in the mode increases.

Can anyone provide any insights into this issue? I would ideally like to explore a more sustainable fix for the OLED locking up in first place with no USB connection, but will be satisfied if we can brainstorm a way to make my pseudo fix in writing spaces to the OLED screen work better. Thank you!

Posted below are two versions of the Bit Whack Mode spin code. The first is the original in which I am not writing spaces continuously to the OLED and it is locking up as soon as Bit Whack mode is entered into without a USB connection. The second is that code with the OLED being continuously written to with spaces.

V.1

PUB Bit_Whacker_Mode | ch        {will need to have lines connected to LED's for the control lines to the part}

  OLED.clearDisplay
  outa[LED7..LED0]~~


  OLED.write1x6String(String("Bit"),3,15,0,OLED#Yellow,OLED#BLACK)
  OLED.write1x6String(String("Whack"),5,0,32,OLED#Yellow,OLED#BLACK)
  misc.delay(1000)


  input_buff_index := -1


  repeat

    if misc.ChkBtnPulse(btn, 0, 50)
      OLED.clearDisplay
      return

    ' attempt to retrieve character from serial terminal

    ch := serial.rxcheck

    OLED.write1x6String(String(" "),1,0,0,OLED#Yellow,OLED#BLACK)   {{writing space to prevent screen from locking up when
                                                                      test box not connected to USB in Bit Whack Mode}}

    ' character ready in receive buffer?
    if (ch <> -1)
      'input_buff_index++
      ' process character, test for carriage return, or basic EDITing characters like back space
      case ch

        ASCII_LF, ASCII_CR: ' return



          ' print the buffer
          if (input_buff_index > -1)
            ' at this point we have the command buffer, so we can parse it
            ' copy it
            bytemove( @tok_buff, @input_buff, ++input_buff_index )

            ' null terminate it
            tok_buff[ input_buff_index ] := 0
            tok_buff_index := input_buff_index

            ' reset buffer
            input_buff_index := -1

            ' tokenize input string
            num_tokens := 0

            ' start the tokenization of the string (this function mimics the C strtok_r function more or less
            strtok_r(@tok_buff, string(","), @token_ptr)

            ' continue tokenization process now that first token has been found
            repeat while (token_ptr <> NULL)
              ' upcase the token before insertion
              StrUpper( token_ptr )

              ' insert token into token array
              tokens[ num_tokens++ ] := token_ptr


              ' get next token
              strtok_r( NULL, string(","), @token_ptr)

           ' end repeat tokenization...

            ' // end if buffer valid

            ' // Now process command in large if, elseif, else chain
            ' each "if" attempts to process a different command, if no
            ' command is found then user typed it wrong or its not supported
            ' and an error is emmited. Each command passes parameters to the COG
            ' running the specific driver being requested; NTSC, VGA, etc.
            ' the full functionality of each driver is NOT exposed, only a subset to
            ' illustrate the idea of use the Prop as a slave processor controlled by a
            ' serial communications stream in ASCII...
            {{
            First process "local" client commands for terminal. These include
            requests to the terminal such as clear the screen, help, etc.
            The remaining commands are "remote commands" that are processed and
            then issued to the "worker" cores running the respective drivers for
            video, vga, audio, etc.
            }}
            ' clear the terminal screen command
            if ( strcomp( tokens[0], string("C") ) )
                serial.txstringnl( string("OK"))
                OLED.clearDisplay
                OLED.write1x6String(string("OK"),2,15,0,OLED#Yellow,OLED#BLACK)


            elseif ( strcomp( tokens[0], string("O") ))
                serial.txstringnl( string("OK"))
                DataS := ( tokens[2] )
                Data := StrToDec(DataS)
                Decimal := sn.decf(Data, 5)
                ifnot DataX == Data
                  OLED.write1x6String(Decimal,5,0,0,OLED#Yellow,OLED#BLACK)
                  outa[LED0] := !((Data & %00000001))
                  outa[LED1] := !((Data & %00000010) >> 1)
                  outa[LED2] := !((Data & %00000100) >> 2)
                  outa[LED3] := !((Data & %00001000) >> 3)
                  outa[LED4] := !((Data & %00010000) >> 4)
                  outa[LED5] := !((Data & %00100000) >> 5)
                  outa[LED6] := !((Data & %01000000) >> 6)
                  outa[LED7] := !((Data & %10000000) >> 7)
              DataX := Data




          ' print prompt
         serial.txstring( @prompt )

        ' editing commands, for now just backspace, later you could add more advanced terminal based editing
        ' but the trick is to keep the buffer on the client side sync'ed with the terminal's display!
       ASCII_BS:      ' backspace
          ' insert null
           if (input_buff_index => 0)
            input_buff[ input_buff_index-- ] := ASCII_NULL

            ' echo character
            serial.tx( ch )

       other:
          ' insert character into command buffer for processing
          input_buff[ ++input_buff_index ] := ch

          ' echo character to terminal (terminal must be in non ECHO mode, otherwise you will see input 2x!)
          'serial.tx( ch )

V.2

PUB Bit_Whacker_Mode | ch        

  OLED.clearDisplay
  outa[LED7..LED0]~~


  OLED.write1x6String(String("Bit"),3,15,0,OLED#Yellow,OLED#BLACK)
  OLED.write1x6String(String("Whack"),5,0,32,OLED#Yellow,OLED#BLACK)
  misc.delay(1000)


  input_buff_index := -1


  repeat

    if misc.ChkBtnPulse(btn, 0, 50)
      OLED.clearDisplay
      return

    ' attempt to retrieve character from serial terminal

    ch := serial.rxcheck

    OLED.write1x6String(String(" "),1,0,0,OLED#Yellow,OLED#BLACK)   {{writing space to prevent screen from locking up when
                                                                      test box not connected to USB in Bit Whack Mode}}

    ' character ready in receive buffer?
    if (ch <> -1)
      'input_buff_index++
      ' process character, test for carriage return, or basic EDITing characters like back space
      case ch

        ASCII_LF, ASCII_CR: ' return



          ' print the buffer
          if (input_buff_index > -1)
            ' at this point we have the command buffer, so we can parse it
            ' copy it
            bytemove( @tok_buff, @input_buff, ++input_buff_index )

            ' null terminate it
            tok_buff[ input_buff_index ] := 0
            tok_buff_index := input_buff_index

            ' reset buffer
            input_buff_index := -1

            ' tokenize input string
            num_tokens := 0

            ' start the tokenization of the string (this function mimics the C strtok_r function more or less
            strtok_r(@tok_buff, string(","), @token_ptr)

            ' continue tokenization process now that first token has been found
            repeat while (token_ptr <> NULL)
              ' upcase the token before insertion
              StrUpper( token_ptr )

              ' insert token into token array
              tokens[ num_tokens++ ] := token_ptr


              ' get next token
              strtok_r( NULL, string(","), @token_ptr)

           ' end repeat tokenization...

            ' // end if buffer valid

            ' // Now process command in large if, elseif, else chain
            ' each "if" attempts to process a different command, if no
            ' command is found then user typed it wrong or its not supported
            ' and an error is emmited. Each command passes parameters to the COG
            ' running the specific driver being requested; NTSC, VGA, etc.
            ' the full functionality of each driver is NOT exposed, only a subset to
            ' illustrate the idea of use the Prop as a slave processor controlled by a
            ' serial communications stream in ASCII...
            {{
            First process "local" client commands for terminal. These include
            requests to the terminal such as clear the screen, help, etc.
            The remaining commands are "remote commands" that are processed and
            then issued to the "worker" cores running the respective drivers for
            video, vga, audio, etc.
            }}
            ' clear the terminal screen command
            if ( strcomp( tokens[0], string("C") ) )
                serial.txstringnl( string("OK"))
                OLED.clearDisplay
                OLED.write1x6String(string("OK"),2,15,0,OLED#Yellow,OLED#BLACK)


            elseif ( strcomp( tokens[0], string("O") ))
                serial.txstringnl( string("OK"))
                DataS := ( tokens[2] )
                Data := StrToDec(DataS)
                Decimal := sn.decf(Data, 5)
                ifnot DataX == Data
                  OLED.write1x6String(Decimal,5,0,0,OLED#Yellow,OLED#BLACK)
                  outa[LED0] := !((Data & %00000001))
                  outa[LED1] := !((Data & %00000010) >> 1)
                  outa[LED2] := !((Data & %00000100) >> 2)
                  outa[LED3] := !((Data & %00001000) >> 3)
                  outa[LED4] := !((Data & %00010000) >> 4)
                  outa[LED5] := !((Data & %00100000) >> 5)
                  outa[LED6] := !((Data & %01000000) >> 6)
                  outa[LED7] := !((Data & %10000000) >> 7)
              DataX := Data




          ' print prompt
         serial.txstring( @prompt )

        ' editing commands, for now just backspace, later you could add more advanced terminal based editing
        ' but the trick is to keep the buffer on the client side sync'ed with the terminal's display!
       ASCII_BS:      ' backspace
          ' insert null
           if (input_buff_index => 0)
            input_buff[ input_buff_index-- ] := ASCII_NULL

            ' echo character
            serial.tx( ch )

       other:
          ' insert character into command buffer for processing
          input_buff[ ++input_buff_index ] := ch

          ' echo character to terminal (terminal must be in non ECHO mode, otherwise you will see input 2x!)
          'serial.tx( ch )
Sign In or Register to comment.