PICBASIC and the SAA1064 Seven-Segment Module

A while back I purchased an I2C compatible 4-digit seven-segment module on eBay for next to nothing. The description said arduino compatible, so getting it to work with PICS should not be a problem.  The display module is based on NXP SAA1064 I2C controller.  The datasheet for the SAA1064 can be found here.  The modules I2C device address is factory-set at %01110000, or $70.  Initially, I2CWRITE seemed like the logical choice for getting the device to work.  For some reason I was unable to get I2CWRITE to work, and had to manually send commands via the SHIFTIN/SHIFOUT commands.  After the 16F88 was up and running on the breadboard, went about hooking up the module.  There are 4 pins on the board: VCC, SDA,SCL,GND.  VCC and GND were connected to their respective pins.  The SDA and SCL pins were then connected to PICs B.2 and B.3 pins with pullup resistors on both pins. 

Before the module can display anything the SAA1064 has to be initialized.   

First the I2c communication has to be started, which accomplished by calling the subroutine I2C_START:


The SDA and SCL pins are both set HIGH, then the SDA is brought LOW, which lets the I2C bus know data is comming.

The SAA1064 expects the next byte to be the device byte, followed by the instruction byte, followed by either a control or data byte.  When the circuit is first powered on the SAA1064 must be initalized.   So first the device byte is sent:

i2c_out = %01110000 : GOSUB I2C_TX

 The program contains a variable i2c_out, that gets loaded with the byte to be shifted out.  The subroutine I2C_TX is then used to shift that data out:

    SHIFTOUT SDA,SCL,1,[i2c_out]  
    SHIFTIN SDA,SCL,0,[i2c_ack\1]          

SHIFTOUT is used to send the i2c_out byte, MSB first.  Next SHIFTIN is used to recieve the ACK bit from the SAA1064.

Next the instruction byte needs to be sent.  Refer to the datasheet for bit settings of the instruction byte.


The instruction byte is like a pointer to where the next byte is put on the SAA1064.  A value of %00000000 sets the pointer to the control register.  So the i2c_out is loaded with %00000000 and shifted out:

i2c_out = %00000000 : GOSUB I2C_TX

Now that the pointer is set to the control register, the control byte can be sent.  The control byte allows different settings of the chip to be used.  A value of %00010111 turns on dynamic mode, turn off blanking on segments 1-4, and sets the segment power at 3mA.  So again the i2c_out variable is loaded with  %00010111 and shifted out:

i2c_out = %00010111 : GOSUB I2C_TX       

Now that the control byte is sent, the I2C communication can be ended by calling the I2C_STOP subroutine:

    PAUSE 1

The I2C_STOP subroutine brings the SDA pin high again which ends the I2C transmission.  Now the display is set up and is ready to use.  A simple example of use:

First use LOOKUP to translate segment bits into actual decimal numbers.  This is where things could be different depending on who built your module.  Mine came with a segment key:  

0 = b
1 = DP
2 = a
3 = c
4 = e
5 = d
6 = g
7 = f



So using a lookup table, bits can be translated into digits:

LOOKUP i, [189,9,117,109,201,236,248,13,253,205],seg_val

If the value (4) is loaded into the i variable, then the LOOKUP command would load (201) into the seg_val variable.  (201) is the decimal equvilant of %11001001, which turns on segments f,g,c,and b; or the number (4) on the display. Now the value can be sent to the display:

   i2c_out = %01110000 : gosub i2C_tx 'device byte is sent
   i2c_out = %00000001 : gosub i2C_tx 'instruction byte is set to point to digit 1
   i2c_out = seg_val : gosub i2c_tx 'seg_val is sent to display

First the I2C transmission is started.  Then the device byte is sent, followed by the  instruction byte %00000001, which sets the pointer to the first digit.  Then seg_val is then sent.  Finally the I2C transmission is stopped, and the number 4 should be displayed. 

I cant seem to get the auto increment to work, so each digit has to be pointed to manually with the instruction byte.

Here is the entire PICBASIC code for a PIC16F88, which counts from 0-9, on each of the digits:

'// for 4MHZ
'// for 8MHZ
While OSCCON.2=0:Wend
CMCON         =  7                 '// PORTA = digital I/O
'OPTION_REG.7  =  0                 '// Enable PORTB pull-ups
ADCON1        =  7
ANSEL=%00000000                    '// set all analog pins to digital
ANSEL = 0                          '// disable ADCs
TRISB.3 = 0
TRISB.2 = 0
led         var PORTA.1
SDA         VAR PORTB.3
SCL         VAR PORTB.2

i2c_out     VAR BYTE        'data to sent over I2C bus
i2c_ack     VAR BIT         'acknowledgement bit
i           var byte
segment     VAR byte
seg_val     var byte
gosub startup 
GOSUB init_display   'initialize the display module
   goto main
    for i = 0 to 9
        lookup i, [189,9,117,109,201,236,248,13,253,205],seg_val
        for segment = 1 to 4
              GOSUB I2C_START
              if segment = 1 then
                 i2c_out = %01110000 : gosub i2C_tx : i2c_out = %00000001 : gosub i2C_tx
                 i2c_out = seg_val : gosub i2c_tx
                 gosub i2c_stop
              if segment = 2 then
                 i2c_out = %01110000 : gosub i2C_tx : i2c_out = %00000010 : gosub i2C_tx
                 i2c_out = seg_val : gosub i2c_tx
                 gosub i2c_stop
              if segment = 3 then    
                 i2c_out = %01110000 : gosub i2C_tx : i2c_out = %00000011 : gosub i2C_tx
                 i2c_out = seg_val : gosub i2c_tx
                 gosub i2c_stop
              if segment = 4 then    
                 i2c_out = %01110000 : gosub i2C_tx : i2c_out = %00000100 : gosub i2C_tx
                 i2c_out = seg_val : gosub i2c_tx
                 gosub i2c_stop
          next segment
        pause 100 
      next i
init_display:           'initialize the SAA1064 module and flash all segments
    GOSUB I2C_START     'Start the I2C communication
       i2c_out = %01110000 : GOSUB I2C_TX        'send device byte
       i2c_out = %00000000 : GOSUB I2C_TX        'send instruction byte 
       i2c_out = %00011111 : GOSUB I2C_TX        'send control byte    
    GOSUB I2C_STOP      'Stop i2C transmission
    pause 1000          ' leave segments on for 1 sec then turn off
       i2c_out = %01110000 : gosub i2C_tx
       i2c_out = %00000000 : gosub i2C_tx
       i2c_out = %00000001 : GOSUB I2C_TX
    pause 500
       i2c_out = %01110000 : gosub i2C_tx
       i2c_out = %00000000 : gosub i2C_tx
       i2c_out = %00010111 : GOSUB I2C_TX
I2C_STOP:               'I2C stop (terminate communication on I2C bus)
    PAUSE 1
I2C_TX:                           'I2C transmit -> send data to the slave
    SHIFTOUT SDA,SCL,1,[i2c_out]  'Shift out “i2c_out” MSBfirst
    SHIFTIN SDA,SCL,0,[i2c_ack\1] 'Receive ACK bit          

Fume extractor for soldering….

  After making more pcb’s to solder, I finally decided it was time to build a fume extractor.  With all the spare parts I have laying around it wouldnt be that hard to contruct.  I etched a small pcb for using an LM317 voltage regulator as a ghetto speed control for a 70mm PC cooling fan.  The box was constructed out of various scrap pieces around the basement.  With everything finished I think a coat of paint will help, and a charcoal filter from the local Salvation Army will complete the project.

LED Eyes for LMFAO costume….



 A friend at work asked if I could make some red eyes for a costume she was making for Halloween.  Its based off the robot from LMFAO’s video.  I bought (two) $1.00 flashlights from walmart.  Then, next door at Lowes I found (two) pvc endcaps for $1.00.  I removed just the flashlight tops and discarded the battery tubes.  I then removed the lightbulbs and replaced them with the red LED’s I already had on hand.  The LED’s were then wired in parallel and then connected to a 4-AA battery holder.  It could definitely be brighter and could use an on/off switch, but doesn’t look to bad.

Trying to unlock an iPhone 3G for use on other networks…

A friend happened to purchase a iPhone 3G for a decent price, and was wanting to know if it could be used on other carriers networks.  I have jailbroke an iPhone 3GS but never needed to unlock it. (I just use it for pandora) Sources this seemed possible to acheive….little did I know that unlocking is a bit more difficult.  There are programs to help you acheive the jailbreaking/unlocking tasks. 

  • Redsnow – used to unlock and jailbrake an iPhone.
  • tinyUmbrella – used to show info about an iphone even if iTunes cant.

Using redsn0w I checked the box that said install Cydia.  I then had to place the phone into DFU mode by:

  1. Press and hold the POWER and HOME button togeter for 10 seconds.
  2. Release the POWER button while still pressing the HOME button.
  3. After 15 seconds release the HOME button.

The phone should now be in DFU mode. redsnow should then continue jailbreaking the device.  After that process is complete, I ran redsnow again with the “install iPad Baseband” box checked. 

Once the phone rebooted, u had to install snowbreeze on the phone to enable the iPad baseband. One more reboot and 20 minutes later, the iPhone was working on tmobile’s family network.



Finally….the fan controller worked

This slideshow requires JavaScript.

After many weeks the fan controller finally works.  Once we had it connected everything was opposite; the fans kicked on when they should be off and vice versa.  Then I realized I changed the transistors from NPN to PNP; instead of pulling the fans high when on they need to be pulled to ground.  One small change in the program and boom went the dynamite.

Fan Relay Board etched and populated….

  After using the toner transfer method to apply the circuit to the bare pcb, I began the etching process.  Using the same batch of etching solution from before, I noticed the process was quite a bit slower.  I left the board in the etchant for at least 30 minutes.  I was a little worried at first, but relived when the copper finally started to disappear.  
Once I began to place the components I had noticed that the transfer was printed upside down…luckily the circuit is simple and works both ways with the relay being the only thing that had to be soldered on the opposite side. 
Also replacing the NPN transistor with a PNP type, allowed the transistor to switch a grounded supply.  I don’t know why this problem eluded me before; I should of realized that a PNP transistor should be used in this situation. This probably would have fixed the initial problem, but adding the relay gives me a little more control over what is going on. 
Once everything was soldered, I connected the boards and placed them into a small black case used for storing static sensitive devices….which were free from Microchip.
Now I just need to hook it up to the car one more time for a test run and the controller should be finished.