Simon Kahn ECE 6483 Exam 2 1) A) #ifndef ASENSOR_H #define ASENSOR_H #include “mbed.h” //the sensor’s 7-bit address #define SENSOR_ADDRESS 0b1110100 //declares an mbed::I2C instance //that must be defined in the main.cpp file extern mbed::I2C Wire; int GetVersion(); int GetTotalStrength(); int GetEvent(); #endif B) #include “ASensor.h” //The touchpad datasheet did not directly indicate //support for multi-byte sequential burst reads, //so I chose to write the address for each byte //in my implementation ( which is always supported by i2c) //the sensor’s address for read transactions static constexpr uint8_t read_addr=((SENSOR_ADDRESS<<1u)|1U); //the sensor's address for write transactions static constexpr uint8_t write_addr=(SENSOR_ADDRESS<<1U); //a buffer used to store data received from the remote //sensor over i2c static uint8_t read_buf[20]; //3 bytes to send (after sending the sensor address) //to close the communication window static const uint8_t com_window_end_buf[3]={0xEE,0xEE,0xFF}; //the 16-bit register address that holds the sensor's major version //broken down into 2 8-bit values for easy sending over i2c static const uint8_t major_ver_addr[2]={0x00,0x04}; //the 16-bit register address that holds the sensor's minor version //broken down into 2 8-bit values for easy sending over i2c static const uint8_t minor_ver_addr[2]={0x00,0x05}; //the 16-bit register address that holds the 8 MSB's of the //sensor's touch strength. //broken down into 2 8-bit values for easy sending over i2c static const uint8_t touch_strength_high_addr[2]={0x00,0x1A}; //the 16-bit register address that holds the 8 LSB's of the //sensor's touch strength. //broken down into 2 8-bit values for easy sending over i2c static const uint8_t touch_strength_low_addr[2]={0x00,0x1B}; //the 16-bit register address that holds the first set of //detected events. //broken down into 2 8-bit values for easy sending over i2c static const uint8_t gesture_event_high_addr[2]={0x00,0x0D}; //the 16-bit register address that holds the second set of //detected events. //broken down into 2 8-bit values for easy sending over i2c static const uint8_t gesture_event_low_addr[2]={0x00,0x0E}; //static const uint8_t major_ver_addr[2]={0x00,0x04}; //static const uint8_t minor_ver_addr[2]={0x00,0x05}; //The data sheet specified that a stop bit alone would not //terminate an i2c communication window and allow normal sampling //to proceed, so this function implements the correct behavior outlined //in the data sheet to explicitly end the communication window. static void terminate_com_window(){ Wire.write(write_addr,(const char *)com_window_end_buf,3,false); } //the format of the return value is as follow: //bits 31-16: not used //bits 15-8 : major version //bits 7-0 : minor version int GetVersion(){ int version=0; //sends the write address followed by the address of the sensor's //major version register, followed by a repeated start Wire.write(write_addr,(const char *) major_ver_addr,2,true); //sends the read address, and stores the received register value // at index 0 in the read_buf, ending with a stop bit. Wire.read(read_addr,(char*)&read_buf[0],1,false); //places the major version in bit position 15-8 of the return variable version|=((uint8_t)read_buf[0]<<8); //sends the write address followed by the address of the sensor's //minor version register, followed by a repeated start Wire.write(write_addr,(const char *) minor_ver_addr,2,true); //sends the read address, and stores the received register value // at index 1 in the read_buf, ending with a stop bit. Wire.read(read_addr,(char*)&read_buf[1],1,false); //places the minor version in bit position 7-0 of the return variable version|=((uint8_t)read_buf[1]); //closes the communication window with the sensor terminate_com_window(); return version; } //the format of the return value is as follow: //bits 31-16: not used //bits 15-0 : total strength; int GetTotalStrength(){ int total_strength=0; //sends the write address followed by the address of the sensor's //register that has the 8 MSB's of the total strength, followed by a repeated start Wire.write(write_addr,(const char *) touch_strength_high_addr,2,true); //sends the read address, and stores the received register value // at index 0 in the read_buf, ending with a stop bit. Wire.read(read_addr,(char*)&read_buf[0],1,false); //places the received MSB's in bit position 15-8 total_strength|=((uint8_t)read_buf[0]<<8); //sends the write address followed by the address of the sensor's //register that has the 8 LSB's of the total strength, followed by a repeated start Wire.write(write_addr,(const char *) touch_strength_low_addr,2,true); //sends the read address, and stores the received register value // at index 0 in the read_buf, ending with a stop bit. Wire.read(read_addr,(char*)&read_buf[1],1,false); //places the received MSB's in bit position 7-0 total_strength|=((uint8_t)read_buf[1]); //closes the communication window with the sensor terminate_com_window(); return total_strength; } /* just returning a different enumerated type corresponding to an individual event would prevent you from being able to recognize multiple simultaneous event occurrences. so I chose to adopt the following bit-field approach for the return value, where a 1 in the corresponding bit position indicates the event was triggered (active), and a 0 means it was not. event : |swipe | swipe | swipe | swipe | press and | single | zoom | scroll | 2 finger | | y- | y+ | x+ | x- | hold | tap | | | tap | -------------------------------------------------------------------------------- bit position: | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | */ int GetEvent(){ int events=0; //sends the write address followed by the address of the sensor's //first event register, followed by a repeated start Wire.write(write_addr,(const char *) gesture_event_high_addr,2,true); //sends the read address, and stores the received register value // at index 0 in the read_buf, ending with a stop bit. Wire.read(read_addr,(char*)&read_buf[0],1,false); //sends the write address followed by the address of the sensor's //second event register, followed by a repeated start Wire.write(write_addr,(const char *) gesture_event_low_addr,2,true); //sends the read address, and stores the received register value // at index 1 in the read_buf, ending with a stop bit. Wire.read(read_addr,(char*)&read_buf[1],1,false); //closes the communication window with the sensor terminate_com_window(); //extracts and formats the events for bit positions 8-3 events|=static_cast((0b00111111&read_buf[0]))<<3; //extracts and formats the events for bit positions 2-0 events|=static_cast((0b00000111&read_buf[1])); return events; } C/D) #include "mbed.h" #include "ASensor.h" // I2C1_SDA I2C1_SCL //assume these pins are externally pulled up. I2C Wire(PB_7,PB_6); //PA_9 is connected to Serial1_TX //PA_10 is connected to Serial1_RX BufferedSerial Serial(PA_9,PA_10,9600); //strings to send out over the UART //corresponding to each events occurrence. //they are intentionally in "reverse order" //to optimize iterating. char event_strings[9][16]{ "2 finger tapn", "scrolln", "zoomn", "single tapn", "press and holdn", "swipe x-n", "swipe x+n", "swipe y+n", "swipe y-n" }; //the lengths of each possible event string (excluding the null character); int string_lengths[9] = { 13,7,5,11,15,9,9,9,9 }; int main(){ //configure I2C to fast mode Wire.frequency(400000); //configure UART with 8 data bits, no parity bits, //and 1 stop bit. Serial.set_format(8,BufferedSerial::None,1); int result = 0; while(1){ //sleep for 500ms thread_sleep_for(500); result = GetEvent(); //iterates through the returned bitfields, //checking if each event was triggered, //and if it was, the corresponding message //is printed to the console for(int i = 0; i < 9;i++){ //checks if the bitfield is 1, //and if it is, the corresponding message //is sent out over Serial if(((result >> i) & 0x01) == 1){ Serial.write(event_strings[i],string_lengths[i]); } } } } 2) A/B) #include “mbed.h” #include “ASensor.h” //the specific flag that will trigger //the main loop to call GetEvent() //and print its result. The flag will be set //with a ticker callback function #define TRIGGER 1 // I2C1_SDA I2C1_SCL //assume these pins are externally pulled up. I2C Wire(PB_7,PB_6); //PA_9 is connected to Serial1_TX //PA_10 is connected to Serial1_RX BufferedSerial Serial(PA_9,PA_10,9600); //strings to send out over the UART //corresponding to each events occurrence. //they are intentionally in “reverse order” //to optimize iterating. char event_strings[9][16]{ “2 finger tapn”, “scrolln”, “zoomn”, “single tapn”, “press and holdn”, “swipe x-n”, “swipe x+n”, “swipe y+n”, “swipe y-n” }; //the lengths of each possible event string (excluding the null character); int string_lengths[9] = { 13,7,5,11,15,9,9,9,9 }; Ticker periodic; EventFlags TriggerFlag; void set_trigger(){ TriggerFlag.set(TRIGGER); } int main(){ //configure I2C to fast mode Wire.frequency(400000); //configure UART with 8 data bits, no parity bits, //and 1 stop bit. Serial.set_format(8,BufferedSerial::None,1); int result = 0; //attaches the set_trigger() function //to the Ticker, which will call the function //every 500 milliseconds periodic.attach(set_trigger,500ms); while(1){ //waits for the trigger flag to be set by the //attached ticker function. After the flag is set, //the wait_all function will wake up the main thread, //and clear the flag to prepare for the next interrupt //once it fully passes through one iteration of the while loop TriggerFlag.wait_all(TRIGGER); result = GetEvent(); //iterates through the returned bitfields, //checking if each event was triggered, //and if it was, the corresponding message //is printed to the console for(int i = 0; i < 9;i++){ //checks if the bitfield is 1, //and if it is, the corresponding message //is sent out over Serial if(((result >> i) & 0x01) == 1){ Serial.write(event_strings[i],string_lengths[i]); } } } } 3) #include “mbed.h” #include “ASensor.h” //the specific flag that will trigger //the main loop to call GetEvent() //and print its result. The flag will be set //with a ticker callback function #define TRIGGER 1 // I2C1_SDA I2C1_SCL //assume these pins are externally pulled up. I2C Wire(PB_7,PB_6); //PA_9 is connected to Serial1_TX //PA_10 is connected to Serial1_RX BufferedSerial Serial(PA_9,PA_10,9600); //strings to send out over the UART //corresponding to each events occurrence. //they are intentionally in “reverse order” //to optimize iterating. char event_strings[9][16]{ “2 finger tapn”, “scrolln”, “zoomn”, “single tapn”, “press and holdn”, “swipe x-n”, “swipe x+n”, “swipe y+n”, “swipe y-n” }; //the lengths of each possible event string (excluding the null character); int string_lengths[9] = { 13,7,5,11,15,9,9,9,9 }; Ticker periodic; //Event Flags used to trigger //periodic events. EventFlags TriggerFlag; //Our board’s LEDs aren’t actually //connected to pwm pins, but assume //that for this problem they are. PwmOut pwm_str(LED0); void set_trigger(){ TriggerFlag.set(TRIGGER); } int main(){ //configure I2C to fast mode Wire.frequency(400000); //configure UART with 8 data bits, no parity bits, //and 1 stop bit. Serial.set_format(8,BufferedSerial::None,1); int result = 0; //sets the pwm signals //period to 50 milliseconds pwm_str.period(50ms); //set the initial pwm //duty cycle to an arbitrary value. //I chose 50% pwm_str.write(0.5f); //attaches the set_trigger() function //to the Ticker, which will call the function //every 500 milliseconds periodic.attach(set_trigger,500ms); while(1){ //waits for the trigger flag to be set by the //attached ticker function. After the flag is set, //the wait_all function will wake up the main thread, //and clear the flag to prepare for the next interrupt //once it fully passes through one iteration of the while loop TriggerFlag.wait_all(TRIGGER); result = GetEvent(); //calls GetTotalStrength(), casts its //return value to a float, divides that value //by the maximum possible value of a 16 bit number, //and sets the result as the pwm duty cycle. pwm_str.write( static_cast(GetTotalStrength()) / (65535.0f) ); //iterates through the returned bitfields, //checking if each event was triggered, //and if it was, the corresponding message //is printed to the console for(int i = 0; i < 9;i++){ //checks if the bitfield is 1, //and if it is, the corresponding message //is sent out over Serial if(((result >> i) & 0x01) == 1){ Serial.write(event_strings[i],string_lengths[i]); } } } }