Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of PsiSwarmLibrary by
i2c.cpp
00001 /* University of York Robotics Laboratory PsiSwarm Library: I2C Source File 00002 * 00003 * File: i2c.cpp 00004 * 00005 * (C) Dept. Electronics & Computer Science, University of York 00006 * James Hilder, Alan Millard, Alexander Horsfield, Homero Elizondo, Jon Timmis 00007 * 00008 * PsiSwarm Library Version: 0.41 00009 * 00010 * March 2016 00011 * 00012 * 00013 */ 00014 00015 #include "psiswarm.h" 00016 00017 char gpio_byte0; 00018 char gpio_byte1; 00019 char user_id_set = 0; 00020 char wheel_enc_set = 0; 00021 char switch_set = 0; 00022 00023 char emitter_byte = 0x00; 00024 00025 Timeout update_timeout; 00026 00027 char test; 00028 00029 char get_dc_status() 00030 { 00031 IF_read_aux_ic_data(); 00032 return status_dc_in; 00033 } 00034 00035 void IF_set_IR_emitter_output(char emitter, char state) 00036 { 00037 if(emitter <3) { 00038 if(state == 0) { 00039 char shift = 1 << emitter; 00040 emitter_byte &= (0xFF - shift); 00041 } 00042 if(state == 1) { 00043 char shift = 1 << emitter; 00044 emitter_byte |= shift; 00045 } 00046 char data[2]; 00047 data [0] = 0x0A; //Write to OLAT register 00048 data [1] = emitter_byte; //GP0-3 are outputs on aux expansion IC 00049 //pc.printf("%c\n", emitter_byte); 00050 primary_i2c.write(AUX_IC_ADDRESS,data,2,false); 00051 } 00052 } 00053 00054 void IF_set_base_LED(char state) 00055 { 00056 if(state == 0) { 00057 emitter_byte &= 0xF7; 00058 } else emitter_byte |= 0x08; 00059 char data[2]; 00060 data [0] = 0x0A; //Write to OLAT register 00061 data [1] = emitter_byte; //GP0-3 are outputs on aux expansion IC 00062 primary_i2c.write(AUX_IC_ADDRESS,data,2,false); 00063 00064 } 00065 00066 unsigned short IF_read_IR_adc_value(char adc, char index) 00067 { 00068 char address = ADC1_ADDRESS; 00069 if(adc == 2) address=ADC2_ADDRESS; 00070 // Returns the raw sensor value for the IR sensor defined by index (range 0-7). 00071 short value = 0; 00072 // Read a single value from the ADC 00073 if(index<8) { 00074 char apb[1]; 00075 char data[2]; 00076 switch(index) { 00077 case 0: 00078 apb[0]=0x80; 00079 break; 00080 case 1: 00081 apb[0]=0x90; 00082 break; 00083 case 2: 00084 apb[0]=0xA0; 00085 break; 00086 case 3: 00087 apb[0]=0xB0; 00088 break; 00089 case 4: 00090 apb[0]=0xC0; 00091 break; 00092 case 5: 00093 apb[0]=0xD0; 00094 break; 00095 case 6: 00096 apb[0]=0xE0; 00097 break; 00098 case 7: 00099 apb[0]=0xF0; 00100 break; 00101 } 00102 primary_i2c.write(address,apb,1,false); 00103 primary_i2c.read(address,data,2,false); 00104 value=((data[0] % 16)<<8)+data[1]; 00105 if(value > 4096) value=4096; 00106 value=4096-value; 00107 } 00108 return value; 00109 } 00110 00111 char IF_setup_led_expansion_ic(void) 00112 { 00113 //LED expansion IC is PCA9555 00114 //Address is 0100 001x (0x42) {defined by LED_IC_ADDRESS} 00115 //All 16 entries are outputs as they drive LEDs; the relevant registers are 2&3 (output port registers) and 6&7 (config. registers: a 0=output) 00116 //Message structure: {Address-RW}{Command}{Port 0}{Port 1} 00117 //Command bytes: 00000010 (0x02) = Write to output port 00118 //Command bytes: 00000110 (0x06) = Write to config registers 00119 //Note that for the LEDs, 0 = on, 1 = off 00120 //Port 0 = LED 1:4 Red:Green 00121 //Port 1 = LED 5:8 Red:Green 00122 char data [3]; 00123 data [0] = 0x06; //Write config registers 00124 data [1] = 0x00; //All 8 pins in port 0 are outputs (0) 00125 data [2] = 0x00; //All 8 pins in port 1 are outputs (0) 00126 primary_i2c.write(LED_IC_ADDRESS,data,3,false); 00127 00128 //Turn all LEDs on 00129 data [0] = 0x02; //Write to output port 00130 data [1] = 0x00; //Enable LED1-4 (both colours) 00131 data [2] = 0x00; //Enable LED5-8 (both colours) 00132 primary_i2c.write(LED_IC_ADDRESS,data,3,false); 00133 00134 wait(0.05); 00135 //Turn all LEDs off 00136 data [0] = 0x02; //Write to output port 00137 data [1] = 0xFF; //Enable LED1-4 (both colours) 00138 data [2] = 0xFF; //Enable LED5-8 (both colours) 00139 return primary_i2c.write(LED_IC_ADDRESS,data,3,false); 00140 } 00141 00142 //Returns 0 if successful, 1 if test mode button pressed 00143 void IF_setup_gpio_expansion_ic(void) 00144 { 00145 //Main GPIO expansion IC is PCA9555 00146 //Address is 0100 000x (0x40) {defined by GPIO_IC_ADDRESS} 00147 //All 16 entries are inputs; the relevant registers are 0&1 (input port registers), 4&5 (polarity inv. registers) and 6&7 (config. registers: a 0=output) 00148 //Message structure: {Address-RW}{Command}{Port 0}{Port 1} 00149 //Command bytes: 00000010 (0x02) = Write to output port 00150 //Command bytes: 00000110 (0x06) = Write to config registers 00151 //Note that for the LEDs, 0 = on, 1 = off 00152 //Port 0 = PGDL; PGDR; PGDIR; UP; DOWN; LEFT; RIGHT; CENTER 00153 //Port 1 = ENC_LA; ENC_LB; ENC_RA; ENC_RB; ID0; ID1; ID2; ID3 00154 char data [3]; 00155 char okay = 1; 00156 data [0] = 0x06; //Write config registers 00157 data [1] = 0xFF; //All 8 pins in port 0 are inputs (1) 00158 data [2] = 0xFF; //All 8 pins in port 1 are inputs (1) 00159 if(primary_i2c.write(GPIO_IC_ADDRESS,data,3,false) != 0) { 00160 system_warnings += 2; 00161 okay = 0; 00162 debug("- WARNING: No I2C acknowledge for main GPIO IC\n"); 00163 if(HALT_ON_GPIO_ERROR){ 00164 debug("- PROGRAM HALTED. Check that robot is switched on!\n"); 00165 while(1){ 00166 mbed_led1=1; 00167 mbed_led2=1; 00168 mbed_led3=0; 00169 mbed_led4=0; 00170 wait(0.25); 00171 mbed_led1=0; 00172 mbed_led2=0; 00173 mbed_led3=1; 00174 mbed_led4=1; 00175 wait(0.25); 00176 } 00177 } 00178 } 00179 //Set all inputs to polarity-inverted (so a logic low = 1) 00180 data [0] = 0x04; //Write to polarity inversion ports 00181 data [1] = 0xF8; //Invert polarity of all switch input bits in input port 0 [but not power-good inputs] 00182 data [2] = 0xFF; //Invert polarity of all bits in input port 1 00183 primary_i2c.write(GPIO_IC_ADDRESS,data,3,false); 00184 00185 wait(0.01); 00186 00187 //Read data 00188 char read_data[2]; 00189 char command[1]; //Command to read from input port 0 00190 command[0]=0; 00191 primary_i2c.write(GPIO_IC_ADDRESS,command,1,false); 00192 primary_i2c.read(GPIO_IC_ADDRESS,read_data,2,false); 00193 gpio_byte0 = read_data[0]; 00194 //char ret_val = (gpio_byte0 & 0xF8) >> 3; //Returns a >0 value if a button is being pushed 00195 gpio_byte1 = read_data[1]; 00196 if(okay && testing_voltage_regulators_flag)debug("- Checking 3.3V voltage regulators\n"); 00197 IF_parse_gpio_byte0(gpio_byte0); 00198 IF_parse_gpio_byte1(gpio_byte1); 00199 testing_voltage_regulators_flag = 0; 00200 //Setup interrupt handler for GPIO interrupts 00201 gpio_interrupt.mode(PullUp); 00202 gpio_interrupt.rise(&IF_handle_gpio_interrupt); 00203 //pc.printf("%c %c",gpio_byte0,gpio_byte1); 00204 00205 //Secondary GPIO expansion IC is MCP23009 00206 //Address is 0100 111 (0x4E) {defined by AUX_IC_ADDRESS} 00207 //GP0,1,2,3 are outputs for driving infrared emitters and the base LED 00208 //IODIR register wants to be 0xF0 (1=input, 0=output) 00209 data [0] = 0x00; //Write to IODIR register 00210 data [1] = 0xF0; //Set GP0-3 as outputs 00211 primary_i2c.write(AUX_IC_ADDRESS,data,2,false); 00212 00213 if(primary_i2c.write(AUX_IC_ADDRESS,data,2,false) != 0) { 00214 system_warnings += 4; 00215 debug("- WARNING: No I2C acknowledge for aux GPIO IC\n"); 00216 } 00217 data [0] = 0x06; //Write to GPPU register 00218 data [1] = 0x3F; //Set GP0-3 as active pull-up outputs and P4,P5 as pull-up inputs 00219 primary_i2c.write(AUX_IC_ADDRESS,data,2,false); 00220 00221 //My interrupt is not so reliable: poll with a 50ms timeout in case interrupts aren't handled 00222 update_timeout.attach_us(&IF_update_gpio_inputs,50000); 00223 //return ret_val; 00224 } 00225 00226 void IF_read_aux_ic_data() 00227 { 00228 //Read the values of the input pins on the auxilliary GPIO expander 00229 char write_data [1]; 00230 char read_data [1]; 00231 write_data[0] = 0x09; 00232 primary_i2c.write(AUX_IC_ADDRESS,write_data,1,false); 00233 primary_i2c.read(AUX_IC_ADDRESS,read_data,1,false); 00234 char old_charging_state = status_dc_in; 00235 status_dc_in = 1-((read_data[0] & 0x10) >> 4); 00236 if(status_dc_in!=old_charging_state){ 00237 if(status_dc_in == 0)debug("No DC input\n"); 00238 else debug("DC input to charge pins\n"); 00239 } 00240 //pc.printf("Aux IC Data:%X Charge:%d\n",read_data[0],charge_in); 00241 } 00242 00243 void IF_parse_gpio_byte0(char byte) 00244 { 00245 gpio_byte0 = byte; 00246 //GPIO byte zero contains the power line traces and the switch states 00247 char current_switch = ((gpio_byte0 & 0xF8) >> 3); 00248 if(switch_set == 1) { 00249 if(current_switch != switch_byte) { 00250 previous_switch_byte = switch_byte; 00251 switch_byte = current_switch; 00252 event++; 00253 switch_event = 1; 00254 } 00255 } else { 00256 switch_byte = current_switch; 00257 switch_set = 1; 00258 } 00259 if(((gpio_byte0 & 0x01)) != power_good_motor_left){ 00260 power_good_motor_left = (gpio_byte0 & 0x01); 00261 if(!power_good_motor_left){ 00262 if(testing_voltage_regulators_flag || SHOW_VR_WARNINGS)debug("- WARNING: Voltage regulator left motor low\n"); 00263 } 00264 else if(testing_voltage_regulators_flag)debug("- Power good left motor v.reg\n"); 00265 } 00266 if(((gpio_byte0 & 0x02) >> 1) != power_good_motor_right){ 00267 power_good_motor_right = (gpio_byte0 & 0x02) >> 1; 00268 if(!power_good_motor_right){ 00269 if(testing_voltage_regulators_flag || SHOW_VR_WARNINGS)debug("- WARNING: Voltage regulator right motor low\n"); 00270 } 00271 else if(testing_voltage_regulators_flag)debug("- Power good right motor v.reg\n"); 00272 } 00273 if(((gpio_byte0 & 0x04) >> 2) != power_good_infrared){ 00274 power_good_infrared = (gpio_byte0 & 0x04) >> 2; 00275 if(!power_good_infrared){ 00276 if(testing_voltage_regulators_flag || SHOW_VR_WARNINGS)debug("- WARNING: Voltage regulator infrared low\n"); 00277 } 00278 else if(testing_voltage_regulators_flag)debug("- Power good infrared and aux v.reg\n"); 00279 } 00280 if(USE_LED4_FOR_VR_WARNINGS){ 00281 mbed_led4 = (!power_good_motor_left || !power_good_motor_right || !power_good_infrared); 00282 } 00283 //Halt the system if settings flag is set and all v-regs are bad [usually this means robot is switched off!] 00284 if(HALT_ON_ALL_VREGS_LOW && !power_good_motor_left && !power_good_motor_right && !power_good_infrared){ 00285 debug("- PROGRAM HALTED. Check that robot is switched on!\n"); 00286 while(1){ 00287 mbed_led1=1; 00288 mbed_led2=0; 00289 mbed_led3=1; 00290 mbed_led4=0; 00291 wait(0.25); 00292 mbed_led1=0; 00293 mbed_led2=1; 00294 mbed_led3=0; 00295 mbed_led4=1; 00296 wait(0.25); 00297 } 00298 } 00299 } 00300 00301 void IF_parse_gpio_byte1(char byte) 00302 { 00303 gpio_byte1 = byte; 00304 //GPIO byte one contains the wheel encoders and the ID switch 00305 char current_id = ((gpio_byte1 & 0xF0)>> 4); 00306 if(user_id_set == 1) { 00307 if(robot_id != current_id) { 00308 previous_robot_id = robot_id; 00309 robot_id = current_id; 00310 event++; 00311 change_id_event = 1; 00312 } 00313 } else { 00314 robot_id = current_id; 00315 user_id_set = 1; 00316 } 00317 char current_encoder = (gpio_byte1 & 0x0F); 00318 if(wheel_enc_set == 1) { 00319 if(wheel_encoder_byte != current_encoder) { 00320 previous_wheel_encoder_byte = wheel_encoder_byte; 00321 wheel_encoder_byte = current_encoder; 00322 event++; 00323 encoder_event = 1; 00324 } 00325 } else { 00326 wheel_encoder_byte = current_encoder; 00327 wheel_enc_set = 1; 00328 } 00329 } 00330 00331 void IF_handle_gpio_interrupt() 00332 { 00333 test = 1-test; 00334 if(USE_LED3_FOR_INTERRUPTS) mbed_led3 = test; 00335 IF_update_gpio_inputs(); 00336 } 00337 00338 char IF_is_switch_pressed() 00339 { 00340 //Read data 00341 char data[1]; 00342 char command[1] = {0}; //Command to read from input port 0 00343 primary_i2c.write(GPIO_IC_ADDRESS,command,1,false); 00344 primary_i2c.read(GPIO_IC_ADDRESS,data,1,false); 00345 return (data[0] & 0x80); //Returns a 1 if the center button is being pushed 00346 } 00347 00348 00349 char IF_get_switch_state() 00350 { 00351 //Read data 00352 char data[1]; 00353 char command[1] = {0}; //Command to read from input port 0 00354 primary_i2c.write(GPIO_IC_ADDRESS,command,1,false); 00355 primary_i2c.read(GPIO_IC_ADDRESS,data,1,false); 00356 return (data[0] & 0xF8) >> 3; //Returns the current switch state 00357 } 00358 00359 void IF_update_gpio_inputs() 00360 { 00361 update_timeout.detach(); 00362 //Read data 00363 char data[2]; 00364 char command[1] = {0}; //Command to read from input port 0 00365 primary_i2c.write(GPIO_IC_ADDRESS,command,1,false); 00366 primary_i2c.read(GPIO_IC_ADDRESS,data,2,false); 00367 if(data[0]!=gpio_byte0) { 00368 IF_parse_gpio_byte0(data[0]); 00369 } 00370 if(data[1]!=gpio_byte1) { 00371 IF_parse_gpio_byte1(data[1]); 00372 } 00373 update_timeout.attach_us(&IF_update_gpio_inputs,50000); 00374 } 00375 00376 00377 void IF_write_to_led_ic(char byte_0, char byte_1) 00378 { 00379 //Set LEDs 00380 char data[3]; 00381 data [0] = 0x02; //Write to output port 00382 data [1] = byte_0; 00383 data [2] = byte_1; 00384 primary_i2c.write(LED_IC_ADDRESS,data,3,false); 00385 } 00386 00387 00388 void IF_setup_temperature_sensor() 00389 { 00390 char data[3]; 00391 data[0] = 0x04; //Set critical temp limit 00392 data[1] = TEMPERATURE_CRITICAL_HI; 00393 data[2] = TEMPEARTURE_CRITICAL_LO; 00394 primary_i2c.write(TEMPERATURE_ADDRESS,data,3,false); 00395 data[0] = 0x02; //Set high temp limit 00396 data[1] = TEMPERATURE_HIGH_HI; 00397 data[2] = TEMPEARTURE_HIGH_LO; 00398 primary_i2c.write(TEMPERATURE_ADDRESS,data,3,false); 00399 data[0] = 0x03; //Set low temp limit 00400 data[1] = TEMPERATURE_LOW_HI; 00401 data[2] = TEMPEARTURE_LOW_LO; 00402 primary_i2c.write(TEMPERATURE_ADDRESS,data,3,false); 00403 } 00404 00405 float IF_read_from_temperature_sensor() 00406 { 00407 char command[1] = {0x05}; //Write to Ta Register 00408 char data[3]; 00409 signed int temp; 00410 float temperature; 00411 primary_i2c.write(TEMPERATURE_ADDRESS,command,1,false); 00412 primary_i2c.read(TEMPERATURE_ADDRESS,data,2,false); 00413 00414 //Convert the temperature data 00415 //First Check flag bits 00416 char UpperByte = data[0]; 00417 char LowerByte = data[1]; 00418 if ((UpperByte & 0x80) == 0x80) { 00419 debug("- WARNING: Temperature sensor reports critical temperature\n"); 00420 } 00421 if ((UpperByte & 0x40) == 0x40) { 00422 debug("- WARNING: Temperature sensor reports above upper limit\n"); 00423 } 00424 if ((UpperByte & 0x20) == 0x20) { 00425 debug("- WARNING: Temperature sensor reports below lower limit\n"); 00426 } 00427 UpperByte = UpperByte & 0x1F; //Clear flag bits 00428 if ((UpperByte & 0x10) == 0x10) { 00429 UpperByte = UpperByte & 0x0F; //Clear SIGN 00430 temp = (UpperByte * 256) + LowerByte; 00431 temperature = - (temp / 16.0f); 00432 } else { 00433 temp = (UpperByte * 256) + LowerByte; 00434 temperature = (temp / 16.0f); 00435 } 00436 return temperature; 00437 }
Generated on Sat Jul 16 2022 05:17:35 by
1.7.2
