Created
July 2, 2025 20:39
-
-
Save sjgallagher2/fe348e618f56724255fd37d31e45542b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Printing and file handling | |
| #include <stdio.h> | |
| #include <string.h> | |
| // Function doc template: | |
| /** | |
| * @brief Summary. | |
| * | |
| * Long description. | |
| * | |
| * @param name Description. | |
| * @return Return description. | |
| */ | |
| typedef enum{ | |
| GPIO_DIR_INPUT=0, | |
| GPIO_DIR_OUTPUT | |
| } GPIO_DIRECTION; | |
| typedef enum{ | |
| GPIO_LOW=0, | |
| GPIO_HIGH | |
| } GPIO_VALUE; | |
| typedef enum{ | |
| GPIO_EDGE_NONE,GPIO_EDGE_RISING,GPIO_EDGE_FALLING,GPIO_EDGE_BOTH | |
| } GPIO_EDGE; | |
| typedef enum{ | |
| GPIO_PROP_DIRECTION,GPIO_PROP_EDGE,GPIO_PROP_LABEL,GPIO_PROP_VALUE,GPIO_PROP_ACTIVE_LOW | |
| } GPIO_PROPERTIES; | |
| typedef struct{ | |
| int number; | |
| GPIO_DIRECTION dir; | |
| int debounce_time; | |
| } gpio_pin; | |
| // Private functions | |
| int _gpio_get_filename(gpio_pin* gpio,char* fname,GPIO_PROPERTIES prop); | |
| int _gpio_write(gpio_pin* gpio,GPIO_PROPERTIES prop,char* value); | |
| int _gpio_read(gpio_pin* gpio,GPIO_PROPERTIES prop,char* value); | |
| // Public functions | |
| int gpio_set_direction(gpio_pin* gpio,GPIO_DIRECTION dir); | |
| GPIO_DIRECTION gpio_get_direction(gpio_pin* gpio); | |
| int gpio_set_value(gpio_pin* gpio,GPIO_VALUE val); | |
| int gpio_toggle_output(gpio_pin* gpio); | |
| GPIO_VALUE gpio_get_value(gpio_pin* gpio); | |
| int gpio_set_active_low(gpio_pin* gpio); | |
| int gpio_set_active_high(gpio_pin* gpio); | |
| // Software debounce only | |
| void gpio_set_debounce_time(gpio_pin* gpio,int time){gpio->debounce_time = time;} | |
| int _gpio_get_filename(gpio_pin* gpio,char* fname,GPIO_PROPERTIES prop) | |
| { | |
| /** | |
| * @brief Generates a filename based on gpio number and property. | |
| * | |
| * This helper function does not check if the file actually exists. | |
| * | |
| * @param gpio gpio_pin struct pointer. | |
| * @param fname filename buffer to be written to. | |
| * @param prop GPIO property enum. | |
| * @return 1 on success, -1 if property is not recognized. | |
| */ | |
| if(prop == GPIO_PROP_DIRECTION) | |
| sprintf(fname, "/sys/class/gpio/gpio%d/%s",gpio->number,"direction"); | |
| else if(prop == GPIO_PROP_EDGE) | |
| sprintf(fname, "/sys/class/gpio/gpio%d/%s",gpio->number,"edge"); | |
| else if(prop == GPIO_PROP_LABEL) | |
| sprintf(fname, "/sys/class/gpio/gpio%d/%s",gpio->number,"label"); | |
| else if(prop == GPIO_PROP_VALUE) | |
| sprintf(fname, "/sys/class/gpio/gpio%d/%s",gpio->number,"value"); | |
| else if(prop == GPIO_PROP_ACTIVE_LOW) | |
| sprintf(fname, "/sys/class/gpio/gpio%d/%s",gpio->number,"active_low"); | |
| else | |
| return -1; | |
| return 1; | |
| } | |
| int _gpio_write(gpio_pin* gpio,GPIO_PROPERTIES prop,char* value) | |
| { | |
| /** | |
| * @brief Writes a value to a GPIO pin property file. | |
| * | |
| * Uses the given gpio data and the desired property `prop`, builds the | |
| * filename, and attempts to write `value` to that file. | |
| * | |
| * @param gpio gpio_pin struct pointer. | |
| * @param prop GPIO property enum. | |
| * @param value C string with value to be written to file | |
| * @return 1 on success, -1 on failure. | |
| */ | |
| // Generate filename. | |
| char filename[FILENAME_MAX]; | |
| int stat = _gpio_get_filename(gpio,filename,prop); | |
| if(stat != 1) | |
| { | |
| printf("Unrecognized GPIO_PROPERTIES value %d\n",prop); | |
| return -1; | |
| } | |
| // Open file. | |
| FILE* fp = fopen(filename,"w"); | |
| if(!fp){ | |
| perror("File opening failed."); | |
| printf("Check that the path is correct and that you have privileges for writing to it. The GPIO pin might not exist.\n"); | |
| return -1; | |
| } | |
| // Write to file. | |
| int write_status = fputs(value,fp); | |
| if(write_status == EOF) | |
| { | |
| printf("File writing failed with fputs(%s,%s)\n",value,filename); | |
| printf("Check that you have privileges for writing.\n"); | |
| return -1; | |
| } | |
| // Close file. | |
| fclose(fp); | |
| // Return success. | |
| return 1; | |
| } | |
| int _gpio_read(gpio_pin* gpio,GPIO_PROPERTIES prop,char* value) | |
| { | |
| /** | |
| * @brief Reads the GPIO property into a buffer. | |
| * | |
| * Uses the given gpio data and the desired property `prop`, builds the | |
| * filename, and attempts to read the contents into `value`. | |
| * | |
| * @param gpio gpio_pin struct pointer. | |
| * @param prop GPIO property enum. | |
| * @return Return 1 on success, -1 on failure. | |
| */ | |
| char filename[FILENAME_MAX]; | |
| int stat = _gpio_get_filename(gpio,filename,prop); | |
| if(stat != 1) | |
| { | |
| printf("Unrecognized GPIO_PROPERTIES value %d\n",prop); | |
| return -1; | |
| } | |
| // Open file. | |
| FILE* fp = fopen(filename,"r"); | |
| if(!fp){ | |
| perror("File opening failed, check that the path is correct and that you have privileges for reading it. The GPIO pin might not exist. Error"); | |
| return -1; | |
| } | |
| // Read from file. | |
| fgets(value,100,fp); | |
| value[strcspn(value, "\n") ] = '\0'; // Remove line ending | |
| // Close file. | |
| fclose(fp); | |
| // Return success. | |
| return 1; | |
| } | |
| int gpio_set_direction(gpio_pin* gpio,GPIO_DIRECTION dir) | |
| { | |
| /** | |
| * @brief Summary. | |
| * | |
| * Long description. | |
| * | |
| * @param gpio gpio_pin struct pointer. | |
| * @return Return description. | |
| */ | |
| int write_status = -1; | |
| if(dir == GPIO_DIR_INPUT) | |
| { | |
| write_status = _gpio_write(gpio,GPIO_PROP_DIRECTION,"in"); | |
| } | |
| else if(dir == GPIO_DIR_OUTPUT) | |
| { | |
| write_status = _gpio_write(gpio,GPIO_PROP_DIRECTION,"out"); | |
| } | |
| else write_status = -1; | |
| return write_status; | |
| } | |
| GPIO_DIRECTION gpio_get_direction(gpio_pin* gpio) | |
| { | |
| /** | |
| * @brief Summary. | |
| * | |
| * Long description. | |
| * | |
| * @param gpio gpio_pin struct pointer. | |
| * @return Return description. | |
| */ | |
| char dir[10]; | |
| _gpio_read(gpio,GPIO_PROP_DIRECTION,dir); | |
| if(strcmp(dir,"in") == 0) | |
| { | |
| return GPIO_DIR_INPUT; | |
| } | |
| else if(strcmp(dir,"out")==0) | |
| { | |
| return GPIO_DIR_OUTPUT; | |
| } | |
| return -1; | |
| } | |
| int gpio_set_value(gpio_pin* gpio,GPIO_VALUE val) | |
| { | |
| /** | |
| * @brief Summary. | |
| * | |
| * Long description. | |
| * | |
| * @param gpio gpio_pin struct pointer. | |
| * @return Return description. | |
| */ | |
| return 0; | |
| } | |
| int gpio_toggle_output(gpio_pin* gpio) | |
| { | |
| /** | |
| * @brief Summary. | |
| * | |
| * Long description. | |
| * | |
| * @param gpio gpio_pin struct pointer. | |
| * @return Return description. | |
| */ | |
| return 0; | |
| } | |
| GPIO_VALUE gpio_get_value(gpio_pin* gpio) | |
| { | |
| /** | |
| * @brief Summary. | |
| * | |
| * Long description. | |
| * | |
| * @param gpio gpio_pin struct pointer. | |
| * @return Return description. | |
| */ | |
| return GPIO_LOW; | |
| } | |
| int gpio_set_active_low(gpio_pin* gpio) | |
| { | |
| /** | |
| * @brief Summary. | |
| * | |
| * Long description. | |
| * | |
| * @param gpio gpio_pin struct pointer. | |
| * @return Return description. | |
| */ | |
| return 0; | |
| } | |
| int gpio_set_active_high(gpio_pin* gpio) | |
| { | |
| /** | |
| * @brief Summary. | |
| * | |
| * Long description. | |
| * | |
| * @param gpio gpio_pin struct pointer. | |
| * @return Return description. | |
| */ | |
| return 0; | |
| } | |
| int main() | |
| { | |
| // TESTS | |
| // For these tests, use GPIO67 (PIN37). Here is its info: | |
| // GPIO67 (unallocated) | |
| // pin 37 (PIN37): ocp:P8_08_pinmux (GPIO UNCLAIMED) function pinmux_P8_08_default_pin group pinmux_P8_08_default_pin | |
| // pin 37 (PIN37) 3:gpio-64-95 44e10894 00000037 pinctrl-single | |
| // Pad config: 0x37 = 0 1 1 0 111 = fast, input/output, pullup, pull enable, mode 7 | |
| // GPIO settings: | |
| // direction = in | |
| // active_low = 0 | |
| // edge = none | |
| // label = P8_08 | |
| // value = 1 | |
| gpio_pin gpio67; | |
| gpio67.number = 67; | |
| gpio67.dir = GPIO_DIR_INPUT; | |
| // int _gpio_get_filename(gpio_pin* gpio,char* fname,GPIO_PROPERTIES prop); | |
| /** | |
| * @brief Generates a filename based on gpio number and property. | |
| * | |
| * This helper function does not check if the file actually exists. | |
| * | |
| * @param gpio gpio_pin struct pointer. | |
| * @param fname filename buffer to be written to. | |
| * @param prop GPIO property enum. | |
| * @return 1 on success, -1 if property is not recognized. | |
| */ | |
| // Common test parameters // | |
| char fname[FILENAME_MAX]; | |
| int stat = -999; | |
| printf("1. Existing GPIO pin and property\n"); | |
| stat = _gpio_get_filename(&gpio67,fname,GPIO_PROP_DIRECTION); | |
| printf("Filename for gpio67 direction: %s\n",fname); | |
| printf("Status out: %d\n",stat); | |
| printf("2. Existing GPIO pin but non-existent property\n"); | |
| stat = _gpio_get_filename(&gpio67,fname,999); | |
| printf("Filename for gpio67 non-existent property: %s\n",fname); | |
| printf("Status out: %d\n",stat); | |
| printf("3. Non-existent GPIO pin and existing property\n"); | |
| gpio67.number = 999; | |
| stat = _gpio_get_filename(&gpio67,fname,GPIO_PROP_DIRECTION); | |
| printf("Filename for gpio67 (999) direction: %s\n",fname); | |
| printf("Status out: %d\n",stat); | |
| gpio67.number = 67; | |
| printf("4. Non-existent GPIO pin and property\n"); | |
| gpio67.number = 999; | |
| stat = _gpio_get_filename(&gpio67,fname,GPIO_PROP_DIRECTION); | |
| printf("Filename for gpio67 (999) non-existent property: %s\n",fname); | |
| printf("Status out: %d\n",stat); | |
| gpio67.number = 67; | |
| printf("\n"); | |
| // int _gpio_read(gpio_pin* gpio,GPIO_PROPERTIES prop,char* value) | |
| /** | |
| * @brief Reads the GPIO property into a buffer. | |
| * | |
| * Uses the given gpio data and the desired property `prop`, builds the | |
| * filename, and attempts to read the contents into `value`. | |
| * | |
| * @param gpio gpio_pin struct pointer. | |
| * @param prop GPIO property enum. | |
| * @return Return 1 on success, -1 on failure. | |
| */ | |
| // Common test parameters // | |
| char pindir[10]; | |
| stat = -999; | |
| printf("1. Existing pin and property\n"); | |
| stat = _gpio_read(&gpio67,GPIO_PROP_DIRECTION,pindir); | |
| printf("gpio67 direction: %s\n",pindir); | |
| printf("Status out: %d\n",stat); | |
| printf("2. Existing pin and non-existent property\n"); | |
| stat = _gpio_read(&gpio67,99,pindir); | |
| printf("gpio67 bad property: %s\n",pindir); | |
| printf("Status out: %d\n",stat); | |
| printf("3. Non-existent pin and existing property\n"); | |
| gpio67.number = 999; | |
| stat = _gpio_read(&gpio67,GPIO_PROP_DIRECTION,pindir); | |
| printf("gpio67 (999) direction: %s\n",pindir); | |
| printf("Status out: %d\n",stat); | |
| gpio67.number = 67; | |
| printf("4. Non-existent pin and property\n"); | |
| gpio67.number = 999; | |
| stat = _gpio_read(&gpio67,999,pindir); | |
| printf("gpio67 (999) bad property: %s\n",pindir); | |
| printf("Status out: %d\n",stat); | |
| gpio67.number = 67; | |
| // int _gpio_write(gpio_pin* gpio,GPIO_PROPERTIES prop,char* value) | |
| /** | |
| * @brief Writes a value to a GPIO pin property file. | |
| * | |
| * Uses the given gpio data and the desired property `prop`, builds the | |
| * filename, and attempts to write `value` to that file. | |
| * | |
| * @param gpio gpio_pin struct pointer. | |
| * @param prop GPIO property enum. | |
| * @param value C string with value to be written to file | |
| * @return 1 on success, -1 on failure. | |
| */ | |
| // Common test parameters // | |
| char pindir_set[] = "in"; | |
| stat = -999; | |
| printf("1. Existing pin and property, attempting to write \"%s\"\n",pindir_set); | |
| stat = _gpio_write(&gpio67,GPIO_PROP_DIRECTION,pindir_set); | |
| printf("Attempting to read pin direction...\n"); | |
| _gpio_read(&gpio67,GPIO_PROP_DIRECTION,pindir); | |
| printf("Read: %s\n",pindir); | |
| printf("String comparison: %d\n",strcmp(pindir_set,pindir)); | |
| if(strcmp(pindir_set,pindir)==0) | |
| { | |
| printf("Success.\n"); | |
| } | |
| else printf("Failure.\n"); | |
| printf("\n"); | |
| printf("2. Non-existent pin and existing property, attempting to write \"%s\"\n",pindir_set); | |
| gpio67.number = 999; | |
| stat = _gpio_write(&gpio67,GPIO_PROP_DIRECTION,pindir_set); | |
| printf("Attempting to read pin direction...\n"); | |
| _gpio_read(&gpio67,GPIO_PROP_DIRECTION,pindir); | |
| printf("Read: %s\n",pindir); | |
| if(strcmp(pindir_set,pindir)==0) | |
| { | |
| printf("Success.\n"); | |
| } | |
| else printf("Failure.\n"); | |
| gpio67.number = 67; | |
| return 0; | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment