diff --git a/Android.bp b/Android.bp index 098a4ed..28fec7f 100644 --- a/Android.bp +++ b/Android.bp @@ -24,6 +24,7 @@ cc_library_shared { "wiringPi/wiringPi.c", "wiringPi/mcp23017.c", "wiringPi/odroidc2.c", + "wiringPi/odroidc4.c", "wiringPi/drcSerial.c", "wiringPi/mcp23s08.c", "wiringPi/odroidn1.c", diff --git a/build b/build index bfe05dc..37978ab 100755 --- a/build +++ b/build @@ -64,7 +64,7 @@ configure_gpiomem() { *c|*c1|*c2) $sudo cp -f udev/rules.d/99-odroid-wiringpi-meson.rules /etc/udev/rules.d/ ;; - *n2) + *n2|*c4) $sudo cp -f udev/rules.d/99-odroid-wiringpi-aml.rules /etc/udev/rules.d/ ;; *) diff --git a/debian/odroid-wiringpi.postinst b/debian/odroid-wiringpi.postinst index 83c66ec..c02cfba 100644 --- a/debian/odroid-wiringpi.postinst +++ b/debian/odroid-wiringpi.postinst @@ -20,7 +20,7 @@ case "$1" in *c|*c1|*c2) cp -f /tmp/odroid-wiringpi/rules.d/99-odroid-wiringpi-meson.rules /etc/udev/rules.d/ ;; - *n2) + *n2|*c4) cp -f /tmp/odroid-wiringpi/rules.d/99-odroid-wiringpi-aml.rules /etc/udev/rules.d/ ;; *) diff --git a/gpio/readall.c b/gpio/readall.c index be2619c..83ad11c 100755 --- a/gpio/readall.c +++ b/gpio/readall.c @@ -481,6 +481,68 @@ static const char *physNamesOdroidN2 [64] = NULL,NULL,NULL, }; +/*----------------------------------------------------------------------------*/ +static const char *physNamesOdroidC4All [64] = +{ + NULL, + + " 3.3V", "5V ", + " SDA.2", "5V ", + " SCL.2", "GND(0V) ", + "GPIO.481", "TxD1 ", + " GND(0V)", "RxD1 ", + "GPIO.479", "GPIO.492", + "GPIO.480", "GND(0V) ", + "GPIO.483", "GPIO.476", + " 3.3V", "GPIO.477", + " MOSI", "GND(0V) ", + " MISO", "GPIO.478", + " SLCK", "SS ", + " GND(0V)", "GPIO. 23", + " SDA.3", "SCL.3 ", + "GPIO.490", "GND(0V) ", + "GPIO.491", "GPIO. 24", + "GPIO.482", "GND(0V) ", + "GPIO.495", "GPIO. 22", + " AIN.2", "1V8 ", + " GND(0V)", "AIN.0 ", + + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL, +}; + +/*----------------------------------------------------------------------------*/ +static const char *physNamesOdroidC4 [64] = +{ + NULL, + + " 3.3V", "5V ", + " SDA.2", "5V ", + " SCL.2", "0V ", + " IO.481", "TxD1 ", + " 0V", "RxD1 ", + " IO.479", "IO.492 ", + " IO.480", "0V ", + " IO.483", "IO.476 ", + " 3.3V", "IO.477 ", + " MOSI", "0V ", + " MISO", "IO.478 ", + " SLCK", "SS ", + " 0V", "IO. 23 ", + " SDA.3", "SCL.3 ", + " IO.490", "0V ", + " IO.491", "IO. 24 ", + " IO.482", "0V ", + " IO.495", "IO. 22 ", + " AIN.2", "1V8 ", + " 0V", "AIN.0 ", + + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL, +}; + /*----------------------------------------------------------------------------*/ static void readallPhys(int model, int UNU rev, int physPin, const char *physNames[], int isAll) { int pin ; @@ -533,6 +595,7 @@ static void readallPhys(int model, int UNU rev, int physPin, const char *physNam break; case MODEL_ODROID_XU3: case MODEL_ODROID_N2: + case MODEL_ODROID_C4: printf (" | %2d | %5s", getPadDrive(pin), pupd[getPUPD(pin)]); break; default: @@ -573,6 +636,7 @@ static void readallPhys(int model, int UNU rev, int physPin, const char *physNam break; case MODEL_ODROID_XU3: case MODEL_ODROID_N2: + case MODEL_ODROID_C4: printf (" | %-5s | %-2d", pupd[getPUPD(pin)], getPadDrive(pin)); break; default: @@ -696,6 +760,10 @@ void doReadall(int argc, char *argv[]) { headerName = (isAll == FALSE) ? "--- N2 ---" : "---- Model ODROID-N2 ----"; physNames = (char *) ((isAll == FALSE) ? physNamesOdroidN2 : physNamesOdroidN2All); break; + case MODEL_ODROID_C4: + headerName = (isAll == FALSE) ? "--- C4 ---" : "---- Model ODROID-C4 ----"; + physNames = (char *) ((isAll == FALSE) ? physNamesOdroidC4 : physNamesOdroidC4All); + break; default: printf("Oops - unknown model: %d\n", model); return; diff --git a/pins/Makefile b/pins/Makefile index 0426542..665f769 100755 --- a/pins/Makefile +++ b/pins/Makefile @@ -8,7 +8,8 @@ SRC = pins.tex \ odroid_c1.tex \ odroid_c2.tex \ odroid_n1.tex \ - odroid_n2.tex + odroid_n2.tex \ + odroid_c4.tex DVI = $(SRC:.tex=.dvi) diff --git a/pins/odroid_c4.pdf b/pins/odroid_c4.pdf new file mode 100644 index 0000000..d5d4760 Binary files /dev/null and b/pins/odroid_c4.pdf differ diff --git a/pins/odroid_c4.tex b/pins/odroid_c4.tex new file mode 100644 index 0000000..62eb42a --- /dev/null +++ b/pins/odroid_c4.tex @@ -0,0 +1,99 @@ +\documentclass[11pt,a4paper]{article} +\parskip 1ex +\parindent 0em +\thispagestyle{empty} +\pagestyle{plain} +\pagenumbering{arabic} +\setlength{\topmargin}{0pt} +\setlength{\headheight}{0pt} +\setlength{\headsep}{0pt} +\setlength{\topskip}{0pt} +\setlength{\textheight}{240mm} +\setlength{\footskip}{5ex} +\setlength{\oddsidemargin}{0pt} +\setlength{\evensidemargin}{0pt} +\setlength{\textwidth}{160mm} +\usepackage[dvips]{graphics,color} +\usepackage{helvet} +\renewcommand{\familydefault}{\sfdefault} +\begin{document} +\begin{sffamily} +\definecolor{rtb-black}{rgb} {0.0, 0.0, 0.0} +\definecolor{rtb-navy}{rgb} {0.0, 0.0, 0.5} +\definecolor{rtb-green}{rgb} {0.0, 0.5, 0.0} +\definecolor{rtb-teal}{rgb} {0.0, 0.5, 0.5} +\definecolor{rtb-maroon}{rgb} {0.5, 0.0, 0.0} +\definecolor{rtb-purple}{rgb} {0.5, 0.0, 0.5} +\definecolor{rtb-olive}{rgb} {0.5, 0.5, 0.0} +\definecolor{rtb-silver}{rgb} {0.7, 0.7, 0.7} +\definecolor{rtb-grey}{rgb} {0.5, 0.5, 0.5} +\definecolor{rtb-blue}{rgb} {0.0, 0.0, 1.0} +\definecolor{rtb-lime}{rgb} {0.0, 1.0, 0.0} +\definecolor{rtb-aqua}{rgb} {0.0, 1.0, 1.0} +\definecolor{rtb-red}{rgb} {1.0, 0.0, 0.0} +\definecolor{rtb-fuchsia}{rgb}{1.0, 0.0, 1.0} +\definecolor{rtb-yellow}{rgb} {1.0, 1.0, 0.0} +\definecolor{rtb-white}{rgb} {1.0, 1.0, 1.0} + +\begin{center} +\bfseries{WiringPi: GPIO Pin Numbering Tables}\\ +\tt{https://wiki.odroid.com/odroid-c4/hardware/} +\end{center} + +\begin{center} +\begin{tabular}{|c|c|c||p{8mm}|p{8mm}||c|c|c|c|} +\hline +\multicolumn{8}{|c|}{\bfseries{ODROID-C4: 40 Pin GPIO connector(J2)}}\\ +\hline +\hline +WiringPi Pin & Native GPIO & Name & \multicolumn{2}{|c||}{Header} & Name & Native GPIO & WiringPi Pin\\ +\hline +\hline + & & \textcolor{rtb-red}{3.3v} & \raggedleft{1} & 2 & \textcolor{rtb-maroon}{5v} & & \\ +\hline +8 & 493 (GPIOX.17) & \textcolor{rtb-aqua}{SDA1} & \raggedleft{3} & 4 & \textcolor{rtb-maroon}{5v} & & \\ +\hline +9 & 494 (GPIOX.18) & \textcolor{rtb-aqua}{SCL1} & \raggedleft{5} & 6 & \textcolor{rtb-black}{0v} & & \\ +\hline +7 & 481 (GPIOX.5) & \textcolor{rtb-green}{GPIO7} & \raggedleft{7} & 8 & \textcolor{rtb-yellow}{TxD} & 488 (GPIOX.12) & 15\\ +\hline + & & \textcolor{rtb-black}{0v} & \raggedleft{9} & 10 & \textcolor{rtb-yellow}{RxD} & 489 (GPIOX.13) & 16\\ +\hline +0 & 479 (GPIOX.3) & \textcolor{rtb-green}{GPIO0} & \raggedleft{11} & 12 & \textcolor{rtb-green}{GPIO1} & 492 (GPIOX.16) & 1\\ +\hline +2 & 480 (GPIOX.4) & \textcolor{rtb-green}{GPIO2} & \raggedleft{13} & 14 & \textcolor{rtb-black}{0v} & & \\ +\hline +3 & 483 (GPIOX.7) & \textcolor{rtb-green}{GPIO3} & \raggedleft{15} & 16 & \textcolor{rtb-green}{GPIO4} & 476 (GPIOX.0) & 4\\ +\hline + & & \textcolor{rtb-red}{3.3v} & \raggedleft{17} & 18 & \textcolor{rtb-green}{GPIO5} & 477 (GPIOX.1) & 5\\ +\hline +12 & 484 (GPIOX.8) & \textcolor{rtb-green}{GPIO12} & \raggedleft{19} & 20 & \textcolor{rtb-black}{0v} & & \\ +\hline +13 & 485 (GPIOX.9) & \textcolor{rtb-green}{GPIO13} & \raggedleft{21} & 22 & \textcolor{rtb-green}{GPIO6} & 478 (GPIOX.2) & 6\\ +\hline +14 & 487 (GPIOX.11) & \textcolor{rtb-green}{GPIO14} & \raggedleft{23} & 24 & \textcolor{rtb-green}{GPIO10} & 486 (GPIOX.10) & 10\\ +\hline + & & \textcolor{rtb-black}{0v} & \raggedleft{25} & 26 & \textcolor{rtb-green}{GPIO11} & 23 (GPIOH.6) & 11\\ +\hline +30 & 474 (GPIOA.14) & \textcolor{rtb-aqua}{SDA2} & \raggedleft{27} & 28 & \textcolor{rtb-aqua}{SCL2} & 475 (GPIOA.15) & 31\\ +\hline +21 & 490 (GPIOX.14) & \textcolor{rtb-green}{GPIO21} & \raggedleft{29} & 30 & \textcolor{rtb-black}{0v} & & \\ +\hline +22 & 491 (GPIOX.15) & \textcolor{rtb-green}{GPIO22} & \raggedleft{31} & 32 & \textcolor{rtb-green}{GPIO26} & 24 (GPIOH.7) & 26\\ +\hline +23 & 482 (GPIOX.6) & \textcolor{rtb-green}{GPIO23} & \raggedleft{33} & 34 & \textcolor{rtb-black}{0v} & & \\ +\hline +24 & 495 (GPIOX.19) & \textcolor{rtb-green}{GPIO24} & \raggedleft{35} & 36 & \textcolor{rtb-green}{GPIO27} & 22 (GPIOH.5) & 27\\ +\hline +25 & ADC.AIN1 & \textcolor{rtb-green}{GPIO25} & \raggedleft{37} & 38 & \textcolor{rtb-green}{GPIO28} & 1.8V Ref Out & 28\\ +\hline + & & \textcolor{rtb-black}{0v} & \raggedleft{39} & 40 & \textcolor{rtb-green}{GPIO29} & ADC.AIN0 & 29\\ +\hline +\hline +WiringPi Pin & Native GPIO & Name & \multicolumn{2}{|c||}{Header} & Name & Native GPIO & WiringPi Pin\\ +\hline +\end{tabular} +\end{center} + +\end{sffamily} +\end{document} diff --git a/wiringPi/Makefile b/wiringPi/Makefile index 702ef31..47ddf3a 100755 --- a/wiringPi/Makefile +++ b/wiringPi/Makefile @@ -68,7 +68,8 @@ SRC = wiringPi.c \ odroidc2.c \ odroidxu3.c \ odroidn1.c \ - odroidn2.c + odroidn2.c \ + odroidc4.c HEADERS = $(shell ls *.h) @@ -155,6 +156,7 @@ odroidc2.o : wiringPi.h odroidc2.h odroidxu3.o : wiringPi.h odroidxu3.h odroidn1.o : wiringPi.h odroidn1.h odroidn2.o : wiringPi.h odroidn2.h +odroidc4.o : wiringPi.h odroidc4.h wiringPi.o: softPwm.h softTone.h wiringPi.h ../version.h wiringSerial.o: wiringSerial.h diff --git a/wiringPi/odroidc4.c b/wiringPi/odroidc4.c new file mode 100644 index 0000000..8b9b3ff --- /dev/null +++ b/wiringPi/odroidc4.c @@ -0,0 +1,704 @@ +/*----------------------------------------------------------------------------*/ +// +// +// WiringPi ODROID-C4 Board Control file (AMLogic 64Bits Platform) +// +// +/*----------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*----------------------------------------------------------------------------*/ +#include "softPwm.h" +#include "softTone.h" + +/*----------------------------------------------------------------------------*/ +#include "wiringPi.h" +#include "odroidc4.h" + +/*----------------------------------------------------------------------------*/ +// wiringPi gpio map define +/*----------------------------------------------------------------------------*/ +static const int pinToGpio[64] = { + // wiringPi number to native gpio number + 479, 492, // 0 | 1 : GPIOX.3, GPIOX.16 + 480, 483, // 2 | 3 : GPIOX.4, GPIOX.7 + 476, 477, // 4 | 5 : GPIOX.0, GPIOX.1 + 478, 481, // 6 | 7 : GPIOX.2, GPIOX.5 + 493, 494, // 8 | 9 : GPIOX.17(I2C-2_SDA), GPIOX.18(I2C-2_SCL) + 486, 23, // 10 | 11 : GPIOX.10(SPI_SS), GPIOH.6 + 484, 485, // 12 | 13 : GPIOX.8(SPI_MOSI), GPIOX.9(SPI_MISO) + 487, 488, // 14 | 15 : GPIOX.11(SPI_CLK), GPIOX.12(UART_TX_B) + 489, -1, // 16 | 17 : GPIOX.13(UART_RX_B), + -1, - 1, // 18 | 19 : + -1, 490, // 20 | 21 : , GPIOX.14 + 491, 482, // 22 | 23 : GPIOX.15, GPIOX.6 + 495, -1, // 24 | 25 : GPIOX.19, ADC.AIN3 + 24, 22, // 26 | 27 : GPIOH.7, GPIOH.5 + -1, - 1, // 28 | 29 : REF1.8V OUT, ADC.AIC4 + 474, 475, // 30 | 31 : GPIOA.14(I2C-3_SDA), GPIOA.15(I2C-3_SCL) + // Padding: + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 32...47 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 48...63 +}; + +static const int phyToGpio[64] = { + // physical header pin number to native gpio number + -1, // 0 + -1, -1, // 1 | 2 : 3.3V, 5.0V + 493, -1, // 3 | 4 : GPIOX.17(I2C-2_SDA), 5.0V + 494, -1, // 5 | 6 : GPIOX.18(I2C-2_SCL), GND + 481, 488, // 7 | 8 : GPIOX.5, GPIOX.12(UART_TX_B) + -1, 489, // 9 | 10 : GND, GPIOX.13(UART_RX_B) + 479, 492, // 11 | 12 : GPIOX.3, GPIOX.16 + 480, -1, // 13 | 14 : GPIOX.4, GND + 483, 476, // 15 | 16 : GPIOX.7, GPIOX.0 + -1, 477, // 17 | 18 : 3.3V, GPIOX.1 + 484, -1, // 19 | 20 : GPIOX.8(SPI_MOSI), GND + 485, 478, // 21 | 22 : GPIOX.9(SPI_MISO), GPIOX.2 + 487, 486, // 23 | 24 : GPIOX.11(SPI_CLK), GPIOX.10(SPI_SS) + -1, 23, // 25 | 26 : GND, GPIOH.6 + 474, 475, // 27 | 28 : GPIOA.14(I2C-3_SDA), GPIOA.15(I2C-3_SCL) + 490, -1, // 29 | 30 : GPIOX.14, GND + 491, 24, // 31 | 32 : GPIOX.15, GPIOH.7 + 482, -1, // 33 | 34 : GPIOX.6, GND + 495, 22, // 35 | 36 : GPIOX.19, GPIOH.5 + -1, -1, // 37 | 38 : ADC.AIN3, 1.8V REF OUT + -1, -1, // 39 | 40 : GND, ADC.AIC4 + // Not used + -1, -1, -1, -1, -1, -1, -1, -1, // 41...48 + -1, -1, -1, -1, -1, -1, -1, -1, // 49...56 + -1, -1, -1, -1, -1, -1, -1 // 57...63 +}; + +/*----------------------------------------------------------------------------*/ +// +// Global variable define +// +/*----------------------------------------------------------------------------*/ +// wiringPi Pinmap control arrary +/*----------------------------------------------------------------------------*/ +/* ADC file descriptor */ +static int adcFds[2]; + +/* GPIO mmap control */ +static volatile uint32_t *gpio; + +/* wiringPi Global library */ +static struct libodroid *lib = NULL; + +/*----------------------------------------------------------------------------*/ +// Function prototype define +/*----------------------------------------------------------------------------*/ +static int gpioToGPSETReg (int pin); +static int gpioToGPLEVReg (int pin); +static int gpioToPUENReg (int pin); +static int gpioToPUPDReg (int pin); +static int gpioToShiftReg (int pin); +static int gpioToGPFSELReg (int pin); +static int gpioToDSReg (int pin); +static int gpioToMuxReg (int pin); + +/*----------------------------------------------------------------------------*/ +// wiringPi core function +/*----------------------------------------------------------------------------*/ +static int _getModeToGpio (int mode, int pin); +static int _setPadDrive (int pin, int value); +static int _getPadDrive (int pin); +static int _pinMode (int pin, int mode); +static int _getAlt (int pin); +static int _getPUPD (int pin); +static int _pullUpDnControl (int pin, int pud); +static int _digitalRead (int pin); +static int _digitalWrite (int pin, int value); +static int _analogRead (int pin); +static int _digitalWriteByte (const unsigned int value); +static unsigned int _digitalReadByte (void); + +/*----------------------------------------------------------------------------*/ +// board init function +/*----------------------------------------------------------------------------*/ +static void init_gpio_mmap (void); +static void init_adc_fds (void); + + void init_odroidc4 (struct libodroid *libwiring); + +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ +// +// offset to the GPIO Set regsiter +// +/*----------------------------------------------------------------------------*/ +static int gpioToGPSETReg (int pin) +{ + if (pin >= C4_GPIOH_PIN_START && pin <= C4_GPIOH_PIN_END) + return C4_GPIOH_OUTP_REG_OFFSET; + if (pin >= C4_GPIOA_PIN_START && pin <= C4_GPIOA_PIN_END) + return C4_GPIOA_OUTP_REG_OFFSET; + if (pin >= C4_GPIOX_PIN_START && pin <= C4_GPIOX_PIN_END) + return C4_GPIOX_OUTP_REG_OFFSET; + return -1; +} + +/*---------------------------------------------------------------------------r-*/ +// +// offset to the GPIO Input regsiter +// +/*----------------------------------------------------------------------------*/ +static int gpioToGPLEVReg (int pin) +{ + if (pin >= C4_GPIOH_PIN_START && pin <= C4_GPIOH_PIN_END) + return C4_GPIOH_INP_REG_OFFSET; + if (pin >= C4_GPIOA_PIN_START && pin <= C4_GPIOA_PIN_END) + return C4_GPIOA_INP_REG_OFFSET; + if (pin >= C4_GPIOX_PIN_START && pin <= C4_GPIOX_PIN_END) + return C4_GPIOX_INP_REG_OFFSET; + return -1; +} + +/*----------------------------------------------------------------------------*/ +// +// offset to the GPIO Pull up/down enable regsiter +// +/*----------------------------------------------------------------------------*/ +static int gpioToPUENReg (int pin) +{ + if (pin >= C4_GPIOH_PIN_START && pin <= C4_GPIOH_PIN_END) + return C4_GPIOH_PUEN_REG_OFFSET; + if (pin >= C4_GPIOA_PIN_START && pin <= C4_GPIOA_PIN_END) + return C4_GPIOA_PUEN_REG_OFFSET; + if (pin >= C4_GPIOX_PIN_START && pin <= C4_GPIOX_PIN_END) + return C4_GPIOX_PUEN_REG_OFFSET; + return -1; +} + +/*----------------------------------------------------------------------------*/ +// +// offset to the GPIO Pull up/down regsiter +// +/*----------------------------------------------------------------------------*/ +static int gpioToPUPDReg (int pin) +{ + if (pin >= C4_GPIOH_PIN_START && pin <= C4_GPIOH_PIN_END) + return C4_GPIOH_PUPD_REG_OFFSET; + if (pin >= C4_GPIOA_PIN_START && pin <= C4_GPIOA_PIN_END) + return C4_GPIOA_PUPD_REG_OFFSET; + if (pin >= C4_GPIOX_PIN_START && pin <= C4_GPIOX_PIN_END) + return C4_GPIOX_PUPD_REG_OFFSET; + return -1; +} + +/*----------------------------------------------------------------------------*/ +// +// offset to the GPIO bit +// +/*----------------------------------------------------------------------------*/ +static int gpioToShiftReg (int pin) +{ + if (pin >= C4_GPIOH_PIN_START && pin <= C4_GPIOH_PIN_END) + return pin - C4_GPIOH_PIN_START; + if (pin >= C4_GPIOA_PIN_START && pin <= C4_GPIOA_PIN_END) + return pin - C4_GPIOA_PIN_START; + if (pin >= C4_GPIOX_PIN_START && pin <= C4_GPIOX_PIN_END) + return pin - C4_GPIOX_PIN_START; + return -1; +} + +/*----------------------------------------------------------------------------*/ +// +// offset to the GPIO Function register +// +/*----------------------------------------------------------------------------*/ +static int gpioToGPFSELReg (int pin) +{ + if (pin >= C4_GPIOH_PIN_START && pin <= C4_GPIOH_PIN_END) + return C4_GPIOH_FSEL_REG_OFFSET; + if(pin >= C4_GPIOA_PIN_START && pin <= C4_GPIOA_PIN_END) + return C4_GPIOA_FSEL_REG_OFFSET; + if(pin >= C4_GPIOX_PIN_START && pin <= C4_GPIOX_PIN_END) + return C4_GPIOX_FSEL_REG_OFFSET; + return -1; +} + +/*----------------------------------------------------------------------------*/ +// +// offset to the GPIO Drive Strength register +// +/*----------------------------------------------------------------------------*/ +static int gpioToDSReg (int pin) +{ + if (pin >= C4_GPIOH_PIN_START && pin <= C4_GPIOH_PIN_END) + return C4_GPIOH_DS_REG_3A_OFFSET; + if (pin >= C4_GPIOA_PIN_START && pin <= C4_GPIOA_PIN_END) + return C4_GPIOA_DS_REG_5A_OFFSET; + if (pin >= C4_GPIOX_PIN_START && pin <= C4_GPIOX_PIN_MID) + return C4_GPIOX_DS_REG_2A_OFFSET; + if (pin > C4_GPIOX_PIN_MID && pin <= C4_GPIOX_PIN_END) + return C4_GPIOX_DS_REG_2B_OFFSET; + return -1; +} + +/*----------------------------------------------------------------------------*/ +// +// offset to the GPIO Pin Mux register +// +/*----------------------------------------------------------------------------*/ +static int gpioToMuxReg (int pin) +{ + switch (pin) { + case C4_GPIOH_PIN_START ...C4_GPIOH_PIN_END: + return C4_GPIOH_MUX_B_REG_OFFSET; + case C4_GPIOA_PIN_START ...C4_GPIOA_PIN_START + 7: + return C4_GPIOA_MUX_D_REG_OFFSET; + case C4_GPIOA_PIN_START + 8 ...C4_GPIOA_PIN_END: + return C4_GPIOA_MUX_E_REG_OFFSET; + case C4_GPIOX_PIN_START ...C4_GPIOX_PIN_START + 7: + return C4_GPIOX_MUX_3_REG_OFFSET; + case C4_GPIOX_PIN_START + 8 ...C4_GPIOX_PIN_START + 15: + return C4_GPIOX_MUX_4_REG_OFFSET; + case C4_GPIOX_PIN_START + 16 ...C4_GPIOX_PIN_END: + return C4_GPIOX_MUX_5_REG_OFFSET; + default: + return -1; + } +} + +/*----------------------------------------------------------------------------*/ +static int _getModeToGpio (int mode, int pin) +{ + int retPin = -1; + + switch (mode) { + /* Native gpio number */ + case MODE_GPIO: + retPin = pin; + break; + /* Native gpio number for sysfs */ + case MODE_GPIO_SYS: + retPin = lib->sysFds[pin] != -1 ? pin : -1; + break; + /* wiringPi number */ + case MODE_PINS: + retPin = pin < 64 ? pinToGpio[pin] : -1; + break; + /* header pin number */ + case MODE_PHYS: + retPin = pin < 64 ? phyToGpio[pin] : -1; + break; + default : + msg(MSG_WARN, "%s : Unknown Mode %d\n", __func__, mode); + return -1; + } + + return retPin; +} + +/*----------------------------------------------------------------------------*/ +static int _setPadDrive (int pin, int value) +{ + int ds, shift; + + if (lib->mode == MODE_GPIO_SYS) + return -1; + + if ((pin = _getModeToGpio(lib->mode, pin)) < 0) + return -1; + + if (value < 0 || value > 3) { + msg(MSG_WARN, "%s : Invalid value %d (Must be 0 ~ 3)\n", __func__, value); + return -1; + } + + ds = gpioToDSReg(pin); + shift = gpioToShiftReg(pin); + shift = pin > C4_GPIOX_PIN_MID ? (shift - 16) * 2 : shift * 2; + + *(gpio + ds) &= ~(0b11 << shift); + *(gpio + ds) |= (value << shift); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +static int _getPadDrive (int pin) +{ + int ds, shift; + + if (lib->mode == MODE_GPIO_SYS) + return -1; + + if ((pin = _getModeToGpio(lib->mode, pin)) < 0) + return -1; + + ds = gpioToDSReg(pin); + shift = gpioToShiftReg(pin); + shift = pin > C4_GPIOX_PIN_MID ? (shift - 16) * 2 : shift * 2; + + return (*(gpio + ds) >> shift) & 0b11; +} + +/*----------------------------------------------------------------------------*/ +static int _pinMode (int pin, int mode) +{ + int fsel, shift, origPin = pin; + + if (lib->mode == MODE_GPIO_SYS) + return -1; + + if ((pin = _getModeToGpio(lib->mode, pin)) < 0) + return -1; + + softPwmStop (origPin); + softToneStop (origPin); + + fsel = gpioToGPFSELReg(pin); + shift = gpioToShiftReg (pin); + + switch (mode) { + case INPUT: + *(gpio + fsel) = (*(gpio + fsel) | (1 << shift)); + break; + case OUTPUT: + *(gpio + fsel) = (*(gpio + fsel) & ~(1 << shift)); + break; + case SOFT_PWM_OUTPUT: + softPwmCreate (pin, 0, 100); + break; + case SOFT_TONE_OUTPUT: + softToneCreate (pin); + break; + default: + msg(MSG_WARN, "%s : Unknown Mode %d\n", __func__, mode); + return -1; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +static int _getAlt (int pin) +{ + int fsel, mux, shift, target, mode; + + if (lib->mode == MODE_GPIO_SYS) + return -1; + + if ((pin = _getModeToGpio(lib->mode, pin)) < 0) + return -1; + + fsel = gpioToGPFSELReg(pin); + mux = gpioToMuxReg(pin); + target = shift = gpioToShiftReg(pin); + + while (target >= 8) { + target -= 8; + } + + mode = (*(gpio + mux) >> (target * 4)) & 0xF; + return mode ? mode + 1 : (*(gpio + fsel) & (1 << shift)) ? 0 : 1; +} + +/*----------------------------------------------------------------------------*/ +static int _getPUPD (int pin) +{ + int puen, pupd, shift; + + if (lib->mode == MODE_GPIO_SYS) + return -1; + + if ((pin = _getModeToGpio(lib->mode, pin)) < 0) + return -1; + + puen = gpioToPUENReg(pin); + pupd = gpioToPUPDReg(pin); + shift = gpioToShiftReg(pin); + + if (*(gpio + puen) & (1 << shift)) + return *(gpio + pupd) & (1 << shift) ? 1 : 2; + else + return 0; +} + +/*----------------------------------------------------------------------------*/ +static int _pullUpDnControl (int pin, int pud) +{ + int shift = 0; + + if (lib->mode == MODE_GPIO_SYS) + return -1; + + if ((pin = _getModeToGpio(lib->mode, pin)) < 0) + return -1; + + shift = gpioToShiftReg(pin); + + if (pud) { + // Enable Pull/Pull-down resister + *(gpio + gpioToPUENReg(pin)) = + (*(gpio + gpioToPUENReg(pin)) | (1 << shift)); + + if (pud == PUD_UP) + *(gpio + gpioToPUPDReg(pin)) = + (*(gpio + gpioToPUPDReg(pin)) | (1 << shift)); + else + *(gpio + gpioToPUPDReg(pin)) = + (*(gpio + gpioToPUPDReg(pin)) & ~(1 << shift)); + } else // Disable Pull/Pull-down resister + *(gpio + gpioToPUENReg(pin)) = + (*(gpio + gpioToPUENReg(pin)) & ~(1 << shift)); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +static int _digitalRead (int pin) +{ + char c ; + + if (lib->mode == MODE_GPIO_SYS) { + if (lib->sysFds[pin] == -1) + return -1; + + lseek (lib->sysFds[pin], 0L, SEEK_SET); + if (read(lib->sysFds[pin], &c, 1) < 0) { + msg(MSG_WARN, "%s: Failed with reading from sysfs GPIO node. \n", __func__); + return -1; + } + + return (c == '0') ? LOW : HIGH; + } + + if ((pin = _getModeToGpio(lib->mode, pin)) < 0) + return -1; + + if ((*(gpio + gpioToGPLEVReg(pin)) & (1 << gpioToShiftReg(pin))) != 0) + return HIGH ; + else + return LOW ; +} + +/*----------------------------------------------------------------------------*/ +static int _digitalWrite (int pin, int value) +{ + if (lib->mode == MODE_GPIO_SYS) { + if (lib->sysFds[pin] != -1) { + if (value == LOW) { + if (write(lib->sysFds[pin], "0\n", 2) < 0) + msg(MSG_WARN, "%s: Failed with reading from sysfs GPIO node. \n", __func__); + } else { + if (write(lib->sysFds[pin], "1\n", 2) < 0) + msg(MSG_WARN, "%s: Failed with reading from sysfs GPIO node. \n", __func__); + } + } + return -1; + } + + if ((pin = _getModeToGpio(lib->mode, pin)) < 0) + return -1; + + if (value == LOW) + *(gpio + gpioToGPSETReg(pin)) &= ~(1 << gpioToShiftReg(pin)); + else + *(gpio + gpioToGPSETReg(pin)) |= (1 << gpioToShiftReg(pin)); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +static int _analogRead (int pin) +{ + char value[5] = {0,}; + + if (lib->mode == MODE_GPIO_SYS) + return -1; + + /* wiringPi ADC number = pin 25, pin 29 */ + switch (pin) { + case 3: case 25: + pin = 0; + break; + case 2: case 29: + pin = 1; + break; + default: + return 0; + } + if (adcFds [pin] == -1) + return 0; + + lseek (adcFds [pin], 0L, SEEK_SET); + if (read(adcFds [pin], &value[0], 4) < 0) { + msg(MSG_WARN, "%s: Error occurs when it reads from ADC file descriptor. \n", __func__); + return -1; + } + + return atoi(value); +} + +/*----------------------------------------------------------------------------*/ +static int _digitalWriteByte (const unsigned int value) +{ + union reg_bitfield gpiox; + + if (lib->mode == MODE_GPIO_SYS) + return -1; + + gpiox.wvalue = *(gpio + C4_GPIOX_INP_REG_OFFSET); + + /* Wiring PI GPIO0 = C4 GPIOX.3 */ + gpiox.bits.bit3 = (value & 0x01); + /* Wiring PI GPIO1 = C4 GPIOX.16 */ + gpiox.bits.bit16 = (value & 0x02); + /* Wiring PI GPIO2 = C4 GPIOX.4 */ + gpiox.bits.bit4 = (value & 0x04); + /* Wiring PI GPIO3 = C4 GPIOX.7 */ + gpiox.bits.bit7 = (value & 0x08); + /* Wiring PI GPIO4 = C4 GPIOX.0 */ + gpiox.bits.bit0 = (value & 0x10); + /* Wiring PI GPIO5 = C4 GPIOX.1 */ + gpiox.bits.bit1 = (value & 0x20); + /* Wiring PI GPIO6 = C4 GPIOX.2 */ + gpiox.bits.bit2 = (value & 0x40); + /* Wiring PI GPIO7 = C4 GPIOX.5 */ + gpiox.bits.bit5 = (value & 0x80); + + *(gpio + C4_GPIOX_OUTP_REG_OFFSET) = gpiox.wvalue; + + return 0; +} + +/*----------------------------------------------------------------------------*/ +static unsigned int _digitalReadByte (void) +{ + union reg_bitfield gpiox; + unsigned int value = 0; + + if (lib->mode == MODE_GPIO_SYS) + return -1; + + gpiox.wvalue = *(gpio + C4_GPIOX_INP_REG_OFFSET); + + /* Wiring PI GPIO0 = C4 GPIOX.3 */ + if (gpiox.bits.bit3) + value |= 0x01; + /* Wiring PI GPIO1 = C4 GPIOX.16 */ + if (gpiox.bits.bit16) + value |= 0x02; + /* Wiring PI GPIO2 = C4 GPIOX.4 */ + if (gpiox.bits.bit4) + value |= 0x04; + /* Wiring PI GPIO3 = C4 GPIOX.7 */ + if (gpiox.bits.bit7) + value |= 0x08; + /* Wiring PI GPIO4 = C4 GPIOX.0 */ + if (gpiox.bits.bit0) + value |= 0x10; + /* Wiring PI GPIO5 = C4 GPIOX.1 */ + if (gpiox.bits.bit1) + value |= 0x20; + /* Wiring PI GPIO6 = C4 GPIOX.2 */ + if (gpiox.bits.bit2) + value |= 0x40; + /* Wiring PI GPIO7 = C4 GPIOX.5 */ + if (gpiox.bits.bit5) + value |= 0x80; + + return value; +} + +/*----------------------------------------------------------------------------*/ +static void init_gpio_mmap (void) +{ + int fd = -1; + void *mapped; + + /* GPIO mmap setup */ + if (!getuid()) { + if ((fd = open ("/dev/mem", O_RDWR | O_SYNC | O_CLOEXEC) ) < 0) + msg (MSG_ERR, + "wiringPiSetup: Unable to open /dev/mem: %s\n", + strerror (errno)); + } else { + if (access("/dev/gpiomem",0) == 0) { + if ((fd = open ("/dev/gpiomem", O_RDWR | O_SYNC | O_CLOEXEC) ) < 0) + msg (MSG_ERR, + "wiringPiSetup: Unable to open /dev/gpiomem: %s\n", + strerror (errno)); + } else + msg (MSG_ERR, + "wiringPiSetup: /dev/gpiomem doesn't exist. Please try again with sudo.\n"); + } + + if (fd < 0) { + msg(MSG_ERR, "wiringPiSetup: Cannot open memory area for GPIO use. \n"); + } else { + // #define C4_GPIO_BASE 0xff634000 +#ifdef ANDROID +#if defined(__aarch64__) + mapped = mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, C4_GPIO_BASE); +#else + mapped = mmap64(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, (off64_t)C4_GPIO_BASE); +#endif +#else + mapped = mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, C4_GPIO_BASE); +#endif + + if (mapped == MAP_FAILED) + msg(MSG_ERR, "wiringPiSetup: mmap (GPIO) failed: %s \n", strerror (errno)); + else + gpio = (uint32_t *) mapped; + } +} + +/*----------------------------------------------------------------------------*/ +static void init_adc_fds (void) +{ + const char *AIN25_NODE, *AIN29_NODE; + + /* ADC node setup */ + AIN25_NODE = "/sys/devices/platform/ff809000.saradc/iio:device0/in_voltage2_raw"; + AIN29_NODE = "/sys/devices/platform/ff809000.saradc/iio:device0/in_voltage0_raw"; + + adcFds[0] = open(AIN25_NODE, O_RDONLY); + adcFds[1] = open(AIN29_NODE, O_RDONLY); +} + +/*----------------------------------------------------------------------------*/ +void init_odroidc4 (struct libodroid *libwiring) +{ + init_gpio_mmap(); + + init_adc_fds(); + + /* wiringPi Core function initialize */ + libwiring->getModeToGpio = _getModeToGpio; + libwiring->setPadDrive = _setPadDrive; + libwiring->getPadDrive = _getPadDrive; + libwiring->pinMode = _pinMode; + libwiring->getAlt = _getAlt; + libwiring->getPUPD = _getPUPD; + libwiring->pullUpDnControl = _pullUpDnControl; + libwiring->digitalRead = _digitalRead; + libwiring->digitalWrite = _digitalWrite; + libwiring->analogRead = _analogRead; + libwiring->digitalWriteByte = _digitalWriteByte; + libwiring->digitalReadByte = _digitalReadByte; + + /* specify pin base number */ + libwiring->pinBase = C4_GPIO_PIN_BASE; + + /* global variable setup */ + lib = libwiring; +} + +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ diff --git a/wiringPi/odroidc4.h b/wiringPi/odroidc4.h new file mode 100644 index 0000000..94fb88e --- /dev/null +++ b/wiringPi/odroidc4.h @@ -0,0 +1,65 @@ +/*----------------------------------------------------------------------------*/ +/* + + WiringPi ODROID-C4 Board Header file + + */ +/*----------------------------------------------------------------------------*/ +#ifndef __ODROID_C4_H__ +#define __ODROID_C4_H__ + +/*----------------------------------------------------------------------------*/ +#define C4_GPIO_BASE 0xFF634000 + +#define C4_GPIO_PIN_BASE 460 + +#define C4_GPIOH_PIN_START 17 // GPIOH_0 +#define C4_GPIOH_PIN_END 25 // GPIOH_8 +#define C4_GPIOA_PIN_START C4_GPIO_PIN_BASE // GPIOA_0 +#define C4_GPIOA_PIN_END (C4_GPIO_PIN_BASE + 15) // GPIOA_15 +#define C4_GPIOX_PIN_START (C4_GPIO_PIN_BASE + 16) // GPIOX_0 +#define C4_GPIOX_PIN_MID (C4_GPIO_PIN_BASE + 31) // GPIOX_15 +#define C4_GPIOX_PIN_END (C4_GPIO_PIN_BASE + 35) // GPIOX_19 + +#define C4_GPIOH_FSEL_REG_OFFSET 0x119 +#define C4_GPIOH_OUTP_REG_OFFSET 0x11A +#define C4_GPIOH_INP_REG_OFFSET 0x11B +#define C4_GPIOH_PUPD_REG_OFFSET 0x13D +#define C4_GPIOH_PUEN_REG_OFFSET 0x14B +#define C4_GPIOH_DS_REG_3A_OFFSET 0x1D4 +#define C4_GPIOH_MUX_B_REG_OFFSET 0x1BB + +#define C4_GPIOA_FSEL_REG_OFFSET 0x120 +#define C4_GPIOA_OUTP_REG_OFFSET 0x121 +#define C4_GPIOA_INP_REG_OFFSET 0x122 +#define C4_GPIOA_PUPD_REG_OFFSET 0x13F +#define C4_GPIOA_PUEN_REG_OFFSET 0x14D +#define C4_GPIOA_DS_REG_5A_OFFSET 0x1D6 +#define C4_GPIOA_MUX_D_REG_OFFSET 0x1BD +#define C4_GPIOA_MUX_E_REG_OFFSET 0x1BE + +#define C4_GPIOX_FSEL_REG_OFFSET 0x116 +#define C4_GPIOX_OUTP_REG_OFFSET 0x117 +#define C4_GPIOX_INP_REG_OFFSET 0x118 +#define C4_GPIOX_PUPD_REG_OFFSET 0x13C +#define C4_GPIOX_PUEN_REG_OFFSET 0x14A +#define C4_GPIOX_DS_REG_2A_OFFSET 0x1D2 +#define C4_GPIOX_DS_REG_2B_OFFSET 0x1D3 +#define C4_GPIOX_MUX_3_REG_OFFSET 0x1B3 +#define C4_GPIOX_MUX_4_REG_OFFSET 0x1B4 +#define C4_GPIOX_MUX_5_REG_OFFSET 0x1B5 + +#ifdef __cplusplus +extern "C" { +#endif + +extern void init_odroidc4 (struct libodroid *libwiring); + +#ifdef __cplusplus +} +#endif + +/*----------------------------------------------------------------------------*/ +#endif /* __ODROID_C4_H__ */ +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index 54d0484..9f658e8 100755 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -37,6 +37,7 @@ #include "odroidxu3.h" #include "odroidn1.h" #include "odroidn2.h" +#include "odroidc4.h" /*----------------------------------------------------------------------------*/ // Const string define @@ -49,6 +50,7 @@ const char *piModelNames [16] = "ODROID-XU3/4", "ODROID-N1", "ODROID-N2", + "ODROID-C4", }; const char *piRevisionNames [16] = @@ -441,6 +443,11 @@ int piGpioLayout (void) libwiring.maker = MAKER_AMLOGIC; libwiring.mem = 4; libwiring.rev = 1; + } else if (strncmp (c, "05", 2) == 0) { + libwiring.model = MODEL_ODROID_C4; + libwiring.maker = MAKER_AMLOGIC; + libwiring.mem = 4; + libwiring.rev = 1; } else { libwiring.model = MODEL_UNKNOWN; libwiring.maker = MAKER_UNKNOWN; @@ -474,6 +481,7 @@ int piBoardRev (void) * Rev 1.1 : /sys/class/odroid/boardrev value is 1 (Mass board) * 03xx - Model ODROID N1, 4096M, Hardkernel * 04xx - Model ODROID N2, 4096M, Hardkernel + * 05xx - Model ODROID C4, 4096M, Hardkernel */ /*----------------------------------------------------------------------------*/ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) @@ -1073,6 +1081,9 @@ int wiringPiSetup (void) case MODEL_ODROID_N2: init_odroidn2(&libwiring); break; + case MODEL_ODROID_C4: + init_odroidc4(&libwiring); + break; default: return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: Unknown model\n"); diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index 25d8dd8..a00dc9d 100755 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -52,6 +52,7 @@ #define MODEL_ODROID_XU3 3 #define MODEL_ODROID_N1 4 #define MODEL_ODROID_N2 5 +#define MODEL_ODROID_C4 6 #define MAKER_UNKNOWN 0 #define MAKER_AMLOGIC 1 diff --git a/wiringPi/wiringPiI2C.c b/wiringPi/wiringPiI2C.c index b9fc54a..48d0a1e 100644 --- a/wiringPi/wiringPiI2C.c +++ b/wiringPi/wiringPiI2C.c @@ -251,6 +251,7 @@ int wiringPiI2CSetup (const int devId) device = "/dev/i2c-4"; break; case MODEL_ODROID_N2: + case MODEL_ODROID_C4: device = "/dev/i2c-2"; break; } diff --git a/wiringPi/wiringPiSPI.c b/wiringPi/wiringPiSPI.c index 5166383..406f099 100644 --- a/wiringPi/wiringPiSPI.c +++ b/wiringPi/wiringPiSPI.c @@ -146,6 +146,7 @@ int wiringPiSPISetupMode (int channel, int speed, int mode) switch(model) { case MODEL_ODROID_C1: case MODEL_ODROID_N2: + case MODEL_ODROID_C4: sprintf(device, "%s%d", spiDevType0, channel); break; case MODEL_ODROID_XU3: