Rev 1283 Rev 1284
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_B0
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); //output_high(SCL); // SCL high 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 45 delay_us( TBUF ); // Hold time after (Repeated) Start Condition.
46 // Condition. 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 // STOP CONDITION ON SMBus 54 // STOP CONDITION ON SMBus
54 //********************************************************************************************* 55 //*********************************************************************************************
55 //Name: STOPbit 56 //Name: STOPbit
56 //Function: Generate STOP condition on SMBus 57 //Function: Generate STOP condition on SMBus
57 //Parameters: No 58 //Parameters: No
58 //Return: No 59 //Return: No
59 //Comments: Refer to "System Managment BUS(SMBus) specification Version 2.0" 60 //Comments: Refer to "System Managment BUS(SMBus) specification Version 2.0"
60 // 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
61 //********************************************************************************************* 62 //*********************************************************************************************
62 void SMB_STOP_bit(void) 63 void SMB_STOP_bit(void)
63 { 64 {
64 // disable_interrupts(GLOBAL); 65 // disable_interrupts(GLOBAL);
65 mSDA_HIGH(); 66 mSDA_HIGH();
66 mSCL_LOW(); // Clear SCL line 67 mSCL_LOW(); // Clear SCL line
67 delay_us( TBUF ); // Wait a few microseconds 68 delay_us( TBUF ); // Wait a few microseconds
68 mSDA_LOW(); // Clear SDA line 69 mSDA_LOW(); // Clear SDA line
69 delay_us( TBUF ); // Wait a few microseconds 70 delay_us( TBUF ); // Wait a few microseconds
70 mSCL_HIGH(); // Set SCL line 71 mSCL_HIGH(); // Set SCL line
71 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)
72 mSDA_HIGH(); // Set SDA line 73 mSDA_HIGH(); // Set SDA line
73 // enable_interrupts(GLOBAL); 74 // enable_interrupts(GLOBAL);
74 } 75 }
75   76  
76   77  
77 void SMB_send_bit(unsigned char bit_out) 78 void SMB_send_bit(unsigned char bit_out)
78 { 79 {
79 // disable_interrupts(GLOBAL); 80 // disable_interrupts(GLOBAL);
80 if(bit_out==0) {mSDA_LOW();} 81 if(bit_out==0) {mSDA_LOW();}
81 else {mSDA_HIGH();} 82 else {mSDA_HIGH();}
82 delay_us(3); 83 delay_us(3);
83 mSCL_HIGH(); // Set SCL line 84 mSCL_HIGH(); // Set SCL line
84 delay_us( HIGHLEV ); // High Level of Clock Pulse 85 delay_us( HIGHLEV ); // High Level of Clock Pulse
85 mSCL_LOW(); // Clear SCL line 86 mSCL_LOW(); // Clear SCL line
86   87  
87 toggle_dome(); 88 toggle_dome();
88   89  
89 delay_us( LOWLEV ); // Low Level of Clock Pulse 90 delay_us( LOWLEV ); // Low Level of Clock Pulse
90 // mSDA_HIGH(); // Master release SDA line , 91 // mSDA_HIGH(); // Master release SDA line ,
91 // enable_interrupts(GLOBAL); 92 // enable_interrupts(GLOBAL);
92   93  
93 toggle_dome(); 94 toggle_dome();
94 return; 95 return;
95 } 96 }
96   97  
97 unsigned char SMB_Receive_bit(void) 98 unsigned char SMB_Receive_bit(void)
98 { 99 {
99 unsigned char Ack_bit; 100 unsigned char Ack_bit;
100   101  
101 // disable_interrupts(GLOBAL); 102 // disable_interrupts(GLOBAL);
102 mSDA_HIGH(); //_SDA_IO=1; // SDA-input 103 mSDA_HIGH(); //_SDA_IO=1; // SDA-input
103 mSCL_HIGH(); // Set SCL line 104 mSCL_HIGH(); // Set SCL line
104 delay_us( HIGHLEV ); // High Level of Clock Pulse 105 delay_us( HIGHLEV ); // High Level of Clock Pulse
105 if(input(SDA)) Ack_bit=1; // \ Read acknowledgment bit, save it in Ack_bit 106 if(input(SDA)) Ack_bit=1; // \ Read acknowledgment bit, save it in Ack_bit
106 else Ack_bit=0; // / 107 else Ack_bit=0; // /
107 mSCL_LOW(); // Clear SCL line 108 mSCL_LOW(); // Clear SCL line
108   109  
109 toggle_dome(); 110 toggle_dome();
110   111  
111 delay_us( LOWLEV ); // Low Level of Clock Pulse 112 delay_us( LOWLEV ); // Low Level of Clock Pulse
112 // enable_interrupts(GLOBAL); 113 // enable_interrupts(GLOBAL);
113   114  
114 toggle_dome(); 115 toggle_dome();
115 return Ack_bit; 116 return Ack_bit;
116 } 117 }
117   118  
118   119  
119 //********************************************************************************************* 120 //*********************************************************************************************
120 // TRANSMIT DATA ON SMBus 121 // TRANSMIT DATA ON SMBus
121 //********************************************************************************************* 122 //*********************************************************************************************
122 //Name: TX_byte 123 //Name: TX_byte
123 //Function: Send a byte on SMBus 124 //Function: Send a byte on SMBus
124 //Parameters: TX_buffer ( the byte which will be send on the SMBus ) 125 //Parameters: TX_buffer ( the byte which will be send on the SMBus )
125 //Return: Ack_bit ( acknowledgment bit ) 126 //Return: Ack_bit ( acknowledgment bit )
126 //Comments: Sends MSbit first 127 //Comments: Sends MSbit first
127 //********************************************************************************************* 128 //*********************************************************************************************
128 unsigned char SMB_TX_byte(unsigned char Tx_buffer) 129 unsigned char SMB_TX_byte(unsigned char Tx_buffer)
129 { 130 {
130 unsigned char Bit_counter; 131 unsigned char Bit_counter;
131 unsigned char Ack_bit; 132 unsigned char Ack_bit;
132 unsigned char bit_out; 133 unsigned char bit_out;
133   134  
134 for(Bit_counter=8; Bit_counter; Bit_counter--) 135 for(Bit_counter=8; Bit_counter; Bit_counter--)
135 { 136 {
136 if(Tx_buffer&0x80) bit_out=1; // If the current bit of Tx_buffer is 1 set bit_out 137 if(Tx_buffer&0x80) bit_out=1; // If the current bit of Tx_buffer is 1 set bit_out
137 else bit_out=0; // else clear bit_out 138 else bit_out=0; // else clear bit_out
138   139  
139 SMB_send_bit(bit_out); // Send the current bit on SDA 140 SMB_send_bit(bit_out); // Send the current bit on SDA
140 Tx_buffer<<=1; // Get next bit for checking 141 Tx_buffer<<=1; // Get next bit for checking
141 } 142 }
142   143  
143 Ack_bit=SMB_Receive_bit(); // Get acknowledgment bit 144 Ack_bit=SMB_Receive_bit(); // Get acknowledgment bit
144   145  
145 return Ack_bit; 146 return Ack_bit;
146 } 147 }
147   148  
148 //********************************************************************************************* 149 //*********************************************************************************************
149 // RECEIVE DATA ON SMBus 150 // RECEIVE DATA ON SMBus
150 //********************************************************************************************* 151 //*********************************************************************************************
151 //Name: RX_byte 152 //Name: RX_byte
152 //Function: Receive a byte on SMBus 153 //Function: Receive a byte on SMBus
153 //Parameters: ack_nack (ackowlegment bit) 154 //Parameters: ack_nack (ackowlegment bit)
154 //Return: RX_buffer(Received byte) 155 //Return: RX_buffer(Received byte)
155 //Comments: MSbit is received first 156 //Comments: MSbit is received first
156 //********************************************************************************************* 157 //*********************************************************************************************
157 unsigned char SMB_RX_byte(unsigned char ack_nack) 158 unsigned char SMB_RX_byte(unsigned char ack_nack)
158 { 159 {
159 unsigned char RX_buffer; 160 unsigned char RX_buffer;
160 unsigned char Bit_Counter; 161 unsigned char Bit_Counter;
161   162  
162 for(Bit_Counter=8; Bit_Counter; Bit_Counter--) 163 for(Bit_Counter=8; Bit_Counter; Bit_Counter--)
163 { 164 {
164 if(SMB_Receive_bit()) // Get a bit from the SDA line 165 if(SMB_Receive_bit()) // Get a bit from the SDA line
165 { 166 {
166 RX_buffer <<= 1; // If the bit is HIGH save 1 in RX_buffer 167 RX_buffer <<= 1; // If the bit is HIGH save 1 in RX_buffer
167 RX_buffer |=0b00000001; 168 RX_buffer |=0b00000001;
168 } 169 }
169 else 170 else
170 { 171 {
171 RX_buffer <<= 1; // If the bit is LOW save 0 in RX_buffer 172 RX_buffer <<= 1; // If the bit is LOW save 0 in RX_buffer
172 RX_buffer &=0b11111110; 173 RX_buffer &=0b11111110;
173 } 174 }
174 } 175 }
175   176  
176 SMB_send_bit(ack_nack); // Sends acknowledgment bit 177 SMB_send_bit(ack_nack); // Sends acknowledgment bit
177   178  
178 return RX_buffer; 179 return RX_buffer;
179 } 180 }
180   181  
181   182  
182 unsigned char PEC_calculation(unsigned char pec[]) // CRC calculation 183 unsigned char PEC_calculation(unsigned char pec[]) // CRC calculation
183 { 184 {
184 unsigned char crc[6]; 185 unsigned char crc[6];
185 unsigned char BitPosition=47; 186 unsigned char BitPosition=47;
186 unsigned char shift; 187 unsigned char shift;
187 unsigned char i; 188 unsigned char i;
188 unsigned char j; 189 unsigned char j;
189 unsigned char temp; 190 unsigned char temp;
190   191  
191 do 192 do
192 { 193 {
193 crc[5]=0; /* Load CRC value 0x000000000107 */ 194 crc[5]=0; /* Load CRC value 0x000000000107 */
194 crc[4]=0; 195 crc[4]=0;
195 crc[3]=0; 196 crc[3]=0;
196 crc[2]=0; 197 crc[2]=0;
197 crc[1]=0x01; 198 crc[1]=0x01;
198 crc[0]=0x07; 199 crc[0]=0x07;
199 BitPosition=47; /* Set maximum bit position at 47 */ 200 BitPosition=47; /* Set maximum bit position at 47 */
200 shift=0; 201 shift=0;
201   202  
202 //Find first 1 in the transmited message 203 //Find first 1 in the transmited message
203 i=5; /* Set highest index */ 204 i=5; /* Set highest index */
204 j=0; 205 j=0;
205 while((pec[i]&(0x80>>j))==0 && i>0) 206 while((pec[i]&(0x80>>j))==0 && i>0)
206 { 207 {
207 BitPosition--; 208 BitPosition--;
208 if(j<7) 209 if(j<7)
209 { 210 {
210 j++; 211 j++;
211 } 212 }
212 else 213 else
213 { 214 {
214 j=0x00; 215 j=0x00;
215 i--; 216 i--;
216 } 217 }
217 toggle_dome(); 218 toggle_dome();
218 } 219 }
219   220  
220 shift=BitPosition-8; /*Get shift value for crc value*/ 221 shift=BitPosition-8; /*Get shift value for crc value*/
221   222  
222   223  
223 //Shift crc value 224 //Shift crc value
224 while(shift) 225 while(shift)
225 { 226 {
226 for(i=5; i<0xFF; i--) 227 for(i=5; i<0xFF; i--)
227 { 228 {
228 if((crc[i-1]&0x80) && (i>0)) 229 if((crc[i-1]&0x80) && (i>0))
229 { 230 {
230 temp=1; 231 temp=1;
231 } 232 }
232 else 233 else
233 { 234 {
234 temp=0; 235 temp=0;
235 } 236 }
236 crc[i]<<=1; 237 crc[i]<<=1;
237 crc[i]+=temp; 238 crc[i]+=temp;
238 } 239 }
239 shift--; 240 shift--;
240 toggle_dome(); 241 toggle_dome();
241 } 242 }
242   243  
243 //Exclusive OR between pec and crc 244 //Exclusive OR between pec and crc
244 for(i=0; i<=5; i++) 245 for(i=0; i<=5; i++)
245 { 246 {
246 pec[i] ^=crc[i]; 247 pec[i] ^=crc[i];
247 } 248 }
248 } while(BitPosition>8); 249 } while(BitPosition>8);
249   250  
250 return pec[0]; 251 return pec[0];
251 } 252 }