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