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