modify parallel epd run file
This commit is contained in:
		| @@ -0,0 +1,55 @@ | ||||
| // blink.c | ||||
| // | ||||
| // Example program for bcm2835 library | ||||
| // Blinks a pin on an off every 0.5 secs | ||||
| // | ||||
| // After installing bcm2835, you can build this  | ||||
| // with something like: | ||||
| // gcc -o blink blink.c -l bcm2835 | ||||
| // sudo ./blink | ||||
| // | ||||
| // Or you can test it before installing with: | ||||
| // gcc -o blink -I ../../src ../../src/bcm2835.c blink.c | ||||
| // sudo ./blink | ||||
| // | ||||
| // Author: Mike McCauley | ||||
| // Copyright (C) 2011 Mike McCauley | ||||
| // $Id: RF22.h,v 1.21 2012/05/30 01:51:25 mikem Exp $ | ||||
|  | ||||
| #include <bcm2835.h> | ||||
| #include <stdio.h> | ||||
|  | ||||
| // Blinks on RPi Plug P1 pin 11 (which is GPIO pin 17) | ||||
| #define PIN RPI_GPIO_P1_11 | ||||
|  | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
|     // If you call this, it will not actually access the GPIO | ||||
|     // Use for testing | ||||
| //    bcm2835_set_debug(1); | ||||
|  | ||||
|     if (!bcm2835_init()) | ||||
|       return 1; | ||||
|  | ||||
|     // Set the pin to be an output | ||||
|     bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_OUTP); | ||||
|  | ||||
|     // Blink | ||||
|     while (1) | ||||
|     { | ||||
| 	// Turn it on | ||||
| 	bcm2835_gpio_write(PIN, HIGH); | ||||
| 	 | ||||
| 	// wait a bit | ||||
| 	bcm2835_delay(500); | ||||
| 	 | ||||
| 	// turn it off | ||||
| 	bcm2835_gpio_write(PIN, LOW); | ||||
| 	 | ||||
| 	// wait a bit | ||||
| 	bcm2835_delay(500); | ||||
|     } | ||||
|     bcm2835_close(); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| @@ -0,0 +1,57 @@ | ||||
| // event.c | ||||
| // | ||||
| // Example program for bcm2835 library | ||||
| // Event detection of an input pin | ||||
| // | ||||
| // After installing bcm2835, you can build this  | ||||
| // with something like: | ||||
| // gcc -o event event.c -l bcm2835  | ||||
| // sudo ./event | ||||
| // | ||||
| // Or you can test it before installing with: | ||||
| // gcc -o event -I ../../src ../../src/bcm2835.c event.c | ||||
| // sudo ./event | ||||
| // | ||||
| // Author: Mike McCauley | ||||
| // Copyright (C) 2011 Mike McCauley | ||||
| // $Id: RF22.h,v 1.21 2012/05/30 01:51:25 mikem Exp $ | ||||
|  | ||||
| #include <bcm2835.h> | ||||
| #include <stdio.h> | ||||
|  | ||||
| // Input on RPi pin GPIO 15 | ||||
| #define PIN RPI_GPIO_P1_15 | ||||
|  | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
|     // If you call this, it will not actually access the GPIO | ||||
|     // Use for testing | ||||
| //    bcm2835_set_debug(1); | ||||
|  | ||||
|     if (!bcm2835_init()) | ||||
| 	return 1; | ||||
|  | ||||
|     // Set RPI pin P1-15 to be an input | ||||
|     bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_INPT); | ||||
|     //  with a pullup | ||||
|     bcm2835_gpio_set_pud(PIN, BCM2835_GPIO_PUD_UP); | ||||
|     // And a low detect enable | ||||
|     bcm2835_gpio_len(PIN); | ||||
|  | ||||
|     while (1) | ||||
|     { | ||||
| 	if (bcm2835_gpio_eds(PIN)) | ||||
| 	{ | ||||
| 	    // Now clear the eds flag by setting it to 1 | ||||
| 	    bcm2835_gpio_set_eds(PIN); | ||||
| 	    printf("low event detect for pin 15\n"); | ||||
| 	} | ||||
|  | ||||
| 	// wait a bit | ||||
| 	delay(500); | ||||
|     } | ||||
|  | ||||
|     bcm2835_close(); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| @@ -0,0 +1,346 @@ | ||||
| /******************************************************************************* | ||||
| * | ||||
| *   gpio.c | ||||
| * | ||||
| *   Copyright (c) 2013 Shahrooz Shahparnia | ||||
| * | ||||
| *   Description: | ||||
| *   gpio is a command-line utility for executing gpio commands with the  | ||||
| *   Broadcom bcm2835.  It was developed and tested on a Raspberry Pi single-board | ||||
| *   computer model B.  The utility is based on the bcm2835 C library developed | ||||
| *   by Mike McCauley of Open System Consultants, http://www.open.com.au/mikem/bcm2835/. | ||||
| * | ||||
| *   Invoking "gpio" results in a read, set of clear of a GPIO.   | ||||
| *   Options include GPIO read/set/clear  | ||||
| *   of a single GPIO pin, enabling or disabling pull up and pull downs as well as  | ||||
| *   resetting all GPIOs to a default input state.   | ||||
| *   The command usage and command-line parameters are described below | ||||
| *   in the showusage function, which prints the usage if no command-line parameters | ||||
| *   are included or if there are any command-line parameter errors.  Invoking gpio  | ||||
| *   requires root privilege. | ||||
| * | ||||
| *   This file contains the main function as well as functions for displaying | ||||
| *   usage and for parsing the command line. | ||||
| * | ||||
| *   Open Source Licensing GNU GPLv3 | ||||
| * | ||||
| *   Building: | ||||
| * After installing bcm2835, you can build this  | ||||
| * with something like: | ||||
| * gcc -o gpio gpio.c -l bcm2835 | ||||
| * sudo ./gpio | ||||
| * | ||||
| * Or you can test it before installing with: | ||||
| * gcc -o gpio -I ../../src ../../src/bcm2835.c gpio.c | ||||
| * sudo ./gpio | ||||
| * | ||||
| * | ||||
| *   History: | ||||
| *   11/10    VERSION 1.0.0: Original | ||||
| * | ||||
| *      User input parsing (comparse) and showusage\ | ||||
| *      have been adapted from: http://ipsolutionscorp.com/raspberry-pi-spi-utility/ | ||||
| *      mostly to keep consistence with the spincl tool usage. | ||||
| * | ||||
| *      Compile with: gcc -o gpio gpio.c bcm2835.c | ||||
| * | ||||
| *      Examples: | ||||
| *            Clear pin 5: sudo ./gpio -ib -dc -pn -n5   | ||||
| *            Reset all GPIOs to inputs and disable all pull up/downs: sudo ./gpio -ie | ||||
| *            Read pin 10: sudo ./gpio -ib -dr -pn -n10 | ||||
| *            Read pin 10 in debug mode with verbose output: sudo ./gpio -ib -dr -pn -n10 -b | ||||
| *            Read pin 10 and set pin as input with pull down: sudo ./gpio -ib -di -pd -n10 | ||||
| * | ||||
| *            Note: Pin numbers match the Raspberry Pie connector pin numbers | ||||
| ********************************************************************************/ | ||||
|  | ||||
| #include <bcm2835.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <stdint.h> | ||||
|  | ||||
| #define MODE_READ 0 | ||||
| #define MODE_SET 1 | ||||
| #define MODE_CLR 2 | ||||
| #define MODE_INPUT_READ 3 | ||||
|  | ||||
| #define PULL_UP 0 | ||||
| #define PULL_DOWN 1 | ||||
| #define NO_PULL 2 | ||||
|  | ||||
| #define GPIO_BEGIN 0 | ||||
| #define GPIO_END 1 | ||||
| #define NO_ACTION 2 | ||||
|  | ||||
| #define NO_PIN 40 // Some big number that's beyond the connector's pin count | ||||
| #define DEBUG_OFF 0 | ||||
| #define DEBUG_ON 1 | ||||
|  | ||||
| uint8_t  init = NO_ACTION; | ||||
| uint8_t  pull = NO_PULL; | ||||
| uint8_t  mode = MODE_READ; | ||||
| uint8_t  pin_number = NO_PIN; | ||||
|  | ||||
| uint8_t i, len; | ||||
| uint8_t data, pin, debug_mode = DEBUG_OFF; | ||||
|  | ||||
| //******************************************************************************* | ||||
| //  comparse: Parse the command line and return EXIT_SUCCESS or EXIT_FAILURE | ||||
| //    argc: number of command-line arguments | ||||
| //    argv: array of command-line argument strings | ||||
| //******************************************************************************* | ||||
|  | ||||
| void gpio_reset(void); | ||||
|  | ||||
| int comparse(int argc, char **argv) { | ||||
|     int argnum, i, xmitnum; | ||||
| 	 | ||||
|     if (argc < 2) {  // must have at least program name and len arguments | ||||
|                      // or -ie (GPIO_END) or -ib (GPIO_BEGIN) | ||||
|         fprintf(stderr, "Insufficient command line arguments\n"); | ||||
|         return EXIT_FAILURE; | ||||
|     } | ||||
|      | ||||
|     argnum = 1; | ||||
|     while (argnum < argc && argv[argnum][0] == '-') { | ||||
|  | ||||
|         switch (argv[argnum][1]) { | ||||
|  | ||||
|             case 'i':  // GPIO init | ||||
|                 switch (argv[argnum][2]) { | ||||
|                     case 'b': init = GPIO_BEGIN; break; | ||||
|                     case 'e': init = GPIO_END; break; | ||||
|                     default: | ||||
|                         fprintf(stderr, "%c is not a valid init option\n", argv[argnum][2]); | ||||
|                         return EXIT_FAILURE; | ||||
|                 } | ||||
|                 break; | ||||
|  | ||||
|             case 'd':  // Set/Clear/Read Mode | ||||
|                 switch (argv[argnum][2]) { | ||||
|                     case 'r': mode = MODE_READ; break; | ||||
|                     case 's': mode = MODE_SET; break; | ||||
|                     case 'c': mode = MODE_CLR; break; | ||||
| 		    case 'i': mode = MODE_INPUT_READ; break; | ||||
| 		    default: | ||||
|                         fprintf(stderr, "%c is not a valid init option\n", argv[argnum][2]); | ||||
|                         return EXIT_FAILURE; | ||||
|                 } | ||||
|                 break; | ||||
| 		 | ||||
|             case 'p':  // Pull up, down and no pull Mode | ||||
|                 switch (argv[argnum][2]) { | ||||
|                     case 'u': pull = PULL_UP; break; | ||||
|                     case 'd': pull = PULL_DOWN; break; | ||||
|                     case 'n': pull = NO_PULL; break; | ||||
| 		    default: | ||||
|                         fprintf(stderr, "%c is not a valid init option\n", argv[argnum][2]); | ||||
|                         return EXIT_FAILURE; | ||||
|                 } | ||||
|                 break;		 | ||||
|  | ||||
|             case 'n':  // pin number | ||||
| 	         pin_number = atoi(argv[argnum]+2); | ||||
|                  break; | ||||
|  | ||||
|             case 'b':  // debug mode | ||||
| 		 debug_mode = DEBUG_ON; | ||||
|                  break; | ||||
|  | ||||
|             default: | ||||
|                 fprintf(stderr, "%c is not a valid option\n", argv[argnum][1]); | ||||
|                 return EXIT_FAILURE; | ||||
|         } | ||||
|  | ||||
|         argnum++;   // advance the argument number | ||||
|  | ||||
|     } | ||||
|  | ||||
|     if (argnum == argc && init != NO_ACTION) // no further arguments are needed | ||||
|         return EXIT_SUCCESS; | ||||
|    | ||||
|     return EXIT_SUCCESS; | ||||
| } | ||||
|  | ||||
| //******************************************************************************* | ||||
| //  showusage: Print the usage statement and return errcode. | ||||
| //******************************************************************************* | ||||
|  | ||||
| int showusage(int errcode) { | ||||
|     printf("gpio \n"); | ||||
|     printf("Usage: \n"); | ||||
|     printf("  gpio [options]\n"); | ||||
|     printf("\n"); | ||||
|     printf("  Invoking gpio to set or reset a GPIO, enable disable pull up or pull down. Initialize or release a GPIO.\n"); | ||||
|     printf("\n"); | ||||
|     printf("  The following are the options, which must be a single letter\n"); | ||||
|     printf("    preceded by a '-' and followed by another character.\n"); | ||||
|     printf("    -ix where x is the GPIO init option, b[egin] or e[nd]\n"); | ||||
|     printf("      The begin option must be executed before any transfer can happen.\n"); | ||||
|     printf("      The end option will return the GPIO to inputs and turn off all pull up and pull downs.\n"); | ||||
|     printf("      It may be included with a transfer.\n"); | ||||
|     printf("    -dx where x is 'c' for clear, 's' is for set, 'r' for read and 'i' for read and set as input.\n"); | ||||
|     printf("    -px where x is the GPIO pull up or down option. 'u' for pull up, 'd' for pull down and 'n' for none.\n");   | ||||
|     printf("    -nx where x is the pin number.\n"); | ||||
|     printf("\n"); | ||||
|     return errcode; | ||||
| } | ||||
|  | ||||
| int main(int argc, char **argv) { | ||||
|  | ||||
|     printf("Running ... \n"); | ||||
|      | ||||
|     // parse the command line | ||||
|     if (comparse(argc, argv) == EXIT_FAILURE) return showusage (EXIT_FAILURE); | ||||
|  | ||||
|     if (!bcm2835_init()) return 1; | ||||
|        | ||||
|     // GPIO begin if specified     | ||||
|     if (init == GPIO_BEGIN) ; | ||||
|  | ||||
|  | ||||
|     // If len is 0, no need to continue, but do GPIO end if specified | ||||
|     // if (len == 0) { | ||||
|     //     if (init == GPIO_END) ; | ||||
|     //	 printf("Zero length ... error!\n"); | ||||
|     //     return EXIT_SUCCESS; | ||||
|     // } | ||||
|     switch (pin_number) { | ||||
|             case 3: | ||||
| 	       pin = RPI_V2_GPIO_P1_03; | ||||
| 	    break; | ||||
|             case 5: | ||||
| 	       pin = RPI_V2_GPIO_P1_05; | ||||
| 	    break;	     | ||||
|             case 7: | ||||
| 	       pin = RPI_V2_GPIO_P1_07; | ||||
| 	    break; | ||||
|             case 26: | ||||
| 	       pin = RPI_V2_GPIO_P1_26; | ||||
| 	    break; | ||||
|             case 24: | ||||
| 	       pin = RPI_V2_GPIO_P1_24; | ||||
| 	    break; | ||||
|             case 21: | ||||
| 	       pin = RPI_V2_GPIO_P1_21; | ||||
| 	    break; | ||||
|             case 19: | ||||
| 	       pin = RPI_V2_GPIO_P1_19; | ||||
| 	    break; | ||||
|             case 23: | ||||
| 	       pin = RPI_V2_GPIO_P1_23; | ||||
| 	    break; | ||||
|             case 10: | ||||
| 	       pin = RPI_V2_GPIO_P1_10; | ||||
| 	    break; | ||||
|             case 11: | ||||
| 	       pin = RPI_V2_GPIO_P1_11; | ||||
| 	    break; | ||||
|             case 12: | ||||
| 	       pin = RPI_V2_GPIO_P1_12; | ||||
| 	    break; | ||||
|             case 13: | ||||
| 	       pin = RPI_V2_GPIO_P1_13; | ||||
| 	    break; | ||||
|             case 15: | ||||
| 	       pin = RPI_V2_GPIO_P1_15; | ||||
| 	    break; | ||||
|             case 16: | ||||
| 	       pin = RPI_V2_GPIO_P1_16; | ||||
| 	    break; | ||||
|             case 18: | ||||
| 	       pin = RPI_V2_GPIO_P1_18; | ||||
| 	    break; | ||||
|             case 22: | ||||
| 	       pin = RPI_V2_GPIO_P1_22; | ||||
| 	    break; | ||||
| 	    default: | ||||
| 	      pin = NO_PIN; | ||||
|     } | ||||
|  | ||||
|     switch (pull) { | ||||
|     	    case PULL_UP: | ||||
| 		bcm2835_gpio_set_pud(pin, BCM2835_GPIO_PUD_UP); | ||||
| 	    break; | ||||
|     	    case PULL_DOWN: | ||||
| 		bcm2835_gpio_set_pud(pin, BCM2835_GPIO_PUD_DOWN); | ||||
| 	    break; | ||||
|     	    case NO_PULL: | ||||
| 		bcm2835_gpio_set_pud(pin, BCM2835_GPIO_PUD_OFF); | ||||
| 	    break; | ||||
|     	    default: | ||||
| 		bcm2835_gpio_set_pud(pin, BCM2835_GPIO_PUD_OFF);	     | ||||
|     } | ||||
|  | ||||
|     switch (mode) { | ||||
|     	    case MODE_READ: | ||||
| 	       data = bcm2835_gpio_lev(pin); | ||||
| 	       printf("Reading pin: %d\n", data); | ||||
| 	    break; | ||||
|     	    case MODE_INPUT_READ: | ||||
| 	       bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_INPT); | ||||
| 	       data = bcm2835_gpio_lev(pin); | ||||
| 	       printf("Reading pin: %d\n", data); | ||||
| 	    break;  | ||||
|     	    case MODE_SET: | ||||
| 	       bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_OUTP); | ||||
| 	       bcm2835_gpio_set(pin); | ||||
| 	    break; | ||||
|     	    case MODE_CLR: | ||||
| 	       bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_OUTP); | ||||
| 	       bcm2835_gpio_clr(pin); | ||||
| 	    break; | ||||
| 	    default: | ||||
| 	       printf("Wrong mode ...!\n"); | ||||
|     } | ||||
|  | ||||
|     if (debug_mode == DEBUG_ON) {     | ||||
|     	printf("Init %d\n", init);     | ||||
|     	printf("Mode %d\n", mode); | ||||
|     	printf("Pull %d\n", pull); | ||||
|     	printf("Pin Number %d\n", pin_number); | ||||
|     	printf("Pin %d\n", pin); | ||||
|     }    | ||||
|         | ||||
|     if (init == GPIO_END) gpio_reset();        | ||||
|     bcm2835_close(); | ||||
|     printf("... done!\n"); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| void gpio_reset(void) { | ||||
| 	bcm2835_gpio_set_pud(RPI_V2_GPIO_P1_03, BCM2835_GPIO_PUD_OFF); | ||||
| 	bcm2835_gpio_set_pud(RPI_V2_GPIO_P1_05, BCM2835_GPIO_PUD_OFF); | ||||
| 	bcm2835_gpio_set_pud(RPI_V2_GPIO_P1_07, BCM2835_GPIO_PUD_OFF); | ||||
| 	bcm2835_gpio_set_pud(RPI_V2_GPIO_P1_26, BCM2835_GPIO_PUD_OFF); | ||||
| 	bcm2835_gpio_set_pud(RPI_V2_GPIO_P1_24, BCM2835_GPIO_PUD_OFF); | ||||
| 	bcm2835_gpio_set_pud(RPI_V2_GPIO_P1_21, BCM2835_GPIO_PUD_OFF); | ||||
| 	bcm2835_gpio_set_pud(RPI_V2_GPIO_P1_19, BCM2835_GPIO_PUD_OFF); | ||||
| 	bcm2835_gpio_set_pud(RPI_V2_GPIO_P1_23, BCM2835_GPIO_PUD_OFF); | ||||
| 	bcm2835_gpio_set_pud(RPI_V2_GPIO_P1_10, BCM2835_GPIO_PUD_OFF); | ||||
| 	bcm2835_gpio_set_pud(RPI_V2_GPIO_P1_11, BCM2835_GPIO_PUD_OFF); | ||||
| 	bcm2835_gpio_set_pud(RPI_V2_GPIO_P1_12, BCM2835_GPIO_PUD_OFF); | ||||
| 	bcm2835_gpio_set_pud(RPI_V2_GPIO_P1_13, BCM2835_GPIO_PUD_OFF); | ||||
| 	bcm2835_gpio_set_pud(RPI_V2_GPIO_P1_15, BCM2835_GPIO_PUD_OFF); | ||||
| 	bcm2835_gpio_set_pud(RPI_V2_GPIO_P1_16, BCM2835_GPIO_PUD_OFF); | ||||
| 	bcm2835_gpio_set_pud(RPI_V2_GPIO_P1_18, BCM2835_GPIO_PUD_OFF); | ||||
| 	bcm2835_gpio_set_pud(RPI_V2_GPIO_P1_22, BCM2835_GPIO_PUD_OFF); | ||||
|  | ||||
| 	bcm2835_gpio_fsel(RPI_V2_GPIO_P1_03, BCM2835_GPIO_FSEL_INPT); | ||||
| 	bcm2835_gpio_fsel(RPI_V2_GPIO_P1_05, BCM2835_GPIO_FSEL_INPT); | ||||
| 	bcm2835_gpio_fsel(RPI_V2_GPIO_P1_07, BCM2835_GPIO_FSEL_INPT); | ||||
| 	bcm2835_gpio_fsel(RPI_V2_GPIO_P1_26, BCM2835_GPIO_FSEL_INPT); | ||||
| 	bcm2835_gpio_fsel(RPI_V2_GPIO_P1_24, BCM2835_GPIO_FSEL_INPT); | ||||
| 	bcm2835_gpio_fsel(RPI_V2_GPIO_P1_21, BCM2835_GPIO_FSEL_INPT); | ||||
| 	bcm2835_gpio_fsel(RPI_V2_GPIO_P1_19, BCM2835_GPIO_FSEL_INPT); | ||||
| 	bcm2835_gpio_fsel(RPI_V2_GPIO_P1_23, BCM2835_GPIO_FSEL_INPT); | ||||
| 	bcm2835_gpio_fsel(RPI_V2_GPIO_P1_10, BCM2835_GPIO_FSEL_INPT); | ||||
| 	bcm2835_gpio_fsel(RPI_V2_GPIO_P1_11, BCM2835_GPIO_FSEL_INPT); | ||||
| 	bcm2835_gpio_fsel(RPI_V2_GPIO_P1_12, BCM2835_GPIO_FSEL_INPT); | ||||
| 	bcm2835_gpio_fsel(RPI_V2_GPIO_P1_13, BCM2835_GPIO_FSEL_INPT); | ||||
| 	bcm2835_gpio_fsel(RPI_V2_GPIO_P1_15, BCM2835_GPIO_FSEL_INPT); | ||||
| 	bcm2835_gpio_fsel(RPI_V2_GPIO_P1_16, BCM2835_GPIO_FSEL_INPT); | ||||
| 	bcm2835_gpio_fsel(RPI_V2_GPIO_P1_18, BCM2835_GPIO_FSEL_INPT); | ||||
| 	bcm2835_gpio_fsel(RPI_V2_GPIO_P1_22, BCM2835_GPIO_FSEL_INPT); | ||||
| } | ||||
| @@ -0,0 +1,278 @@ | ||||
| /******************************************************************************* | ||||
| * | ||||
| *   i2c.c | ||||
| * | ||||
| *   Copyright (c) 2013 Shahrooz Shahparnia (sshahrooz@gmail.com) | ||||
| * | ||||
| *   Description: | ||||
| *   i2c is a command-line utility for executing i2c commands with the  | ||||
| *   Broadcom bcm2835.  It was developed and tested on a Raspberry Pi single-board | ||||
| *   computer model B.  The utility is based on the bcm2835 C library developed | ||||
| *   by Mike McCauley of Open System Consultants, http://www.open.com.au/mikem/bcm2835/. | ||||
| * | ||||
| *   Invoking spincl results in a read or write I2C transfer.  Options include the | ||||
| *   the I2C clock frequency, read/write, address, and port initialization/closing | ||||
| *   procedures.  The command usage and command-line parameters are described below | ||||
| *   in the showusage function, which prints the usage if no command-line parameters | ||||
| *   are included or if there are any command-line parameter errors.  Invoking i2c  | ||||
| *   requires root privilege. | ||||
| * | ||||
| *   This file contains the main function as well as functions for displaying | ||||
| *   usage and for parsing the command line. | ||||
| * | ||||
| *   Open Source Licensing GNU GPLv3 | ||||
| * | ||||
| *   Building: | ||||
| * After installing bcm2835, you can build this  | ||||
| * with something like: | ||||
| * gcc -o i2c i2c.c -l bcm2835 | ||||
| * sudo ./i2c | ||||
| * | ||||
| * Or you can test it before installing with: | ||||
| * gcc -o i2c -I ../../src ../../src/bcm2835.c i2c.c | ||||
| * sudo ./i2c | ||||
| * | ||||
| *   History: | ||||
| *   11/05    VERSION 1.0.0: Original | ||||
| * | ||||
| *      User input parsing (comparse) and showusage\ | ||||
| *      have been adapted from: http://ipsolutionscorp.com/raspberry-pi-spi-utility/ | ||||
| *      mostly to keep consistence with the spincl tool usage. | ||||
| * | ||||
| *      Compile with: gcc -o i2c i2c.c bcm2835.c | ||||
| * | ||||
| *      Examples: | ||||
| * | ||||
| *           Set up ADC (Arduino: ADC1015) | ||||
| *           sudo ./i2c -s72 -dw -ib 3 0x01 0x44 0x00 (select config register, setup mux, etc.) | ||||
| *           sudo ./i2c -s72 -dw -ib 1 0x00 (select ADC data register) | ||||
| * | ||||
| *           Bias DAC (Arduino: MCP4725) at some voltage | ||||
| *           sudo ./i2c -s99 -dw -ib 3 0x60 0x7F 0xF0 (FS output is with 0xFF 0xF0) | ||||
| *           Read ADC convergence result | ||||
| *           sudo ./i2c -s72 -dr -ib 2 (FS output is 0x7FF0 with PGA1 = 1) | ||||
| *   | ||||
| *      In a DAC to ADC loop back typical results are: | ||||
| * | ||||
| *      DAC    VOUT   ADC | ||||
| *      7FFh   1.6V   677h                    Note ratio is FS_ADC*PGA_GAIN/FS_DAC = 4.096/3.3 = 1.23 | ||||
| *      5FFh   1.2V   4DCh | ||||
| *      8F0h   1.8V   745h | ||||
| *      9D0h   2V     7EAh | ||||
| *      000h   10mV   004h | ||||
| * | ||||
| ********************************************************************************/ | ||||
|  | ||||
| #include <bcm2835.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <stdint.h> | ||||
|  | ||||
| #define MODE_READ 0 | ||||
| #define MODE_WRITE 1 | ||||
|  | ||||
| #define MAX_LEN 32 | ||||
|  | ||||
| char wbuf[MAX_LEN]; | ||||
|  | ||||
| typedef enum { | ||||
|     NO_ACTION, | ||||
|     I2C_BEGIN, | ||||
|     I2C_END | ||||
| } i2c_init; | ||||
|  | ||||
| uint8_t  init = NO_ACTION; | ||||
| uint16_t clk_div = BCM2835_I2C_CLOCK_DIVIDER_148; | ||||
| uint8_t slave_address = 0x00; | ||||
| uint32_t len = 0; | ||||
| uint8_t  mode = MODE_READ; | ||||
|  | ||||
| //******************************************************************************* | ||||
| //  comparse: Parse the command line and return EXIT_SUCCESS or EXIT_FAILURE | ||||
| //    argc: number of command-line arguments | ||||
| //    argv: array of command-line argument strings | ||||
| //******************************************************************************* | ||||
|  | ||||
| int comparse(int argc, char **argv) { | ||||
|     int argnum, i, xmitnum; | ||||
| 	 | ||||
|     if (argc < 2) {  // must have at least program name and len arguments | ||||
|                      // or -ie (I2C_END) or -ib (I2C_BEGIN) | ||||
|         fprintf(stderr, "Insufficient command line arguments\n"); | ||||
|         return EXIT_FAILURE; | ||||
|     } | ||||
|      | ||||
|     argnum = 1; | ||||
|     while (argnum < argc && argv[argnum][0] == '-') { | ||||
|  | ||||
|         switch (argv[argnum][1]) { | ||||
|  | ||||
|             case 'i':  // I2C init | ||||
|                 switch (argv[argnum][2]) { | ||||
|                     case 'b': init = I2C_BEGIN; break; | ||||
|                     case 'e': init = I2C_END; break; | ||||
|                     default: | ||||
|                         fprintf(stderr, "%c is not a valid init option\n", argv[argnum][2]); | ||||
|                         return EXIT_FAILURE; | ||||
|                 } | ||||
|                 break; | ||||
|  | ||||
|             case 'd':  // Read/Write Mode | ||||
|                 switch (argv[argnum][2]) { | ||||
|                     case 'r': mode = MODE_READ; break; | ||||
|                     case 'w': mode = MODE_WRITE; break; | ||||
|                     default: | ||||
|                         fprintf(stderr, "%c is not a valid init option\n", argv[argnum][2]); | ||||
|                         return EXIT_FAILURE; | ||||
|                 } | ||||
|                 break; | ||||
|  | ||||
|             case 'c':  // Clock divider | ||||
|                 clk_div = atoi(argv[argnum]+2); | ||||
|                 break; | ||||
|  | ||||
|             case 's':  // Slave address | ||||
|                 slave_address = atoi(argv[argnum]+2); | ||||
|                 break; | ||||
|  | ||||
|             default: | ||||
|                 fprintf(stderr, "%c is not a valid option\n", argv[argnum][1]); | ||||
|                 return EXIT_FAILURE; | ||||
|         } | ||||
|  | ||||
|         argnum++;   // advance the argument number | ||||
|  | ||||
|     } | ||||
|  | ||||
|     // If command is used for I2C_END or I2C_BEGIN only | ||||
|     if (argnum == argc && init != NO_ACTION) // no further arguments are needed | ||||
|         return EXIT_SUCCESS; | ||||
| 	 | ||||
|     // Get len | ||||
|     if (strspn(argv[argnum], "0123456789") != strlen(argv[argnum])) { | ||||
|         fprintf(stderr, "Invalid number of bytes specified\n"); | ||||
|         return EXIT_FAILURE; | ||||
|     } | ||||
|      | ||||
|     len = atoi(argv[argnum]); | ||||
|  | ||||
|     if (len > MAX_LEN) { | ||||
|     	fprintf(stderr, "Invalid number of bytes specified\n"); | ||||
|         return EXIT_FAILURE; | ||||
|     } | ||||
|      | ||||
|     argnum++;   // advance the argument number | ||||
|  | ||||
|     xmitnum = argc - argnum;    // number of xmit bytes | ||||
|  | ||||
|     memset(wbuf, 0, sizeof(wbuf)); | ||||
|  | ||||
|     for (i = 0; i < xmitnum; i++) { | ||||
|         if (strspn(argv[argnum + i], "0123456789abcdefABCDEFxX") != strlen(argv[argnum + i])) { | ||||
|             fprintf(stderr, "Invalid data: "); | ||||
| 	    fprintf(stderr, "%d \n", xmitnum); | ||||
|             return EXIT_FAILURE; | ||||
|         } | ||||
|         wbuf[i] = (char)strtoul(argv[argnum + i], NULL, 0); | ||||
|     } | ||||
|  | ||||
|     return EXIT_SUCCESS; | ||||
| } | ||||
|  | ||||
| //******************************************************************************* | ||||
| //  showusage: Print the usage statement and return errcode. | ||||
| //******************************************************************************* | ||||
| int showusage(int errcode) { | ||||
|     printf("i2c \n"); | ||||
|     printf("Usage: \n"); | ||||
|     printf("  i2c [options] len [rcv/xmit bytes]\n"); | ||||
|     printf("\n"); | ||||
|     printf("  Invoking i2c results in an I2C transfer of a specified\n"); | ||||
|     printf("    number of bytes.  Additionally, it can be used to set the appropriate\n"); | ||||
|     printf("    GPIO pins to their respective I2C configurations or return them\n"); | ||||
|     printf("    to GPIO input configuration.  Options include the I2C clock frequency,\n"); | ||||
|     printf("    initialization option (i2c_begin and i2c_end).  i2c must be invoked\n"); | ||||
|     printf("    with root privileges.\n"); | ||||
|     printf("\n"); | ||||
|     printf("  The following are the options, which must be a single letter\n"); | ||||
|     printf("    preceded by a '-' and followed by another character.\n"); | ||||
|     printf("    -dx where x is 'w' for write and 'r' is for read.\n"); | ||||
|     printf("    -ix where x is the I2C init option, b[egin] or e[nd]\n"); | ||||
|     printf("      The begin option must be executed before any transfer can happen.\n"); | ||||
|     printf("        It may be included with a transfer.\n"); | ||||
|     printf("      The end option will return the I2C pins to GPIO inputs.\n"); | ||||
|     printf("        It may be included with a transfer.\n"); | ||||
|     printf("    -cx where x is the clock divider from 250MHz. Allowed values\n"); | ||||
|     printf("      are 150 through 2500.\n"); | ||||
|     printf("      Corresponding frequencies are specified in bcm2835.h.\n"); | ||||
|     printf("\n"); | ||||
|     printf("    len: The number of bytes to be transmitted or received.\n"); | ||||
|     printf("    The maximum number of bytes allowed is %d\n", MAX_LEN); | ||||
|     printf("\n"); | ||||
|     printf("\n"); | ||||
|     printf("\n"); | ||||
|     return errcode; | ||||
| } | ||||
|  | ||||
| char buf[MAX_LEN]; | ||||
| int i; | ||||
| uint8_t data; | ||||
|  | ||||
| int main(int argc, char **argv) { | ||||
|  | ||||
|     printf("Running ... \n"); | ||||
|      | ||||
|     // parse the command line | ||||
|     if (comparse(argc, argv) == EXIT_FAILURE) return showusage (EXIT_FAILURE); | ||||
|  | ||||
|     if (!bcm2835_init()) | ||||
|     { | ||||
|       printf("bcm2835_init failed. Are you running as root??\n"); | ||||
|       return 1; | ||||
|     } | ||||
|        | ||||
|     // I2C begin if specified     | ||||
|     if (init == I2C_BEGIN) | ||||
|     { | ||||
|       if (!bcm2835_i2c_begin()) | ||||
|       { | ||||
|         printf("bcm2835_i2c_begin failed. Are you running as root??\n"); | ||||
| 	return 1; | ||||
|       } | ||||
|     } | ||||
| 	   | ||||
|  | ||||
|     // If len is 0, no need to continue, but do I2C end if specified | ||||
|     if (len == 0) { | ||||
|          if (init == I2C_END) bcm2835_i2c_end(); | ||||
| 	 printf("... done!\n"); | ||||
|          return EXIT_SUCCESS; | ||||
|     } | ||||
|  | ||||
|     bcm2835_i2c_setSlaveAddress(slave_address); | ||||
|     bcm2835_i2c_setClockDivider(clk_div); | ||||
|     fprintf(stderr, "Clock divider set to: %d\n", clk_div); | ||||
|     fprintf(stderr, "len set to: %d\n", len); | ||||
|     fprintf(stderr, "Slave address set to: %d\n", slave_address);    | ||||
|      | ||||
|     if (mode == MODE_READ) { | ||||
|     	for (i=0; i<MAX_LEN; i++) buf[i] = 'n'; | ||||
|     	data = bcm2835_i2c_read(buf, len); | ||||
|     	printf("Read Result = %d\n", data);    | ||||
|     	for (i=0; i<MAX_LEN; i++) { | ||||
|     		if(buf[i] != 'n') printf("Read Buf[%d] = %x\n", i, buf[i]); | ||||
| 	}     | ||||
|     } | ||||
|     if (mode == MODE_WRITE) { | ||||
|     	data = bcm2835_i2c_write(wbuf, len); | ||||
|     	printf("Write Result = %d\n", data); | ||||
|     }    | ||||
|  | ||||
|     // This I2C end is done after a transfer if specified | ||||
|     if (init == I2C_END) bcm2835_i2c_end();    | ||||
|     bcm2835_close(); | ||||
|     printf("... done!\n"); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| @@ -0,0 +1,53 @@ | ||||
| // input.c | ||||
| // | ||||
| // Example program for bcm2835 library | ||||
| // Reads and prints the state of an input pin | ||||
| // | ||||
| // After installing bcm2835, you can build this  | ||||
| // with something like: | ||||
| // gcc -o input input.c -l bcm2835 | ||||
| // sudo ./input | ||||
| // | ||||
| // Or you can test it before installing with: | ||||
| // gcc -o input -I ../../src ../../src/bcm2835.c input.c | ||||
| // sudo ./input | ||||
| // | ||||
| // Author: Mike McCauley | ||||
| // Copyright (C) 2011 Mike McCauley | ||||
| // $Id: RF22.h,v 1.21 2012/05/30 01:51:25 mikem Exp $ | ||||
|  | ||||
| #include <bcm2835.h> | ||||
| #include <stdio.h> | ||||
|  | ||||
| // Input on RPi pin GPIO 15 | ||||
| #define PIN RPI_GPIO_P1_15 | ||||
|  | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
|     // If you call this, it will not actually access the GPIO | ||||
|     // Use for testing | ||||
| //    bcm2835_set_debug(1); | ||||
|  | ||||
|     if (!bcm2835_init()) | ||||
| 	return 1; | ||||
|  | ||||
|     // Set RPI pin P1-15 to be an input | ||||
|     bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_INPT); | ||||
|     //  with a pullup | ||||
|     bcm2835_gpio_set_pud(PIN, BCM2835_GPIO_PUD_UP); | ||||
|  | ||||
|     // Blink | ||||
|     while (1) | ||||
|     { | ||||
| 	// Read some data | ||||
| 	uint8_t value = bcm2835_gpio_lev(PIN); | ||||
| 	printf("read from pin 15: %d\n", value); | ||||
| 	 | ||||
| 	// wait a bit | ||||
| 	delay(500); | ||||
|     } | ||||
|  | ||||
|     bcm2835_close(); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| @@ -0,0 +1,66 @@ | ||||
| // pwm.c | ||||
| // | ||||
| // Example program for bcm2835 library | ||||
| // Shows how to use PWM to control GPIO pins | ||||
| // | ||||
| // After installing bcm2835, you can build this  | ||||
| // with something like: | ||||
| // gcc -o pwm pwm.c -l bcm2835  | ||||
| // sudo ./pwm | ||||
| // | ||||
| // Or you can test it before installing with: | ||||
| // gcc -o pwm -I ../../src ../../src/bcm2835.c pwm.c | ||||
| // sudo ./pwm | ||||
| // | ||||
| // Connect an LED between GPIO18 (pin 12) and GND to observe the LED changing in brightness | ||||
| // | ||||
| // Author: Mike McCauley | ||||
| // Copyright (C) 2013 Mike McCauley | ||||
| // $Id: RF22.h,v 1.21 2012/05/30 01:51:25 mikem Exp $ | ||||
|  | ||||
| #include <bcm2835.h> | ||||
| #include <stdio.h> | ||||
|  | ||||
| // PWM output on RPi Plug P1 pin 12 (which is GPIO pin 18) | ||||
| // in alt fun 5. | ||||
| // Note that this is the _only_ PWM pin available on the RPi IO headers | ||||
| #define PIN RPI_GPIO_P1_12 | ||||
| // and it is controlled by PWM channel 0 | ||||
| #define PWM_CHANNEL 0 | ||||
| // This controls the max range of the PWM signal | ||||
| #define RANGE 1024 | ||||
|  | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
|     if (!bcm2835_init()) | ||||
| 	return 1; | ||||
|  | ||||
|     // Set the output pin to Alt Fun 5, to allow PWM channel 0 to be output there | ||||
|     bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_ALT5); | ||||
|  | ||||
|     // Clock divider is set to 16. | ||||
|     // With a divider of 16 and a RANGE of 1024, in MARKSPACE mode, | ||||
|     // the pulse repetition frequency will be | ||||
|     // 1.2MHz/1024 = 1171.875Hz, suitable for driving a DC motor with PWM | ||||
|     bcm2835_pwm_set_clock(BCM2835_PWM_CLOCK_DIVIDER_16); | ||||
|     bcm2835_pwm_set_mode(PWM_CHANNEL, 1, 1); | ||||
|     bcm2835_pwm_set_range(PWM_CHANNEL, RANGE); | ||||
|  | ||||
|     // Vary the PWM m/s ratio between 1/RANGE and (RANGE-1)/RANGE | ||||
|     // over the course of a a few seconds | ||||
|     int direction = 1; // 1 is increase, -1 is decrease | ||||
|     int data = 1; | ||||
|     while (1) | ||||
|     { | ||||
| 	if (data == 1) | ||||
| 	    direction = 1;   // Switch to increasing | ||||
| 	else if (data == RANGE-1) | ||||
| 	    direction = -1;  // Switch to decreasing | ||||
| 	data += direction; | ||||
| 	bcm2835_pwm_set_data(PWM_CHANNEL, data); | ||||
| 	bcm2835_delay(1); | ||||
|     } | ||||
|  | ||||
|     bcm2835_close(); | ||||
|     return 0; | ||||
| } | ||||
| @@ -0,0 +1,56 @@ | ||||
| // spi.c | ||||
| // | ||||
| // Example program for bcm2835 library | ||||
| // Shows how to interface with SPI to transfer a byte to and from an SPI device | ||||
| // | ||||
| // After installing bcm2835, you can build this  | ||||
| // with something like: | ||||
| // gcc -o spi spi.c -l bcm2835 | ||||
| // sudo ./spi | ||||
| // | ||||
| // Or you can test it before installing with: | ||||
| // gcc -o spi -I ../../src ../../src/bcm2835.c spi.c | ||||
| // sudo ./spi | ||||
| // | ||||
| // Author: Mike McCauley | ||||
| // Copyright (C) 2012 Mike McCauley | ||||
| // $Id: RF22.h,v 1.21 2012/05/30 01:51:25 mikem Exp $ | ||||
|  | ||||
| #include <bcm2835.h> | ||||
| #include <stdio.h> | ||||
|  | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
|     // If you call this, it will not actually access the GPIO | ||||
| // Use for testing | ||||
| //        bcm2835_set_debug(1); | ||||
|  | ||||
|     if (!bcm2835_init()) | ||||
|     { | ||||
|       printf("bcm2835_init failed. Are you running as root??\n"); | ||||
|       return 1; | ||||
|     } | ||||
|  | ||||
|     if (!bcm2835_spi_begin()) | ||||
|     { | ||||
|       printf("bcm2835_spi_begin failed. Are you running as root??\n"); | ||||
|       return 1; | ||||
|     } | ||||
|     bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST);      // The default | ||||
|     bcm2835_spi_setDataMode(BCM2835_SPI_MODE0);                   // The default | ||||
|     bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_65536); // The default | ||||
|     bcm2835_spi_chipSelect(BCM2835_SPI_CS0);                      // The default | ||||
|     bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, LOW);      // the default | ||||
|      | ||||
|     // Send a byte to the slave and simultaneously read a byte back from the slave | ||||
|     // If you tie MISO to MOSI, you should read back what was sent | ||||
|     uint8_t send_data = 0x23; | ||||
|     uint8_t read_data = bcm2835_spi_transfer(send_data); | ||||
|     printf("Sent to SPI: 0x%02X. Read back from SPI: 0x%02X.\n", send_data, read_data); | ||||
|     if (send_data != read_data) | ||||
|       printf("Do you have the loopback from MOSI to MISO connected?\n"); | ||||
|     bcm2835_spi_end(); | ||||
|     bcm2835_close(); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| @@ -0,0 +1,63 @@ | ||||
| // spin.c | ||||
| // | ||||
| // Example program for bcm2835 library | ||||
| // Shows how to interface with SPI to transfer a number of bytes to and from an SPI device | ||||
| // | ||||
| // After installing bcm2835, you can build this  | ||||
| // with something like: | ||||
| // gcc -o spin spin.c -l bcm2835 | ||||
| // sudo ./spin | ||||
| // | ||||
| // Or you can test it before installing with: | ||||
| // gcc -o spin -I ../../src ../../src/bcm2835.c spin.c | ||||
| // sudo ./spin | ||||
| // | ||||
| // Author: Mike McCauley | ||||
| // Copyright (C) 2012 Mike McCauley | ||||
| // $Id: RF22.h,v 1.21 2012/05/30 01:51:25 mikem Exp $ | ||||
|  | ||||
| #include <bcm2835.h> | ||||
| #include <stdio.h> | ||||
|  | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
|     // If you call this, it will not actually access the GPIO | ||||
| // Use for testing | ||||
| //        bcm2835_set_debug(1); | ||||
|      | ||||
|     if (!bcm2835_init()) | ||||
|     { | ||||
|       printf("bcm2835_init failed. Are you running as root??\n"); | ||||
|       return 1; | ||||
|     } | ||||
|  | ||||
|     if (!bcm2835_spi_begin()) | ||||
|     { | ||||
|       printf("bcm2835_spi_begin failed. Are you running as root??\n"); | ||||
|       return 1; | ||||
|     } | ||||
|     bcm2835_spi_begin(); | ||||
|     bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST);      // The default | ||||
|     bcm2835_spi_setDataMode(BCM2835_SPI_MODE0);                   // The default | ||||
|     bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_65536); // The default | ||||
|     bcm2835_spi_chipSelect(BCM2835_SPI_CS0);                      // The default | ||||
|     bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, LOW);      // the default | ||||
|      | ||||
|     // Send a some bytes to the slave and simultaneously read  | ||||
|     // some bytes back from the slave | ||||
|     // Most SPI devices expect one or 2 bytes of command, after which they will send back | ||||
|     // some data. In such a case you will have the command bytes first in the buffer, | ||||
|     // followed by as many 0 bytes as you expect returned data bytes. After the transfer, you  | ||||
|     // Can the read the reply bytes from the buffer. | ||||
|     // If you tie MISO to MOSI, you should read back what was sent. | ||||
|      | ||||
|     char buf[] = { 0x01, 0x02, 0x11, 0x33 }; // Data to send | ||||
|     bcm2835_spi_transfern(buf, sizeof(buf)); | ||||
|     // buf will now be filled with the data that was read from the slave | ||||
|     printf("Read from SPI: %02X  %02X  %02X  %02X \n", buf[0], buf[1], buf[2], buf[3]); | ||||
|      | ||||
|     bcm2835_spi_end(); | ||||
|     bcm2835_close(); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| @@ -0,0 +1,92 @@ | ||||
| // spiram.c | ||||
| // | ||||
| // Little library for accessing  SPI RAM such as 23K256-I/P | ||||
| // using bcm2835 library on Raspberry Pi | ||||
| // | ||||
| // Author: Mike McCauley | ||||
| // Copyright (C) 2018 Mike McCauley | ||||
| // This software is part of the bcm2835 library and is licensed under the same conditions | ||||
| // $Id:  $ | ||||
|  | ||||
| #include <bcm2835.h> | ||||
| #include <string.h> // memcpy | ||||
| #include "spiram.h" | ||||
|  | ||||
| static uint8_t _mode = SPIRAM_MODE_INVALID; | ||||
|  | ||||
| uint8_t spiram_read_sr() | ||||
| { | ||||
|   uint8_t command[] = { SPIRAM_OPCODE_READ_SR, 0}; | ||||
|   bcm2835_spi_transfern(command, sizeof(command)); | ||||
|   return command[1]; | ||||
| } | ||||
|  | ||||
| bool spiram_write_sr(uint8_t value) | ||||
| { | ||||
|   uint8_t command[] = { SPIRAM_OPCODE_WRITE_SR, value}; | ||||
|   bcm2835_spi_transfern(command, sizeof(command)); | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| bool spiram_set_mode(uint8_t mode) | ||||
| { | ||||
|   if (mode != _mode) | ||||
|     { | ||||
|       spiram_write_sr(mode); | ||||
|       _mode = mode; | ||||
|     } | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| bool spiram_begin() | ||||
| { | ||||
|   _mode = SPIRAM_MODE_BYTE; | ||||
|    | ||||
|   bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST);      // The default | ||||
|   bcm2835_spi_setDataMode(BCM2835_SPI_MODE0);                   // The default | ||||
|   bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_65536); // The default | ||||
|   bcm2835_spi_chipSelect(BCM2835_SPI_CS0);                      // The default | ||||
|   bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, LOW);      // the default | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| bool spiram_end() | ||||
| { | ||||
|   bcm2835_spi_end(); | ||||
|   return true; | ||||
| } | ||||
|  | ||||
|  | ||||
| uint8_t spiram_read_byte(uint16_t address) | ||||
| { | ||||
|   spiram_set_mode(SPIRAM_MODE_BYTE); | ||||
|   uint8_t command[] = { SPIRAM_OPCODE_READ, (address >> 8) & 0xff, address & 0xff, 0xff }; | ||||
|   bcm2835_spi_transfern(command, sizeof(command)); | ||||
|   uint8_t ret = command[3]; | ||||
| } | ||||
|  | ||||
| bool spiram_write_byte(uint16_t address, uint8_t value) | ||||
| { | ||||
|   spiram_set_mode(SPIRAM_MODE_BYTE); | ||||
|   uint8_t command[] = { SPIRAM_OPCODE_WRITE, (address >> 8) & 0xff, address & 0xff, value }; | ||||
|   bcm2835_spi_writenb(command, sizeof(command)); | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| bool spiram_read_page(uint16_t address, uint8_t *buf) | ||||
| { | ||||
|   spiram_set_mode(SPIRAM_MODE_PAGE); | ||||
|   uint8_t command[3 + SPIRAM_PAGE_SIZE] = { SPIRAM_OPCODE_READ, (address >> 8) & 0xff, address & 0xff }; | ||||
|   bcm2835_spi_transfern(command, sizeof(command)); | ||||
|   memcpy(buf, command + 3, SPIRAM_PAGE_SIZE); | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| bool spiram_write_page(uint16_t address, uint8_t *buf) | ||||
| { | ||||
|   spiram_set_mode(SPIRAM_MODE_PAGE); | ||||
|   uint8_t command[3 + SPIRAM_PAGE_SIZE] = { SPIRAM_OPCODE_WRITE, (address >> 8) & 0xff, address & 0xff }; | ||||
|   memcpy(command + 3, buf, SPIRAM_PAGE_SIZE);; | ||||
|   bcm2835_spi_writenb(command, sizeof(command)); | ||||
|   return true; | ||||
| } | ||||
| @@ -0,0 +1,102 @@ | ||||
| // spiram.h | ||||
| // | ||||
| // Header for a Little Library for accessing SPI RAM chips such as 23K256-I/P | ||||
| // using bcm2835 library on Raspberry Pi | ||||
| // | ||||
| // Author: Mike McCauley | ||||
| // Copyright (C) 2018 Mike McCauley | ||||
| // This software is part of the bcm2835 library and is licensed under the same conditions | ||||
| // $Id:  $ | ||||
|  | ||||
| #include <stdbool.h> // bool, true, false | ||||
|  | ||||
| #ifndef SPIRAM_h | ||||
| #define SPIRAM_h | ||||
|  | ||||
| #define SPIRAM_HOLD_DISABLE     0x1 | ||||
| #define SPIRAM_MODE_BYTE       (0x00 | SPIRAM_HOLD_DISABLE) | ||||
| #define SPIRAM_MODE_PAGE       (0x80 | SPIRAM_HOLD_DISABLE) | ||||
| #define SPIRAM_MODE_STREAM     (0x40 | SPIRAM_HOLD_DISABLE) | ||||
| #define SPIRAM_MODE_INVALID    0xff | ||||
| #define SPIRAM_OPCODE_READ_SR  0x05 | ||||
| #define SPIRAM_OPCODE_WRITE_SR 0x01 | ||||
| #define SPIRAM_OPCODE_READ     0x03 | ||||
| #define SPIRAM_OPCODE_WRITE    0x02 | ||||
|  | ||||
| /* Size of a page in 23K256 */ | ||||
| #define SPIRAM_PAGE_SIZE       32 | ||||
|  | ||||
| /* | ||||
|  * This library allows you to read and write data from an external SPI interfaced static ram (SRAM) | ||||
|  * such as 23K256 (256kbit = 32kByte) | ||||
|  * Byte and POage modes are supported. | ||||
|  * Valid addresses are from 0x0000 to 0x7fff | ||||
|  * Tested on RPI 3 Model B, Raspbian Jessie | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * Initialise the spiram library, enables SPI with default divider of  | ||||
|  * BCM2835_SPI_CLOCK_DIVIDER_65536 = 6.1035156kHz on RPI3. | ||||
|  * You can change the SPI speed after calling this by calling bcm2835_spi_setClockDivider() | ||||
|  * Returns true on success, false otherwise | ||||
|  */ | ||||
| bool spiram_begin(); | ||||
|  | ||||
| /* | ||||
|  * Stops using the RPI SPI functions and returns the GPIO pins to their default behaviour. | ||||
|  * Call this when you have finished using SPI forever, or at the end of your program | ||||
|  * Returns true on success, false otherwise | ||||
|  */ | ||||
| bool spiram_end(); | ||||
|  | ||||
| /* | ||||
|  * Read and returns the current value of the SRAM status register | ||||
|  */ | ||||
| uint8_t spiram_read_sr(); | ||||
|  | ||||
| /* | ||||
|  * Write a new value to the SRAM status register,  | ||||
|  * usually one of SPIRAM_MODE_* | ||||
|  * You should never need to call this directly. Used internally. | ||||
|  * Returns true on success, false otherwise | ||||
|  */ | ||||
| bool spiram_write_sr(uint8_t value); | ||||
|  | ||||
| /* | ||||
|  * Set the operating mode of the SRAM. | ||||
|  * Mode is one of  SPIRAM_MODE_*. THis is done automatically  | ||||
|  * by the spiram_write_* and spiram_read_* functions, so you would not normally | ||||
|  * need to call this directly. | ||||
|  * Returns true on success, false otherwise | ||||
|  */ | ||||
| bool spiram_set_mode(uint8_t mode); | ||||
|  | ||||
| /* | ||||
|  * Reads a single byte from the given address and returns it. | ||||
|  */ | ||||
| uint8_t spiram_read_byte(uint16_t address); | ||||
|  | ||||
| /* | ||||
|  * Writes a single byte to the given address. | ||||
|  * Returns true on success, false otherwise | ||||
|  */ | ||||
| bool spiram_write_byte(uint16_t address, uint8_t value); | ||||
|  | ||||
| /* | ||||
|  * Reads a whole page of data (32 bytes) from the page starting at the given address. | ||||
|  * The read data is placed in buf. Be sure that there is enough rom there for it. | ||||
|  * Caution: if the starting address is not on a page boundary,  | ||||
|  * it will wrap back to the beginning of the page. | ||||
|  * Returns true on success, false otherwise | ||||
|  */ | ||||
| bool spiram_read_page(uint16_t address, uint8_t *buf); | ||||
|  | ||||
| /* | ||||
|  * Writes a whole page of data (32 bytes) to the page starting at the given address. | ||||
|  * Caution: if the starting address is not on a page boundary,  | ||||
|  * it will wrap back to the beginning of the page. | ||||
|  * Returns true on success, false otherwise | ||||
|  */ | ||||
| bool spiram_write_page(uint16_t address, uint8_t *buf); | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,99 @@ | ||||
| // spiram_test.c | ||||
| // | ||||
| // Example program for bcm2835  | ||||
| // Shows how to interface with SPI RAM such as 23K256-I/P | ||||
| // using the spiram little library | ||||
| // | ||||
| // Tested on RPI 3 Model B, Raspbian Jessie | ||||
| // Tested at full speed over many hours with no errors. | ||||
| // | ||||
| // Connect RPi 3 B to 23K256-I/P like this: | ||||
| // RPi pin    Function     23K256-I/P pin (name) | ||||
| // J1-6       GND          4 (VSS) | ||||
| // J1-1       3.3V         8 (VCC) | ||||
| //                    and  7 (/HOLD) | ||||
| // J1-19      SPI0_MOSI    5 (SI) | ||||
| // J1-21      SPI0_MISO    2 (SO) | ||||
| // J1-23      SPI0_SCLK    6 (SCK) | ||||
| // J1-24      SPI0_CE0_N   1 (/CS) | ||||
| // | ||||
| // After installing bcm2835, you can build this | ||||
| // with something like: | ||||
| // gcc -o spiram_test spiram.c spiram_test.c -l bcm2835 | ||||
| // sudo ./spiram_test | ||||
| // | ||||
| // Or you can test it before installing with: | ||||
| // gcc -o spiram_test -I ../../src ../../src/bcm2835.c spiram.c spiram_test.c | ||||
| // sudo ./spiram_test | ||||
| // | ||||
| // Author: Mike McCauley | ||||
| // Copyright (C) 2018 Mike McCauley | ||||
| // $Id:  $ | ||||
|  | ||||
| #include <bcm2835.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> // memcmp | ||||
| #include "spiram.h" | ||||
|  | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
|   if (!bcm2835_init()) | ||||
|     { | ||||
|       printf("bcm2835_init failed. Are you running as root??\n"); | ||||
|       return 1; | ||||
|     } | ||||
|  | ||||
|   if (!bcm2835_spi_begin()) | ||||
|     { | ||||
|       printf("bcm2835_spi_begin failed. Are you running as root??\n"); | ||||
|       return 1; | ||||
|     } | ||||
|   if (!spiram_begin()) | ||||
|     { | ||||
|       printf("spiram_begin failed.\n"); | ||||
|       return 1; | ||||
|     } | ||||
|   /* You can speed things up by selecting a faster SPI speed | ||||
|   // after spiram_begin, which defaults to BCM2835_SPI_CLOCK_DIVIDER_65536 = 6.1035156kHz on RPI3 | ||||
|   */ | ||||
|   bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_64); // 6.25MHz on RPI3 | ||||
|  | ||||
|   uint8_t value = 0; | ||||
|   uint16_t address = 0x0000; | ||||
|   while (1) | ||||
|     { | ||||
|       uint8_t ret; | ||||
|  | ||||
|       /*      ret = spiram_read_sr();*/ | ||||
|       spiram_write_byte(address, value); | ||||
|       ret = spiram_read_byte(address); | ||||
|       if (ret != value) | ||||
| 	printf("ERROR: spiram_read_byte address %04x got %02x, expected %02x\n", address, ret, value); | ||||
| #if 0 | ||||
|       printf("spiram_read_byte at address %04x got %02x\n", address, ret); | ||||
| #endif | ||||
|        | ||||
|       uint8_t write_page_buf[SPIRAM_PAGE_SIZE] = { 0, value, value, value }; | ||||
|       uint8_t read_page_buf[SPIRAM_PAGE_SIZE]; | ||||
|       spiram_write_page(address, write_page_buf); | ||||
|      | ||||
|       spiram_read_page(address, read_page_buf); | ||||
|       if (memcmp(write_page_buf, read_page_buf, SPIRAM_PAGE_SIZE) != 0) | ||||
| 	printf("ERROR: spiram_read_page at address %04x\n", address); | ||||
| #if 0 | ||||
|       printf("spiram_read_page address %04x got ", address); | ||||
|       int i; | ||||
|       for (i = 0; i < SPIRAM_PAGE_SIZE; i++) | ||||
| 	printf("%02x ", read_page_buf[i]); | ||||
|       printf("\n"); | ||||
| #endif | ||||
|       /* sleep(1); */ | ||||
|       value++; | ||||
|       address++; | ||||
|     } | ||||
|    | ||||
|   spiram_end(); | ||||
|   bcm2835_close(); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user