Skip to main content
Topic: Controlling CS pin in binary I2C mode (Read 12718 times) previous topic - next topic

Controlling CS pin in binary I2C mode

I've been preparing a tutorial on interfacing Hope RF pressure/temperature sensors HP03S & HP03M with Bus Pirate. They work quite well in the text mode so I decided to write a C application that would handle them in binary I2C mode as it is quite complicated to get the pressure/temperature value which depends heavily on calibration data stored internally and then you have to put everything into equations... Anyway, I have read a few posts about the problems with binary I2C mode which is SW emulated so I took all the necessary measures to reattempts writes/reads to get it done. For these chips to work I must provide 30-35kHz frequency for the ADC. I used the general binary mode commands for that and it works just fine on AUX pin.

Now the tricky part.. This sensors also have a XCLR pin which keeps the ADC in reset/low power consumption state when not used and high when getting the pressure/temperature readings and what is more important it must be held low when reading calibration data. In the text mode I was successfully using the CS pin for that by first issuing "C" command to make the AUX => CS ( luckily the PWM works independently from that :) ) and then using a/A. I was trying to reproduce the same behavior in the binary mode. I configured the CS pin as output ( while still in the BitBang mode ) with "10xxxxx - Configure pins as I/O" command. Then in the binary I2C I was trying to use the "0100wxyz – Configure peripherals" command to control the CS pin. Now.. things get really complicated. When connecting the OLS I can see the CS is high.. but for some reason it is not the same high state as in text mode :/

I am able to work with the chip by manually handling the XCLR by either connecting it to 3V3 or GND and as mentioned a couple of times in the text mode using CS as AUX.

I have OLS logs from both text and binary modes. Everything seems exactly the same and yet it still doesn't work unless I manually take care of XCLR. I am using on-board VRegs and pull-ups connected to the 3V3 which is also used to power up the sensor.

Re: Controlling CS pin in binary I2C mode

Reply #1
Hi pppd,

Quote
while still in the BitBang mode

The pin settings are cleared when entering or leaving a mode.

You can use this command to set them up in I2C mode:
http://dangerousprototypes.com/docs/I2C_(binary)#0100wxyz_.E2.80.93_Configure_peripherals_w.3Dpower.2C_x.3Dpullups.2C_y.3DAUX.2C_z.3DCS

It says that CS follows the current HiZ setting, so you may need to add a pull-up resistor to hold it high.
Got a question? Please ask in the forum for the fastest answers.

Re: Controlling CS pin in binary I2C mode

Reply #2
Hi Ian,

But I do use the 0100wxyz command already.. and it doesn't help. The real problem is.. why it does work in the text mode and then it fails in binary. As I said logic sniffer captures CS as HIGH both in text/binary modes.. but there must be either a bug in my code or a difference in behavior.

My code goes as follows:

Code: [Select]
	//01001101 -- XCLR/CS high, keep VREG and PullUps

if( BB_simpleCMD(fd, 0x4D, 1, "1") ) {
return -1;
}

... //other I2C commands


//01001100 -- XCLR/CS low, keep VREG, PullUps
if( BB_simpleCMD(fd, 0x4C, 1, "1") ) {
return -1;
}

Re: Controlling CS pin in binary I2C mode

Reply #3
Can you paste the terminal output so I can take a look?
Got a question? Please ask in the forum for the fastest answers.

Re: Controlling CS pin in binary I2C mode

Reply #4
A dump from the binary mode or text commands used to achieve this ?

Here's the text mode, and I will get binary log in a minute:
Code: [Select]
HiZ>m
1. HiZ
2. 1-WIRE
3. UART
4. I2C
5. SPI
6. 2WIRE
7. 3WIRE
8. LCD
9. DIO
x. exit(without change)

(1)>4
Set speed:
 1. ~5KHz
 2. ~50KHz
 3. ~100KHz
 4. ~400KHz

(1)>1
Ready
I2C>W 
Power supplies ON
I2C>P
Pull-up resistors ON
I2C>g
1KHz-4,000KHz PWM
Frequency in KHz
(50)>32
Duty cycle in %
(50)>50
PWM active
I2C>C
a/A/@ controls CS pin
I2C>A %:2 [0xEE 0xFF 0xF0] %:50 [0xEE 0xFD[0xEF r:2] a
AUX HIGH
DELAY 2ms
I2C START BIT
WRITE: 0xEE ACK
WRITE: 0xFF ACK
WRITE: 0xF0 ACK
I2C STOP BIT
DELAY 50ms
I2C START BIT
WRITE: 0xEE ACK
WRITE: 0xFD ACK
I2C START BIT
WRITE: 0xEF ACK
READ: 0xB4  ACK 0xAD
NACK
I2C STOP BIT
AUX LOW
I2C>

Re: Controlling CS pin in binary I2C mode

Reply #5
Attached binary log, it's quite long as it includes entering binary mode. I have connected a multimeter to the CS pin and in binary mode it gives 3.25V while in text mode it is 3.29V. Now that's just weird.. while the multimeter was still connected I could randomly get readouts in binary mode. As soon as I unplugged it it kept giving NACK to A/D which means the XCLR is LOW.

[attachment=0]

Re: Controlling CS pin in binary I2C mode

Reply #6
Thank you, I meant the text mode output, but I'll take a look at both.

Just off the bat - do you expect the PWM to run in binary I2C mode? It may, I'm not 100% sure though.
Got a question? Please ask in the forum for the fastest answers.

Re: Controlling CS pin in binary I2C mode

Reply #7
It does work, luckily :)

Re: Controlling CS pin in binary I2C mode

Reply #8
I have looked through the BP source and I think I found the difference. In text mode I am setting it to use alternative Aux ( CS ) and then controlling it with a/A which calls the following routine in the BP source:
Code: [Select]
void bpAuxHigh(void){

#ifndef BUSPIRATEV4
if(modeConfig.altAUX==0)
{ BP_AUX_DIR=0;//aux output
BP_AUX=1;//aux high
}
else
{ BP_CS_DIR=0;//aux input
BP_CS=1;//aux high
}
#endif
As you can see it does not check for HiZ mode and truly puts the pin in the high state and not just leave it for the pull-ups to keep it up.

Below is a snipped from the binary I2C mode:
Code: [Select]
	//AUX pin, high/low only
if(inByte&0b10){
BP_AUX_DIR=0;//aux output
BP_AUX=1;//aux high
}else{
BP_AUX_DIR=0;//aux output
BP_AUX=0;//aux low
}

//CS pin, follows HiZ setting
if(inByte&0b1){
if(modeConfig.HiZ==1){
IODIR|=CS; //CS iput in open drain mode
}else{
IOLAT|=CS; //CS high
IODIR&=(~CS); //CS output
}
}else{
IOLAT&=(~CS); //BP_CS=0;
IODIR&=(~CS); //CS output
}
Now my question is if I could add a new I2C command ( or two ) so I can either control CS directly just like in the text mode.. or control AUX and add alternative AUX selection.

Re: Controlling CS pin in binary I2C mode

Reply #9
I have added a new I2C binary mode command which I called extended AUX. It uses the AUXpin.c functions with an extra parameter not to print anything. Now it works just like it did in the text mode. The command is 0x09 ( 00001001 ) and takes one byte parameter not to waste any more bytes in the root command set. I tried not to define any more variables but to reuse existing. I am not sure this is the best way to go, but I don't know how much RAM we have.

Below is the command itself and all possible parameters for now:
Code: [Select]
//00001001 xxxxxxxx
case 9: //extended AUX command
UART1TX(1); //confirm that the command is known
//inByte - used as extended commmand
//fr - used as result
while(U1STAbits.URXDA == 0);//wait for subcommand byte
inByte=U1RXREG; //get byte
//0x00 - AUX/CS low
//0x01 - AUX/CS high
//0x02 - AUX/CS HiZ
//0x03 - AUX read
//0x10 - use AUX
//0x20 - use CS


fr=1;
switch( inByte ) {
case 0x00:
bpAuxLow(0);
break;
case 0x01:
bpAuxHigh(0);
break;
case 0x02:
bpAuxHiZ(0);
break;
case 0x03:
fr = bpAuxRead();
break;
case 0x10:
modeConfig.altAUX = 0;
break;
case 0x20:
modeConfig.altAUX = 1;
break;
default:
fw = 0;
break;
}
UART1TX(fr);//result
break;
I do have R/W access to the repository from the time I was submitting pirate loader utility, but I would like to get this approved by you before submitting anything.

This seems to work perfectly fine and I can finally control my sensors in binary mode. I think the reason is CS pull-up resistor which does not provide enough current to keep the XCLR high.

Re: Controlling CS pin in binary I2C mode

Reply #10
Added this fix to the v6 code and documented it here:
http://dangerousprototypes.com/docs/I2C ... UX_command
Got a question? Please ask in the forum for the fastest answers.

Re: Controlling CS pin in binary I2C mode

Reply #11
I am trying to use Bus Pirate on Lazarus.
I have problems implementing this command.
It has to return 0x01 for OK or a value when AUX is read and it supposes to return 0x00 on error, but it returns weird values.

Looking at this code

Code: [Select]
    //00001001 xxxxxxxx
    case 9: //extended AUX command
          UART1TX(1); //confirm that the command is known
          //inByte - used as extended commmand
          //fr - used as result
          while(U1STAbits.URXDA == 0);//wait for subcommand byte
          inByte=U1RXREG; //get byte
          //0x00 - AUX/CS low
          //0x01 - AUX/CS high
          //0x02 - AUX/CS HiZ
          //0x03 - AUX read
          //0x10 - use AUX
          //0x20 - use CS
         
         
          fr=1;
          switch( inByte ) {
            case 0x00:
                bpAuxLow(0);
                break;
            case 0x01:
                bpAuxHigh(0);
                break;
            case 0x02:
                bpAuxHiZ(0);
                break;
            case 0x03:
                fr = bpAuxRead();
                break;
            case 0x10:
                modeConfig.altAUX = 0;
                break;
            case 0x20:
                modeConfig.altAUX = 1;
                break;
            default:
                fw = 0;
                break;
          }
          UART1TX(fr);//result
          break;

I think there is an error, the code says
Code: [Select]
 //fr - used as result 

but and the end of the code i see
Code: [Select]
           default:
                fw = 0;
                break;
Which one is not correct fr or fw

Re: Controlling CS pin in binary I2C mode

Reply #12
The default case should not be reached if correct subcommand is given, so that is not affecting the result itself.

What you should receive is:

0x01 - command recognized
0x0? - AUX value either 0 or 1

Re: Controlling CS pin in binary I2C mode

Reply #13
I don't have a Bus Pirate here, I have it at work, but I'll try to explain the problem.

1-Send 0x09 command, get 0x01.
2-Send 0x10 subcmmand (use AUX), don't remember what i get.
3-Send 0x00 command again, get 0x01.
4-Send 0x01 subcommand (AUX High), get 65
5-Send 0x09 command, get 0x01.
6-Send 0x00 subcommand (AUX Low), get 82 or 88 (not sure).

If you see the code fr is set to 1 before the switch and the default value set fw not fr to 0.

What is the right value fr or fw.

Re: Controlling CS pin in binary I2C mode

Reply #14
This is really weird.. as you can see in the code only the fr is ever sent via UART, the fw is set to 0 but never really sent which is a bug but does not explain the weird values you get.