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