Rev Author Line No. Line
1274 kakl 1 /************ SMB driver ************/
2  
3 #define SA 0x00 // Slave Address (0 for single slave / 0x5A<<1 default)
4 #define RAM_Access 0x00 // RAM access command
5 #define RAM_Tobj1 0x07 // To1 address in the RAM
1720 kakl 6 #define RAM_Tobj2 0x08 // To2 address in the RAM
1274 kakl 7 #define RAM_Tamb 0x06 // Ta address in the RAM
8  
1275 kakl 9  
1284 kakl 10 // High and Low level of clock
1720 kakl 11 #define HIGHLEV 40 // max. 50us
12 #define LOWLEV 100 // max. 30ms
13 #define TBUF 20
1274 kakl 14  
1284 kakl 15 // SMBus control signals
1274 kakl 16 #define SCL PIN_B0
17 #define SDA PIN_B1
18  
1720 kakl 19 #define mSDA_HIGH() output_float(SDA); // SDA float
1284 kakl 20 #define mSDA_LOW() output_low(SDA); // SDA low
1720 kakl 21 #define mSCL_HIGH() output_float(SCL); // SCL float
1284 kakl 22 #define mSCL_LOW() output_low(SCL); // SCL low
1274 kakl 23  
1720 kakl 24 #define ACK 0
25 #define NACK 1
1274 kakl 26  
27 //**********************************************************************************************
1720 kakl 28 // START CONDITION ON SMBus
1274 kakl 29 //**********************************************************************************************
1720 kakl 30 //Name: START_bit
31 //Function: Generate START condition on SMBus
32 //Parameters: No
33 //Return: No
34 //Comments: Refer to "System Managment BUS(SMBus) specification Version 2.0"
35 // or AN"SMBus communication with MLX90614" on the website www.melexis.com
1274 kakl 36 //**********************************************************************************************
37 void SMB_START_bit(void)
38 {
1275 kakl 39 // disable_interrupts(GLOBAL);
1720 kakl 40 mSDA_HIGH(); // Set SDA line
41 delay_us( TBUF ); // Wait a few microseconds
42 mSCL_HIGH(); // Set SCL line
43 delay_us( TBUF ); // Generate bus free time between Stop
44 // and Start condition (Tbuf=4.7us min)
45 mSDA_LOW(); // Clear SDA line
46 delay_us( TBUF ); // Hold time after (Repeated) Start Condition.
47 // After this period, the first clock is generated.
48 // (Thd:sta=4.0us min)
49 mSCL_LOW(); // Clear SCL line
1275 kakl 50 // enable_interrupts(GLOBAL);
1720 kakl 51 delay_us( TBUF ); // Wait a few microseconds
1274 kakl 52 }
1284 kakl 53  
1274 kakl 54 //*********************************************************************************************
1720 kakl 55 // STOP CONDITION ON SMBus
1274 kakl 56 //*********************************************************************************************
1720 kakl 57 //Name: STOPbit
58 //Function: Generate STOP condition on SMBus
59 //Parameters: No
60 //Return: No
61 //Comments: Refer to "System Managment BUS(SMBus) specification Version 2.0"
62 // or AN"SMBus communication with MLX90614" on the website www.melexis.com
1274 kakl 63 //*********************************************************************************************
64 void SMB_STOP_bit(void)
65 {
1275 kakl 66 // disable_interrupts(GLOBAL);
1274 kakl 67 mSDA_HIGH();
1720 kakl 68 mSCL_LOW(); // Clear SCL line
69 delay_us( TBUF ); // Wait a few microseconds
70 mSDA_LOW(); // Clear SDA line
71 delay_us( TBUF ); // Wait a few microseconds
72 mSCL_HIGH(); // Set SCL line
73 delay_us( TBUF ); // Stop condition setup time(Tsu:sto=4.0us min)
74 mSDA_HIGH(); // Set SDA line
1275 kakl 75 // enable_interrupts(GLOBAL);
1274 kakl 76 }
77  
78  
79 void SMB_send_bit(unsigned char bit_out)
80 {
1275 kakl 81 // disable_interrupts(GLOBAL);
1720 kakl 82 if(bit_out==0) {mSDA_LOW();}
83 else {mSDA_HIGH();}
1274 kakl 84 delay_us(3);
1720 kakl 85 mSCL_HIGH(); // Set SCL line
86 delay_us( HIGHLEV ); // High Level of Clock Pulse
87 mSCL_LOW(); // Clear SCL line
1283 kakl 88  
89 toggle_dome();
90  
1720 kakl 91 delay_us( LOWLEV ); // Low Level of Clock Pulse
92 // mSDA_HIGH(); // Master release SDA line ,
1275 kakl 93 // enable_interrupts(GLOBAL);
94  
1283 kakl 95 toggle_dome();
1720 kakl 96 return;
1274 kakl 97 }
98  
99 unsigned char SMB_Receive_bit(void)
100 {
1720 kakl 101 unsigned char Ack_bit;
1274 kakl 102  
1275 kakl 103 // disable_interrupts(GLOBAL);
1720 kakl 104 mSDA_HIGH(); //_SDA_IO=1; // SDA-input
105 mSCL_HIGH(); // Set SCL line
106 delay_us( HIGHLEV ); // High Level of Clock Pulse
107 if(input(SDA)) Ack_bit=1; // \ Read acknowledgment bit, save it in Ack_bit
108 else Ack_bit=0; // /
109 mSCL_LOW(); // Clear SCL line
1283 kakl 110  
111 toggle_dome();
112  
1720 kakl 113 delay_us( LOWLEV ); // Low Level of Clock Pulse
1275 kakl 114 // enable_interrupts(GLOBAL);
1274 kakl 115  
1283 kakl 116 toggle_dome();
1720 kakl 117 return Ack_bit;
1274 kakl 118 }
119  
120  
121 //*********************************************************************************************
1720 kakl 122 // TRANSMIT DATA ON SMBus
1274 kakl 123 //*********************************************************************************************
1720 kakl 124 //Name: TX_byte
125 //Function: Send a byte on SMBus
126 //Parameters: TX_buffer ( the byte which will be send on the SMBus )
127 //Return: Ack_bit ( acknowledgment bit )
128 //Comments: Sends MSbit first
1274 kakl 129 //*********************************************************************************************
130 unsigned char SMB_TX_byte(unsigned char Tx_buffer)
131 {
1720 kakl 132 unsigned char Bit_counter;
133 unsigned char Ack_bit;
134 unsigned char bit_out;
1274 kakl 135  
1720 kakl 136 for(Bit_counter=8; Bit_counter; Bit_counter--)
137 {
138 if(Tx_buffer&0x80) bit_out=1; // If the current bit of Tx_buffer is 1 set bit_out
139 else bit_out=0; // else clear bit_out
1274 kakl 140  
1720 kakl 141 SMB_send_bit(bit_out); // Send the current bit on SDA
142 Tx_buffer<<=1; // Get next bit for checking
143 }
1274 kakl 144  
1720 kakl 145 Ack_bit=SMB_Receive_bit(); // Get acknowledgment bit
1274 kakl 146  
1720 kakl 147 return Ack_bit;
1275 kakl 148 }
1274 kakl 149  
150 //*********************************************************************************************
1720 kakl 151 // RECEIVE DATA ON SMBus
1274 kakl 152 //*********************************************************************************************
1720 kakl 153 //Name: RX_byte
154 //Function: Receive a byte on SMBus
155 //Parameters: ack_nack (ackowlegment bit)
156 //Return: RX_buffer(Received byte)
157 //Comments: MSbit is received first
1274 kakl 158 //*********************************************************************************************
159 unsigned char SMB_RX_byte(unsigned char ack_nack)
160 {
1720 kakl 161 unsigned char RX_buffer;
162 unsigned char Bit_Counter;
1274 kakl 163  
1720 kakl 164 for(Bit_Counter=8; Bit_Counter; Bit_Counter--)
165 {
166 if(SMB_Receive_bit()) // Get a bit from the SDA line
167 {
168 RX_buffer <<= 1; // If the bit is HIGH save 1 in RX_buffer
169 RX_buffer |=0b00000001;
170 }
171 else
172 {
173 RX_buffer <<= 1; // If the bit is LOW save 0 in RX_buffer
174 RX_buffer &=0b11111110;
175 }
176 }
1274 kakl 177  
1720 kakl 178 SMB_send_bit(ack_nack); // Sends acknowledgment bit
1274 kakl 179  
1720 kakl 180 return RX_buffer;
1274 kakl 181 }
182  
183  
184 unsigned char PEC_calculation(unsigned char pec[]) // CRC calculation
185 {
186 unsigned char crc[6];
187 unsigned char BitPosition=47;
188 unsigned char shift;
189 unsigned char i;
190 unsigned char j;
191 unsigned char temp;
192  
193 do
194 {
195 crc[5]=0; /* Load CRC value 0x000000000107 */
196 crc[4]=0;
197 crc[3]=0;
198 crc[2]=0;
199 crc[1]=0x01;
200 crc[0]=0x07;
1284 kakl 201 BitPosition=47; /* Set maximum bit position at 47 */
1274 kakl 202 shift=0;
203  
204 //Find first 1 in the transmited message
1284 kakl 205 i=5; /* Set highest index */
1274 kakl 206 j=0;
207 while((pec[i]&(0x80>>j))==0 && i>0)
208 {
209 BitPosition--;
210 if(j<7)
211 {
212 j++;
213 }
214 else
215 {
216 j=0x00;
217 i--;
218 }
1283 kakl 219 toggle_dome();
1275 kakl 220 }
1274 kakl 221  
222 shift=BitPosition-8; /*Get shift value for crc value*/
223  
224  
225 //Shift crc value
226 while(shift)
227 {
228 for(i=5; i<0xFF; i--)
229 {
230 if((crc[i-1]&0x80) && (i>0))
231 {
232 temp=1;
233 }
234 else
235 {
236 temp=0;
237 }
238 crc[i]<<=1;
239 crc[i]+=temp;
1275 kakl 240 }
1274 kakl 241 shift--;
1283 kakl 242 toggle_dome();
1275 kakl 243 }
1274 kakl 244  
245 //Exclusive OR between pec and crc
246 for(i=0; i<=5; i++)
247 {
248 pec[i] ^=crc[i];
1275 kakl 249 }
1283 kakl 250 } while(BitPosition>8);
1274 kakl 251  
252 return pec[0];
253 }