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