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