wiringOP-Python/wiringOP/wiringPi/wiringPi.c

4967 lines
153 KiB
C
Raw Normal View History

2024-06-06 12:13:43 +08:00
/*
* wiringPi:
* Arduino look-a-like Wiring library for the Raspberry Pi
* Copyright (c) 2012-2017 Gordon Henderson
* Additional code for pwmSetClock by Chris Hall <chris@kchall.plus.com>
*
* Thanks to code samples from Gert Jan van Loo and the
* BCM2835 ARM Peripherals manual, however it's missing
* the clock section /grr/mutter/
***********************************************************************
* This file is part of wiringPi:
* https://projects.drogon.net/raspberry-pi/wiringpi/
*
* wiringPi is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* wiringPi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with wiringPi.
* If not, see <http://www.gnu.org/licenses/>.
***********************************************************************
*/
// Revisions:
// 19 Jul 2012:
// Moved to the LGPL
// Added an abstraction layer to the main routines to save a tiny
// bit of run-time and make the clode a little cleaner (if a little
// larger)
// Added waitForInterrupt code
// Added piHiPri code
//
// 9 Jul 2012:
// Added in support to use the /sys/class/gpio interface.
// 2 Jul 2012:
// Fixed a few more bugs to do with range-checking when in GPIO mode.
// 11 Jun 2012:
// Fixed some typos.
// Added c++ support for the .h file
// Added a new function to allow for using my "pin" numbers, or native
// GPIO pin numbers.
// Removed my busy-loop delay and replaced it with a call to delayMicroseconds
//
// 02 May 2012:
// Added in the 2 UART pins
// Change maxPins to numPins to more accurately reflect purpose
#include <stdio.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdlib.h>
#include <ctype.h>
#include <poll.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <asm/ioctl.h>
#include "softPwm.h"
#include "softTone.h"
#include "wiringPi.h"
#include "../version.h"
// Environment Variables
#define ENV_DEBUG "WIRINGPI_DEBUG"
#define ENV_CODES "WIRINGPI_CODES"
#define ENV_GPIOMEM "WIRINGPI_GPIOMEM"
int pwmmode = 1;
static int ORANGEPI_PIN_MASK_3[12][32] = //[BANK] [INDEX]
{
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PA
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PB
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PC
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,15,16,-1,18,-1,-1,21,22,23,24,25,26,-1,-1,-1,-1,-1,},//PD
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PE
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PF
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PG
{-1,-1,-1, 3, 4, 5, 6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PH
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PI
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PJ
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PK
{-1,-1, 2, 3,-1,-1,-1,-1, 8,-1,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PL
};
static int ORANGEPI_PIN_MASK_LITE_2[12][32] = //[BANK] [INDEX]
{
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PA
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PB
{ 0,-1, 2, 3,-1, 5,-1, 7, 8, 9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PC
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,21,22,23,24,25,26,-1,-1,-1,-1,-1,},//PD
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PE
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PF
{-1,-1,-1,-1,-1,-1, 6, 7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PG
{-1,-1,-1, 3, 4, 5, 6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PH
};
static int ORANGEPI_PIN_MASK_ZERO[12][32] = //[BANK] [INDEX]
{
{ 0, 1, 2, 3,-1,-1, 6, 7,-1,-1,10,11,12,13,14,15,16,-1,18,19,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PA
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PB
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PC
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PD
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PE
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PF
{-1,-1,-1,-1,-1,-1, 6, 7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PG
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PH
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PI
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PJ
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PK
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PL
};
static int ORANGEPI_PIN_MASK_ZERO_PLUS_2[12][32] = //[BANK] [INDEX]
{
{ 0, 1, 2, 3,-1,-1, 6,-1,-1,-1,-1,11,12,13,14,15,16,-1,18,19,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PA
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PB
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PC
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,11,-1,-1,14,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PD
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PE
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PF
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PG
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PH
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PI
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PJ
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PK
{ 0, 1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PL
};
static int ORANGEPI_PIN_MASK_WIN[12][32] = //[BANK] [INDEX]
{
{ 0, 1, 2, 3,-1,-1, 6, 7, 8, 9,10,11,12,13,14,15,16,-1,18,19,20,21,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PA
{ 0, 1, 2, 3, 4, 5, 6, 7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PB
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PC
{ 0, 1, 2, 3, 4, 5, 6,-1,-1,-1,-1,11,-1,-1,14,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PD
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PE
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PF
{-1,-1,-1,-1,-1,-1, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PG
{-1,-1, 2, 3, 4, 5, 6, 7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PH
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PI
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PJ
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PK
{-1,-1, 2, 3,-1,-1,-1,-1,-1, 9,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PL
};
static int ORANGEPI_PIN_MASK_PRIME[9][32] = //[BANK] [INDEX]
{
{ 0, 1, 2, 3,-1,-1, 6, 7, 8, 9,10,11,12,13,14,15,16,-1,18,19,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PA
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PB
{-1,-1,-1,-1, 4, 5, 6, 7, 8, 9,10,11,12,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PC
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,11,-1,-1,14,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PD
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PE
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PF
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PG
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PH
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PI
};
static int ORANGEPI_PIN_MASK_PC_2[9][32] = //[BANK] [INDEX]
{
{ 0, 1, 2, 3,-1,-1, 6, 7, 8, 9,10,11,12,13,14,15,16,-1,18,19,-1,21,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PA
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PB
{-1,-1,-1,-1, 4, 5, 6, 7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PC
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,11,-1,-1,14,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PD
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PE
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PF
{-1,-1,-1,-1,-1,-1, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PG
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PH
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PI
};
static int ORANGEPI_PIN_MASK_ZERO_PLUS[12][32] = //[BANK] [INDEX]
{
{ 0, 1, 2, 3,-1,-1, 6, 7,-1,-1,10,11,12,13,14,15,16,-1,18,19,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PA
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PB
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PC
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PD
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PE
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PF
{-1,-1,-1,-1,-1,-1, 6, 7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PG
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PH
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PI
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PJ
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PK
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PL
};
static int ORANGEPI_PIN_MASK_ZERO_2[12][32] = //[BANK] [INDEX]
{
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PA
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PB
{-1, 1,-1,-1,-1, 5, 6, 7, 8, 9,10,11,-1,-1,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PC
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PD
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PE
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PF
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PG
{-1,-1, 2, 3, 4, 5, 6, 7, 8, 9,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PH
{-1,-1,-1,-1,-1,-1, 6,-1,-1,-1,-1,-1,-1,-1,-1,-1,16,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PI
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PJ
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PK
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PE
};
static int ORANGEPI_PIN_MASK_ZERO_2_W[12][32] = //[BANK] [INDEX]
{
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PA
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PB
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,12,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PC
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PD
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PE
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PF
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PG
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PH
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PI
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PJ
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PK
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PE
};
static int ORANGEPI_PIN_MASK_800[5][32] = //[BANK] [INDEX]
{
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},
};
static int ORANGEPI_PIN_MASK_4[5][32] = //[BANK] [INDEX]
{
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},//PA
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},//PB
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},//PC
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},//PD
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},//PD
};
static int ORANGEPI_PIN_MASK_4_LTS[5][32] = //[BANK] [INDEX]
{
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},//PA
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},//PB
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},//PC
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},//PD
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},//PD
};
static int ORANGEPI_PIN_MASK_RK3399[5][32] = //[BANK] [INDEX]
{
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},//PA
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},//PB
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},//PC
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},//PD
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},//PD
};
static int ORANGEPI_PIN_MASK_5[5][32] = //[BANK] [INDEX]
{
{-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1, 4, 5,-1,-1,},//GPIO0
{-1,-1,-1, 3,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1, 6, 7, 0, 1, 2,-1, 4,-1, 6,-1, -1,-1, 2, 3,-1,-1,-1,-1,},//GPIO1
{-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1, 4,-1,-1,-1,},//GPIO2
{-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,},//GPIO3
{-1,-1,-1, 3, 4,-1,-1,-1, -1,-1, 2, 3, 4,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,},//GPIO4
};
static int ORANGEPI_PIN_MASK_5B[5][32] = //[BANK] [INDEX]
{
{-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1, 4, 5,-1,-1,},//GPIO0
{-1,-1,-1, 3,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1, 6, 7, 0, 1, 2,-1, 4,-1, 6,-1, -1,-1, 2, 3,-1,-1,-1,-1,},//GPIO1
{-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,},//GPIO2
{-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,},//GPIO3
{-1,-1,-1, 3, 4,-1,-1,-1, -1,-1, 2, 3, 4,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,},//GPIO4
};
static int ORANGEPI_PIN_MASK_5PLUS[5][32] = //[BANK] [INDEX]
{
{-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1, 7, 0,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,},//GPIO0
{ 0, 1, 2, 3, 4,-1,-1, 7, 0, 1, 2, 3, 4, 5, 6, 7, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1, 6, 7,},//GPIO1
{-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,},//GPIO2
{ 0, 1, 2, 3, 4, 5,-1,-1, -1,-1,-1,-1,-1, 5, 6,-1, -1, 1, 2,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,},//GPIO3
{-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,},//GPIO4
};
static int ORANGEPI_PIN_MASK_900[5][32] = //[BANK] [INDEX]
{
{-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,},//GPIO0
{ 0, 1, 2, 3, 4,-1,-1, 7, 0, 1, 2, 3, 4, 5, 6, 7, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1, 6, 7,},//GPIO1
{-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,},//GPIO2
{ 0, 1, 2, 3, 4, 5,-1,-1, -1,-1, 2, 3,-1, 5, 6,-1, -1, 1, 2,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,},//GPIO3
{-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,},//GPIO4
};
static int ORANGEPI_PIN_MASK_CM4[5][32] = //[BANK] [INDEX]
{
{-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, 0, 1,-1,-1,-1,-1,-1,-1,},//GPIO0
{ 0, 1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,},//GPIO1
{-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,},//GPIO2
{-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1, 6, 7, 0, 1, 2, 3, 4, 5,-1, 7,},//GPIO3
{ 0, 1, 2, 3, 4, 5, 6, 7, 0,-1, 2, 3, 4, 5,-1,-1, 0,-1,-1, 3,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,},//GPIO4
};
static int ORANGEPI_PIN_MASK_R1_PLUS[5][32] = //[BANK] [INDEX]
{
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},//PA
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},//PB
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},//PC
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},//PD
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,},//PD
};
static int ORANGEPI_PIN_MASK_H3[9][32] = //[BANK] [INDEX]
{
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,-1,-1,-1,18,19,20,21,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PA
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PB
{ 0, 1, 2, 3, 4,-1,-1, 7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PC
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,14,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PD
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PE
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PF
{-1,-1,-1,-1,-1,-1, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PG
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PH
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,},//PI
};
int (*ORANGEPI_PIN_MASK)[32];
// Extend wiringPi with other pin-based devices and keep track of
// them in this structure
struct wiringPiNodeStruct *wiringPiNodes = NULL ;
// BCM Magic
#define BCM_PASSWORD 0x5A000000
// The BCM2835 has 54 GPIO pins.
// BCM2835 data sheet, Page 90 onwards.
// There are 6 control registers, each control the functions of a block
// of 10 pins.
// Each control register has 10 sets of 3 bits per GPIO pin - the ALT values
//
// 000 = GPIO Pin X is an input
// 001 = GPIO Pin X is an output
// 100 = GPIO Pin X takes alternate function 0
// 101 = GPIO Pin X takes alternate function 1
// 110 = GPIO Pin X takes alternate function 2
// 111 = GPIO Pin X takes alternate function 3
// 011 = GPIO Pin X takes alternate function 4
// 010 = GPIO Pin X takes alternate function 5
//
// So the 3 bits for port X are:
// X / 10 + ((X % 10) * 3)
// Port function select bits
#define FSEL_INPT 0b000
#define FSEL_OUTP 0b001
#define FSEL_ALT0 0b100
#define FSEL_ALT1 0b101
#define FSEL_ALT2 0b110
#define FSEL_ALT3 0b111
#define FSEL_ALT4 0b011
#define FSEL_ALT5 0b010
// Access from ARM Running Linux
// Taken from Gert/Doms code. Some of this is not in the manual
// that I can find )-:
//
// Updates in September 2015 - all now static variables (and apologies for the caps)
// due to the Pi v2, v3, etc. and the new /dev/gpiomem interface
static volatile unsigned int GPIO_PADS ;
static volatile unsigned int GPIO_CLOCK_BASE ;
#ifndef CONFIG_ORANGEPI
static volatile unsigned int GPIO_BASE ;
#endif
static volatile unsigned int GPIO_TIMER ;
//static volatile unsigned int GPIO_PWM;
#define PAGE_SIZE (4*1024)
#define BLOCK_SIZE (4*1024)
static unsigned int usingGpioMem = FALSE ;
static int wiringPiSetuped = FALSE ;
static int wiringPiSysSetuped = FALSE ;
// PWM
// Word offsets into the PWM control region
#define PWM_CONTROL 0
#define PWM_STATUS 1
#define PWM0_RANGE 4
#define PWM0_DATA 5
#define PWM1_RANGE 8
#define PWM1_DATA 9
// Clock regsiter offsets
#define PWMCLK_CNTL 40
#define PWMCLK_DIV 41
#define PWM0_MS_MODE 0x0080 // Run in MS mode
#define PWM0_USEFIFO 0x0020 // Data from FIFO
#define PWM0_REVPOLAR 0x0010 // Reverse polarity
#define PWM0_OFFSTATE 0x0008 // Ouput Off state
#define PWM0_REPEATFF 0x0004 // Repeat last value if FIFO empty
#define PWM0_SERIAL 0x0002 // Run in serial mode
#define PWM0_ENABLE 0x0001 // Channel Enable
#define PWM1_MS_MODE 0x8000 // Run in MS mode
#define PWM1_USEFIFO 0x2000 // Data from FIFO
#define PWM1_REVPOLAR 0x1000 // Reverse polarity
#define PWM1_OFFSTATE 0x0800 // Ouput Off state
#define PWM1_REPEATFF 0x0400 // Repeat last value if FIFO empty
#define PWM1_SERIAL 0x0200 // Run in serial mode
#define PWM1_ENABLE 0x0100 // Channel Enable
// Timer
// Word offsets
#define TIMER_LOAD (0x400 >> 2)
#define TIMER_VALUE (0x404 >> 2)
#define TIMER_CONTROL (0x408 >> 2)
#define TIMER_IRQ_CLR (0x40C >> 2)
#define TIMER_IRQ_RAW (0x410 >> 2)
#define TIMER_IRQ_MASK (0x414 >> 2)
#define TIMER_RELOAD (0x418 >> 2)
#define TIMER_PRE_DIV (0x41C >> 2)
#define TIMER_COUNTER (0x420 >> 2)
// Locals to hold pointers to the hardware
static volatile unsigned int *gpio ;
static volatile unsigned int *pwm ;
static volatile unsigned int *clk ;
static volatile unsigned int *pads ;
//static volatile unsigned int *timer ;
//static volatile unsigned int *timerIrqRaw ;
// Export variables for the hardware pointers
volatile unsigned int *_wiringPiGpio ;
volatile unsigned int *_wiringPiPwm ;
volatile unsigned int *_wiringPiClk ;
volatile unsigned int *_wiringPiPads ;
volatile unsigned int *_wiringPiTimer ;
volatile unsigned int *_wiringPiTimerIrqRaw ;
// Data for use with the boardId functions.
// The order of entries here to correspond with the PI_MODEL_X
// and PI_VERSION_X defines in wiringPi.h
// Only intended for the gpio command - use at your own risk!
// piGpioBase:
// The base address of the GPIO memory mapped hardware IO
#define GPIO_PERI_BASE_OLD 0x20000000
#define GPIO_PERI_BASE_NEW 0x3F000000
static volatile unsigned int piGpioBase = 0 ;
// Time for easy calculations
static uint64_t epochMilli, epochMicro ;
// Misc
static int wiringPiMode = WPI_MODE_UNINITIALISED ;
static volatile int pinPass = -1 ;
static pthread_mutex_t pinMutex ;
// Debugging & Return codes
int wiringPiDebug = FALSE ;
int wiringPiReturnCodes = FALSE ;
// Use /dev/gpiomem ?
int wiringPiTryGpioMem = FALSE ;
sunxi_gpio_info sunxi_gpio_info_t;
rk3328_soc_info rk3328_soc_info_t;
rk3399_soc_info rk3399_soc_info_t;
rk3588_soc_info rk3588_soc_info_t;
rk3566_soc_info rk3566_soc_info_t;
// sysFds:
// Map a file descriptor from the /sys/class/gpio/gpioX/value
static int sysFds[384] =
{
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1-1,-1,-1,-1
};
// ISR Data
static void (*isrFunctions [64])(void) ;
// Doing it the Arduino way with lookup tables...
// Yes, it's probably more innefficient than all the bit-twidling, but it
// does tend to make it all a bit clearer. At least to me!
// pinToGpio:
// Take a Wiring pin (0 through X) and re-map it to the GPIO pin
// Cope for 3 different board revisions here.
static int OrangePiModel;
static int *pinToGpio ;
int pinToGpio_3[64] =
{
122, 121,
118, 354, 355,
120, 114, 119, 362, 111, 112,
229, 230, 117, 228, 227, 360,
// Padding:
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 31
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 63
};
int pinToGpio_LITE_2[64] =
{
230, 229,
228, 117, 118,
120, 73, 119, 122, 72, 71,
66, 67, 121, 64, 69, 227,
// Padding:
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 63
};
int pinToGpio_ZERO[64] =
{
12, 11, 6, 198, 199, 1, 7, 0, // From the Original Wiki - GPIO 0 through 7: wpi 0 - 7
3, 19, // I2C - SDA0, SCL0 wpi 8 - 9
18, 15, // SPI - CE1, CE0 wpi 10 - 11
16, 2, 14, // SPI - MOSI, MISO, SCLK wpi 12 - 14
13, 10, // UART - Tx, Rx wpi 15 - 16
-1, -1, -1, -1, // Rev 2: New GPIOs 8 though 11 wpi 17 - 20
-1, -1, -1, -1, -1, // B+ wpi 21, 22, 23, 24, 25
-1, -1, -1, -1, // B+ wpi 26, 27, 28, 29
-1, 1, // B+ wpi 30, 31
// Padding:
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 63
};
int pinToGpio_H3[64] =
{
12, 11, 6, 13, 14, 1, 110, 0, // From the Original Wiki - GPIO 0 through 7: wpi 0 - 7
3, 68, // I2C - SDA0, SCL0 wpi 8 - 9
71, 64, // SPI - CE1, CE0 wpi 10 - 11
65, 2, 66, // SPI - MOSI, MISO, SCLK wpi 12 - 14
67, 21, // UART - Tx, Rx wpi 15 - 16
19, 18, 7, 8, // Rev 2: New GPIOs 8 though 11 wpi 17 - 20
200, 9, 10, 201, 20, // B+ wpi 21, 22, 23, 24, 25
198, 199, // wpi 26, 27
-1, -1, //PA4, PA5(PWM0) wpi 28, 29
-1, -1, // B+ wpi 30, 31
// Padding:
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 63
};
int pinToGpio_ZERO_PLUS_2[64] =
{
12, 11, 6, 0, 1, 352, 107, 353, 3, // From the Original Wiki - GPIO 0 through 7: wpi 0 - 7
19, 18, // I2C - SDA0, SCL0 wpi 8 - 9
15, 16, // SPI - CE1, CE0 wpi 10 - 11
2, 14, 13, // SPI - MOSI, MISO, SCLK wpi 12 - 14
110, -1, // UART - Tx, Rx wpi 15 - 16
-1, -1, -1, -1, // Rev 2: New GPIOs 8 though 11 wpi 17 - 20
-1, -1, -1, -1, -1, // B+ wpi 21, 22, 23, 24, 25
-1, -1, // wpi 26, 27
-1, -1, //PA4, PA5(PWM0) wpi 28, 29
// Padding:
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 63
};
int pinToGpio_WIN[64] =
{
227, 226, // 0, 1
362, 354, // 2, 3
355, 229, // 4 5
100, 228, // 6, 7
231, 361, // 8, 9
68, 98, //10,11
99, 230, //12,13
97, 96, //14,15
102, 143, //16,17
142, 36, //18,19
37, 34, //20,21
38, 39, //22,23
35, 101, //24,25
32, 33, //26,27
-1, -1, //28,29
-1, -1, //30,31
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,// ... 63
};
int pinToGpio_PRIME[64] =
{
12, 11, // 0, 1
6, 69, // 2, 3
70, 1, // 4 5
110, 0, // 6, 7
3, 68, // 8, 9
71, 15, // 10,11
16, 2, // 12,13
14, 13, // 14,15
72, 19, // 16,17
18, 7, // 18,19
8, 73, // 20,21
9, 10, // 22,23
74,107, // 24,25
75, 76, // 26,27
-1, -1, // 28,29
-1, -1, // 30,31
// Padding:
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 63
};
int pinToGpio_PC_2[64] =
{
12, 11, // 0, 1
6, 69, // 2, 3
70, 1, // 4 5
110,0, // 6, 7
3, 68, // 8, 9
71, 15, //10,11
16, 2, //12,13
14, 13, //14,15
21, 19, //16,17
18, 7, //18,19
8, 200, //20,21
9, 10, //22,23
201,107, //24,25
198, 199, //26,27
-1, -1, //28, 29
-1, -1, //30,31
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,// ... 63
};
int pinToGpio_ZERO_PLUS[64] =
{
12, 11, 6, 198, 199, 1, 7, 0, 3, // From the Original Wiki - GPIO 0 through 7: wpi 0 - 7
19, 18, // I2C - SDA0, SCL0 wpi 8 - 9
15, 16, // SPI - CE1, CE0 wpi 10 - 11
2, 14, 13, // SPI - MOSI, MISO, SCLK wpi 12 - 14
10, -1, // UART - Tx, Rx wpi 15 - 16
-1, -1, -1, -1, // Rev 2: New GPIOs 8 though 11 wpi 17 - 20
-1, -1, -1, -1, -1, // B+ wpi 21, 22, 23, 24, 25
-1, -1, // wpi 26, 27
-1, -1, //PA4, PA5(PWM0) wpi 28, 29
// Padding:
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 63
};
int pinToGpio_ZERO_2[64] =
{
229, 228, 73, 226, 227, 70, 75,
69, 72, 79, 78, 231, 232, 71,
230, 233, 74, 65, 272, 262, 234,
// Padding:
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 31
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 63
};
int pinToGpio_ZERO_2_W[64] =
{
264, 263, // 0, 1
269, 224, // 2, 3
225, 226, // 4 5
257, 227, // 6, 7
261, 270, // 8, 9
228, 231, //10,11
232, 262, //12,13
230, 229, //14,15
233, 266, //16,17
265, 256, //18,19
271, 267, //20,21
268, 258, //22,23
76, 272, //24,25
260, 259, //26,27
-1, -1, //28,29
-1, -1, //30,31
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 63
};
int pinToGpio_RK3399[64] =
{
43, 44, // 0, 1
64, 148, // 2, 3
147, 80, // 4 5
65, 81, // 6, 7
82, 66, // 8, 9
67, 39, //10,11
40, 83, //12,13
41, 42, //14,15
133, 154, //16,17
50, 68, //18,19
69, 76, //20,21
70, 71, //22,23
73, 72, //24,25
74, 75, //26,27
-1, -1, //28,29
-1, -1, //30,31
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,// ... 63
};
int pinToGpio_800[64] =
{
43, 44, //0,1
150, 39, //2,3
40, 148, //4,5
152, 147, //6,7
149, 64, //8,9
65, 74, //10,11
73, 153, //12,13
75, 76, //14,15
154, -1, //16,17
-1, -1, //18,19
-1, -1, //20,21
-1, -1, //22,23
-1, -1, //24,25
-1, -1, //26,27
-1, -1, //28,29
-1, -1, //30,31
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,// ... 63
};
int pinToGpio_4[64] =
{
64, 65, // 0, 1
150, 145, // 2, 3
144, 33, // 4 5
50, 35, // 6, 7
92, 54, // 8, 9
55, 40, //10,11
39, 56, //12,13
41, 42, //14,15
149, 64, //16,17
65, -1, //18,19
-1, -1, //20,21
-1, -1, //22,23
-1, -1, //24,25
-1, -1, //26,27
-1, -1, //28,29
-1, -1, //30,31
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,// ... 63
};
int pinToGpio_4_LTS[64] =
{
52, 53, // 0, 1
150, 145, // 2, 3
144, 33, // 4 5
50, 35, // 6, 7
92, 54, // 8, 9
55, 40, //10,11
39, 56, //12,13
41, 42, //14,15
149, 64, //16,17
65, -1, //18,19
-1, -1, //20,21
-1, -1, //22,23
-1, -1, //24,25
-1, -1, //26,27
-1, -1, //28,29
-1, -1, //30,31
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,// ... 63
};
int pinToGpio_5[64] =
{
47, 46, // 0, 1
54, 131, // 2, 3
132,138, // 4 5
29, 139, // 6, 7
28, 59, // 8, 9
58, 49, //10,11
48, 92, //12,13
50, 52, //14,15
35, -1, //16,17
-1, -1, //18,19
-1, -1, //20,21
-1, -1, //22,23
-1, -1, //24,25
-1, -1, //26,27
-1, -1, //28,29
-1, -1, //30,31
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,// ... 63
};
int pinToGpio_5B[64] =
{
47, 46, // 0, 1
54, 131, // 2, 3
132,138, // 4 5
29, 139, // 6, 7
28, 59, // 8, 9
58, 49, //10,11
48, 50, //12,13
52, 35, //14,15
-1, -1, //16,17
-1, -1, //18,19
-1, -1, //20,21
-1, -1, //22,23
-1, -1, //24,25
-1, -1, //26,27
-1, -1, //28,29
-1, -1, //30,31
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,// ... 63
};
int pinToGpio_5PLUS[64] =
{
16, 15, // 0, 1
62, 33, // 2, 3
32, 36, // 4 5
97, 39, // 6, 7
40, 109, // 8, 9
110, 42, //10,11
41, 34, //12,13
43, 44, //14,15
45, 47, //16,17
46, 63, //18,19
96, 35, //20,21
114, 98, //22,23
101,113, //24,25
100, 99, //26,27
-1, -1, //28,29
-1, -1, //30,31
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,// ... 63
};
int pinToGpio_900[64] =
{
34, 35, // 0, 1
39, 46, // 2, 3
47, 101, // 4 5
97, 96, // 6, 7
113,107, // 8, 9
62, 42, //10,11
41, 63, //12,13
43, 44, //14,15
45, 32, //16,17
33, 36, //18,19
40, 114, //20,21
106, 98, //22,23
110,109, //24,25
100, 99, //26,27
-1, -1, //28,29
-1, -1, //30,31
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,// ... 63
};
int pinToGpio_CM4[64] =
{
140,141, // 0, 1
147, 25, // 2, 3
24, 118, // 4 5
119,128, // 6, 7
130,131, // 8, 9
129,138, //10,11
136,132, //12,13
139,134, //14,15
135, 32, //16,17
33, 133, //18,19
124,144, //20,21
127,120, //22,23
125,123, //24,25
122,121, //26,27
-1, -1, //28,29
-1, -1, //30,31
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,// ... 63
};
int pinToGpio_R1_PLUS[64] =
{
89, 88, // 0, 1
100, 102, // 2, 3
112, 103, // 4 5
101, 66, // 6, 7
-1, -1, // 8, 9
-1, -1, //10,11
-1, -1, //12,13
-1, -1, //14,15
-1, -1, //16,17
-1, -1, //18,19
-1, -1, //20,21
-1, -1, //22,23
-1, -1, //24,25
-1, -1, //26,27
-1, -1, //28,29
-1, -1, //30,31
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,// ... 63
};
// physToGpio:
// Take a physical pin (1 through 26) and re-map it to the GPIO pin
// Cope for 2 different board revisions here.
// Also add in the P5 connector, so the P5 pins are 3,4,5,6, so 53,54,55,56
static int *physToGpio ;
int physToGpio_3[64] =
{
-1, // 0
-1, -1, // 1, 2
122, -1,
121, -1,
118, 354,
-1, 355,
120, 114,
119, -1,
362, 111,
-1, 112,
229, -1,
230, 117,
228, 227,
-1, 360, // 25, 26
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 42
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 58
-1, -1, -1, -1, -1, // ... 63
};
int physToGpio_LITE_2[64] =
{
-1, // 0
-1, -1, // 1, 2
230, -1,
229, -1,
228, 117,
-1, 118,
120, 73,
119, -1,
122, 72,
-1, 71,
66, -1,
67, 121,
64, 69,
-1, 227, // 25, 26
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 56
-1, -1, -1, -1, -1, -1, -1, // ... 63
};
int physToGpio_ZERO[64] =
{
-1, // 0
-1, -1, // 1, 2
12, -1,
11, -1,
6,198,
-1,199,
1, 7,
0, -1,
3, 19,
-1, 18,
15, -1,
16, 2,
14, 13,
-1, 10, // 25, 26
-1, -1, //27, 28
-1, -1, //29, 30
-1, -1, //31, 32
-1, -1, //33, 34
-1, -1, //35, 36
-1, -1, //37, 38
-1, -1, //39, 40
// Padding:
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 56
-1, -1, -1, -1, -1, -1, -1, // ... 63
};
int physToGpio_H3[64] =
{
-1, // 0
-1, -1, // 1, 2
12, -1,
11, -1,
6, 13,
-1, 14,
1, 110,
0, -1,
3, 68,
-1, 71,
64, -1,
65, 2,
66, 67,
-1, 21, // 25, 26
19, 18, //27, 28
7, -1, //29, 30
8, 200, //31, 32
9, -1, //33, 34
10, 201, //35, 36
20, 198, //37, 38
-1, 199, //39, 40
4, 5, //41, 42
// Padding:
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 56
-1, -1, -1, -1, -1, -1, -1, // ... 63
};
int physToGpio_ZERO_PLUS_2[64] =
{
-1, // 0
-1, -1, // 1, 2
12, -1,
11, -1,
6, 0,
-1, 1,
352, 107,
353, -1,
3, 19,
-1, 18,
15, -1,
16, 2,
14, 13,
-1, 110, // 25, 26
-1, -1, //27, 28
-1, -1, //29, 30
-1, -1, //31, 32
-1, -1, //33, 34
-1, -1, //35, 36
-1, -1, //37, 38
-1, -1, //39, 40
-1, -1, //41, 42
// Padding:
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 56
-1, -1, -1, -1, -1, -1, -1, // ... 63
};
int physToGpio_WIN[64] =
{
-1, // 0
-1, -1, // 1, 2
227, -1, // 3, 4
226, -1, // 5, 6
362, 354, // 7, 8
-1, 355, // 9, 10
229, 100, //11, 12
228, -1, //13, 14
231, 361, //15, 16
-1, 68, //17, 18
98, -1, //19, 20
99, 230, //21, 22
97, 96, //23, 24
-1, 102, //25, 26
143, 142, //27, 28
36, -1, //29, 30
37, 34, //31, 32
38, -1, //33, 34
39, 35, //35, 36
101, 32, //37, 38
-1, 33, //39, 40
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, //41-> 55
-1, -1, -1, -1, -1, -1, -1, -1 // 56-> 63
};
int physToGpio_PRIME[64] =//head num map to OrangePi
{
-1, // 0
-1, -1, // 1, 2
12, -1, // 3, 4
11, -1, // 5, 6
6, 69, // 7, 8
-1, 70, // 9, 10
1, 110, //11, 12
0, -1, //13, 14
3, 68, //15, 16
-1, 71, //17, 18
15, -1, //19, 20
16, 2, //21, 22
14, 13, //23, 24
-1, 72, //25, 26
19, 18, //27, 28
7, -1, //29, 30
8, 73, //31, 32
9, -1, //33, 34
10, 74, //35, 36
107, 75, //37, 38
-1, 76, //39, 40
// Padding:
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, //41-> 55
-1, -1, -1, -1, -1, -1, -1, -1 // 56-> 63
};
int physToGpio_PC_2[64] =//head num map to OrangePi
{
-1, // 0
-1, -1, // 1, 2
12, -1, // 3, 4
11, -1, // 5, 6
6, 69, // 7, 8
-1, 70, // 9, 10
1, 110, //11, 12
0, -1, //13, 14
3, 68, //15, 16
-1, 71, //17, 18
15, -1, //19, 20
16, 2, //21, 22
14, 13, //23, 24
-1, 21, //25, 26
19, 18, //27, 28
7, -1, //29, 30
8, 200, //31, 32
9, -1, //33, 34
10, 201, //35, 36
107, 198, //37, 38
-1, 199, //39, 40
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, //41-> 55
-1, -1, -1, -1, -1, -1, -1, -1 // 56-> 63
};
int physToGpio_ZERO_PLUS[64] =
{
-1, // 0
-1, -1, // 1, 2
12, -1,
11, -1,
6, 198,
-1, 199,
1, 7,
0, -1,
3, 19,
-1, 18,
15, -1,
16, 2,
14, 13,
-1, 10, // 25, 26
-1, -1, //27, 28
-1, -1, //29, 30
-1, -1, //31, 32
-1, -1, //33, 34
-1, -1, //35, 36
-1, -1, //37, 38
-1, -1, //39, 40
-1, -1, //41, 42
// Padding:
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 56
-1, -1, -1, -1, -1, -1, -1, // ... 63
};
int physToGpio_ZERO_2[64] =
{
-1, // 0
-1, -1, // 1, 2
229, -1,
228, -1,
73, 226,
-1, 227,
70, 75,
69, -1,
72, 79,
-1, 78,
231, -1,
232, 71,
230, 233,
-1, 74, // 25, 26
65, -1, // 27
272, -1, // 29
262, -1, // 31
234, -1, // 33
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 49
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 63
};
int physToGpio_ZERO_2_W[64] =
{
-1,
-1, -1,
264, -1,
263, -1,
269, 224,
-1, 225,
226, 257,
227, -1,
261, 270,
-1, 228,
231, -1,
232, 262,
230, 229,
-1, 233,
266, 265,
256, -1,
271, 267,
268, -1,
258, 76,
272, 260,
-1, 259,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 56
-1, -1, -1, -1, -1, -1, -1, // ... 63
};
int physToGpio_RK3399[64] =//head num map to OrangePi
{
-1, // 0
-1, -1, // 1, 2
43, -1, // 3, 4
44, -1, // 5, 6
64, 148, // 7, 8
-1, 147, // 9, 10
80, 65, // 11, 12
81, -1, // 13, 14
82, 66, // 15, 16
-1, 67, // 17, 18
39, -1, // 19, 20
40, 83, // 21, 22
41, 42, // 23, 24
-1, 133, // 25, 26
154, 50, // 27, 28
68, -1, // 29, 30
69, 76, // 31, 32
70, -1, // 33, 34
71, 73, // 35, 36
72, 74, // 37, 38
-1, 75, // 39, 40
// Padding:
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 56
-1, -1, -1, -1, -1, -1, -1, // ... 63
};
int physToGpio_800[64] =//head num map to OrangePi
{
-1, // 0
-1, -1, // 1, 2
43, -1, // 3, 4
44, -1, // 5, 6
150, 39, // 7, 8
-1, 40, // 9, 10
148, 152, // 11, 12
147, -1, // 13, 14
149, 64, // 15, 16
-1, 65, // 17, 18
74, -1, // 19, 20
73, 153, // 21, 22
75, 76, // 23, 24
-1, 154, // 25, 26
-1, -1, // 27, 28
-1, -1, // 29, 30
-1, -1, // 31, 32
-1, -1, // 33, 34
-1, -1, // 35, 36
-1, -1, // 37, 38
-1, 75, // 39, 40
// Padding:
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 56
-1, -1, -1, -1, -1, -1, -1, // ... 63
};
int physToGpio_4[64] =//head num map to OrangePi
{
-1, // 0
-1, -1, // 1, 2
64, -1, // 3, 4
65, -1, // 5, 6
150, 145, // 7, 8
-1, 144, // 9, 10
33, 50, // 11, 12
35, -1, // 13, 14
92, 54, // 15, 16
-1, 55, // 17, 18
40, -1, // 19, 20
39, 56, // 21, 22
41, 42, // 23, 24
-1, 149, // 25, 26
64, 65, // 27, 28
-1, -1, // 29, 30
-1, 76, // 31, 32
-1, -1, // 33, 34
-1, 73, // 35, 36
-1, 74, // 37, 38
-1, 75, // 39, 40
// Padding:
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 56
-1, -1, -1, -1, -1, -1, -1, // ... 63
};
int physToGpio_4_LTS[64] =//head num map to OrangePi
{
-1, // 0
-1, -1, // 1, 2
64, -1, // 3, 4
65, -1, // 5, 6
150, 145, // 7, 8
-1, 144, // 9, 10
33, 50, // 11, 12
35, -1, // 13, 14
92, 54, // 15, 16
-1, 55, // 17, 18
40, -1, // 19, 20
39, 56, // 21, 22
41, 42, // 23, 24
-1, 149, // 25, 26
-1, -1, // 27, 28
-1, -1, // 29, 30
-1, -1, // 31, 32
-1, -1, // 33, 34
-1, -1, // 35, 36
-1, -1, // 37, 38
-1, -1, // 39, 40
//Padding:
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 56
-1, -1, -1, -1, -1, -1, -1, // ... 63
};
int physToGpio_5[64] =
{
-1, // 0
-1, -1, // 1, 2
47, -1, // 3, 4
46, -1, // 5, 6
54, 131, // 7, 8
-1, 132, // 9, 10
138, 29, // 11, 12
139, -1, // 13, 14
28, 59, // 15, 16
-1, 58, // 17, 18
49, -1, // 19, 20
48, 92, // 21, 22
50, 52, // 23, 24
-1, 35, // 25, 26
-1, -1, // 27, 28
-1, -1, // 29, 30
-1, -1, // 31, 32
-1, -1, // 33, 34
-1, -1, // 35, 36
-1, -1, // 37, 38
-1, -1, // 39, 40
//Padding:
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 56
-1, -1, -1, -1, -1, -1, -1, // ... 63
};
int physToGpio_5B[64] =
{
-1, // 0
-1, -1, // 1, 2
47, -1, // 3, 4
46, -1, // 5, 6
54, 131, // 7, 8
-1, 132, // 9, 10
138, 29, // 11, 12
139, -1, // 13, 14
28, 59, // 15, 16
-1, 58, // 17, 18
49, -1, // 19, 20
48, -1, // 21, 22
50, 52, // 23, 24
-1, 35, // 25, 26
-1, -1, // 27, 28
-1, -1, // 29, 30
-1, -1, // 31, 32
-1, -1, // 33, 34
-1, -1, // 35, 36
-1, -1, // 37, 38
-1, -1, // 39, 40
//Padding:
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 56
-1, -1, -1, -1, -1, -1, -1, // ... 63
};
int physToGpio_5PLUS[64] =
{
-1, // 0
-1, -1, // 1, 2
16, -1, // 3, 4
15, -1, // 5, 6
62, 33, // 7, 8
-1, 32, // 9, 10
36, 97, // 11, 12
39, -1, // 13, 14
40, 109, // 15, 16
-1, 110, // 17, 18
42, -1, // 19, 20
41, 34, // 21, 22
43, 44, // 23, 24
-1, 45, // 25, 26
47, 46, // 27, 28
63, -1, // 29, 30
96, 35, // 31, 32
114, -1, // 33, 34
98, 101, // 35, 36
113,100, // 37, 38
-1, 99, // 39, 40
//Padding:
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 56
-1, -1, -1, -1, -1, -1, -1, // ... 63
};
int physToGpio_900[64] =
{
-1, // 0
-1, -1, // 1, 2
34, -1, // 3, 4
35, -1, // 5, 6
39, 46, // 7, 8
-1, 47, // 9, 10
101, 97, // 11, 12
96, -1, // 13, 14
113, 107, // 15, 16
-1, 62, // 17, 18
42, -1, // 19, 20
41, 63, // 21, 22
43, 44, // 23, 24
-1, 45, // 25, 26
32, 33, // 27, 28
36, -1, // 29, 30
40, 114, // 31, 32
106, -1, // 33, 34
98, 110, // 35, 36
109,100, // 37, 38
-1, 99, // 39, 40
//Padding:
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 56
-1, -1, -1, -1, -1, -1, -1, // ... 63
};
int physToGpio_CM4[64] =
{
-1, // 0
-1, -1, // 1, 2
140, -1, // 3, 4
141, -1, // 5, 6
147, 25, // 7, 8
-1, 24, // 9, 10
118,119, // 11, 12
128, -1, // 13, 14
130,131, // 15, 16
-1, 129, // 17, 18
138, -1, // 19, 20
136,132, // 21, 22
139,134, // 23, 24
-1, 135, // 25, 26
32, 33, // 27, 28
133, -1, // 29, 30
124,144, // 31, 32
127, -1, // 33, 34
120,125, // 35, 36
123,122, // 37, 38
-1, 121, // 39, 40
//Padding:
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 56
-1, -1, -1, -1, -1, -1, -1, // ... 63
};
int physToGpio_R1_PLUS[64] =//head num map to OrangePi
{
-1, // 0
-1, -1, // 1, 2
89, 88, // 3, 4
100, 102, // 5, 6
-1, -1, // 7, 8
-1, 112, // 9, 10
103,101, // 11, 12
66, -1, // 13, 14
-1, -1, // 15, 16
-1, -1, // 17, 18
-1, -1, // 19, 20
-1, -1, // 21, 22
-1, -1, // 23, 24
-1, -1, // 25, 26
-1, -1, // 27, 28
-1, -1, // 29, 30
-1, -1, // 31, 32
-1, -1, // 33, 34
-1, -1, // 35, 36
-1, -1, // 37, 38
-1, -1, // 39, 40
// Padding:
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 56
-1, -1, -1, -1, -1, -1, -1, // ... 63
};
// gpioToGPFSEL:
// Map a BCM_GPIO pin to it's Function Selection
// control port. (GPFSEL 0-5)
// Groups of 10 - 3 bits per Function - 30 bits per port
static uint8_t gpioToGPFSEL [] =
{
0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,
4,4,4,4,4,4,4,4,4,4,
5,5,5,5,5,5,5,5,5,5,
} ;
// gpioToShift
// Define the shift up for the 3 bits per pin in each GPFSEL port
static uint8_t gpioToShift [] =
{
0,3,6,9,12,15,18,21,24,27,
0,3,6,9,12,15,18,21,24,27,
0,3,6,9,12,15,18,21,24,27,
0,3,6,9,12,15,18,21,24,27,
0,3,6,9,12,15,18,21,24,27,
0,3,6,9,12,15,18,21,24,27,
} ;
// gpioToGPSET:
// (Word) offset to the GPIO Set registers for each GPIO pin
static uint8_t gpioToGPSET [] =
{
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
} ;
// gpioToGPCLR:
// (Word) offset to the GPIO Clear registers for each GPIO pin
static uint8_t gpioToGPCLR [] =
{
10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
} ;
// gpioToGPLEV:
// (Word) offset to the GPIO Input level registers for each GPIO pin
static uint8_t gpioToGPLEV [] =
{
13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
} ;
#ifdef notYetReady
// gpioToEDS
// (Word) offset to the Event Detect Status
static uint8_t gpioToEDS [] =
{
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
} ;
// gpioToREN
// (Word) offset to the Rising edge ENable register
static uint8_t gpioToREN [] =
{
19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
} ;
// gpioToFEN
// (Word) offset to the Falling edgde ENable register
static uint8_t gpioToFEN [] =
{
22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
} ;
#endif
// GPPUD:
// GPIO Pin pull up/down register
#define GPPUD 37
// gpioToPUDCLK
// (Word) offset to the Pull Up Down Clock regsiter
static uint8_t gpioToPUDCLK [] =
{
38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,
39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
} ;
// gpioToPwmALT
// the ALT value to put a GPIO pin into PWM mode
static uint8_t gpioToPwmALT [] =
{
0, 0, 0, 0, 0, 0, 0, 0, // 0 -> 7
0, 0, 0, 0, FSEL_ALT0, FSEL_ALT0, 0, 0, // 8 -> 15
0, 0, FSEL_ALT5, FSEL_ALT5, 0, 0, 0, 0, // 16 -> 23
0, 0, 0, 0, 0, 0, 0, 0, // 24 -> 31
0, 0, 0, 0, 0, 0, 0, 0, // 32 -> 39
FSEL_ALT0, FSEL_ALT0, 0, 0, 0, FSEL_ALT0, 0, 0, // 40 -> 47
0, 0, 0, 0, 0, 0, 0, 0, // 48 -> 55
0, 0, 0, 0, 0, 0, 0, 0, // 56 -> 63
} ;
// gpioToPwmPort
// The port value to put a GPIO pin into PWM mode
/*static uint8_t gpioToPwmPort [] =
{
0, 0, 0, 0, 0, 0, 0, 0, // 0 -> 7
0, 0, 0, 0, PWM0_DATA, PWM1_DATA, 0, 0, // 8 -> 15
0, 0, PWM0_DATA, PWM1_DATA, 0, 0, 0, 0, // 16 -> 23
0, 0, 0, 0, 0, 0, 0, 0, // 24 -> 31
0, 0, 0, 0, 0, 0, 0, 0, // 32 -> 39
PWM0_DATA, PWM1_DATA, 0, 0, 0, PWM1_DATA, 0, 0, // 40 -> 47
0, 0, 0, 0, 0, 0, 0, 0, // 48 -> 55
0, 0, 0, 0, 0, 0, 0, 0, // 56 -> 63
} ;*/
// gpioToGpClkALT:
// ALT value to put a GPIO pin into GP Clock mode.
// On the Pi we can really only use BCM_GPIO_4 and BCM_GPIO_21
// for clocks 0 and 1 respectively, however I'll include the full
// list for completeness - maybe one day...
#define GPIO_CLOCK_SOURCE 1
// gpioToGpClkALT0:
static uint8_t gpioToGpClkALT0 [] =
{
0, 0, 0, 0, FSEL_ALT0, FSEL_ALT0, FSEL_ALT0, 0, // 0 -> 7
0, 0, 0, 0, 0, 0, 0, 0, // 8 -> 15
0, 0, 0, 0, FSEL_ALT5, FSEL_ALT5, 0, 0, // 16 -> 23
0, 0, 0, 0, 0, 0, 0, 0, // 24 -> 31
FSEL_ALT0, 0, FSEL_ALT0, 0, 0, 0, 0, 0, // 32 -> 39
0, 0, FSEL_ALT0, FSEL_ALT0, FSEL_ALT0, 0, 0, 0, // 40 -> 47
0, 0, 0, 0, 0, 0, 0, 0, // 48 -> 55
0, 0, 0, 0, 0, 0, 0, 0, // 56 -> 63
} ;
// gpioToClk:
// (word) Offsets to the clock Control and Divisor register
static uint8_t gpioToClkCon [] =
{
-1, -1, -1, -1, 28, 30, 32, -1, // 0 -> 7
-1, -1, -1, -1, -1, -1, -1, -1, // 8 -> 15
-1, -1, -1, -1, 28, 30, -1, -1, // 16 -> 23
-1, -1, -1, -1, -1, -1, -1, -1, // 24 -> 31
28, -1, 28, -1, -1, -1, -1, -1, // 32 -> 39
-1, -1, 28, 30, 28, -1, -1, -1, // 40 -> 47
-1, -1, -1, -1, -1, -1, -1, -1, // 48 -> 55
-1, -1, -1, -1, -1, -1, -1, -1, // 56 -> 63
} ;
static uint8_t gpioToClkDiv [] =
{
-1, -1, -1, -1, 29, 31, 33, -1, // 0 -> 7
-1, -1, -1, -1, -1, -1, -1, -1, // 8 -> 15
-1, -1, -1, -1, 29, 31, -1, -1, // 16 -> 23
-1, -1, -1, -1, -1, -1, -1, -1, // 24 -> 31
29, -1, 29, -1, -1, -1, -1, -1, // 32 -> 39
-1, -1, 29, 31, 29, -1, -1, -1, // 40 -> 47
-1, -1, -1, -1, -1, -1, -1, -1, // 48 -> 55
-1, -1, -1, -1, -1, -1, -1, -1, // 56 -> 63
} ;
/*
* Functions
*********************************************************************************
*/
/*
* wiringPiFailure:
* Fail. Or not.
*********************************************************************************
*/
int wiringPiFailure (int fatal, const char *message, ...)
{
va_list argp ;
char buffer [1024] ;
if (!fatal && wiringPiReturnCodes)
return -1 ;
va_start (argp, message) ;
vsnprintf (buffer, 1023, message, argp) ;
va_end (argp) ;
fprintf (stderr, "%s", buffer) ;
exit (EXIT_FAILURE) ;
return 0 ;
}
/*
* setupCheck
* Another sanity check because some users forget to call the setup
* function. Mosty because they need feeding C drip by drip )-:
*********************************************************************************
*/
static void setupCheck (const char *fName)
{
if (!wiringPiSetuped)
{
fprintf (stderr, "%s: You have not called one of the wiringPiSetup\n"
" functions, so I'm aborting your program before it crashes anyway.\n", fName) ;
exit (EXIT_FAILURE) ;
}
}
/*
* gpioMemCheck:
* See if we're using the /dev/gpiomem interface, if-so then some operations
* can't be done and will crash the Pi.
*********************************************************************************
*/
static void usingGpioMemCheck (const char *what)
{
if (usingGpioMem)
{
fprintf (stderr, "%s: Unable to do this when using /dev/gpiomem. Try sudo?\n", what) ;
exit (EXIT_FAILURE) ;
}
}
/*
* piGpioLayout:
* Return a number representing the hardware revision of the board.
* This is not strictly the board revision but is used to check the
* layout of the GPIO connector - and there are 2 types that we are
* really interested in here. The very earliest Pi's and the
* ones that came after that which switched some pins ....
*
* Revision 1 really means the early Model A and B's.
* Revision 2 is everything else - it covers the B, B+ and CM.
* ... and the Pi 2 - which is a B+ ++ ...
* ... and the Pi 0 - which is an A+ ...
*
* The main difference between the revision 1 and 2 system that I use here
* is the mapping of the GPIO pins. From revision 2, the Pi Foundation changed
* 3 GPIO pins on the (original) 26-way header - BCM_GPIO 22 was dropped and
* replaced with 27, and 0 + 1 - I2C bus 0 was changed to 2 + 3; I2C bus 1.
*
* Additionally, here we set the piModel2 flag too. This is again, nothing to
* do with the actual model, but the major version numbers - the GPIO base
* hardware address changed at model 2 and above (not the Zero though)
*
*********************************************************************************
*/
void piGpioLayoutOops (const char *why)
{
fprintf (stderr, "Oops: Unable to determine board revision from /etc/orangepi-release or /etc/armbian-release.\n") ;
fprintf (stderr, " -> %s\n", why) ;
fprintf (stderr, " -> You'd best google the error to find out why.\n") ;
exit (EXIT_FAILURE) ;
}
void piBoardId (int * model)
{
FILE *cpuFd ;
char line [40] ;
char *c;
char revision[40];
unsigned int i = 0;
if ((cpuFd = fopen ("/etc/orangepi-release", "r")) == NULL)
if ((cpuFd = fopen ("/etc/armbian-release", "r")) == NULL)
piGpioLayoutOops ("Unable to open /etc/orangepi-release or /etc/armbian-release.");
while (fgets (line, 40, cpuFd) != NULL)
if (strncmp (line, "BOARD=", 6) == 0)
break ;
fclose (cpuFd) ;
if (strncmp (line, "BOARD=", 6) != 0)
piGpioLayoutOops ("No \"Revision\" line") ;
if (wiringPiDebug)
printf ("piBoardId: Revision string: %s\n", line) ;
// Chomp trailing CR/NL
for (c = &line [strlen (line) - 1] ; (*c == '\n') || (*c == '\r') ; --c)
*c = 0 ;
// Need to work out if it's using the new or old encoding scheme:
// Scan to the first character of the revision number
for (c = line ; *c ; ++c)
if (*c == '=')
break ;
if (*c != '=')
piGpioLayoutOops ("Revision line (no equal)");
c++;
for (i = 0; *c ; ++c)
revision[i++] = *c;
revision[i] = '.';
if (wiringPiDebug)
printf ("piBoardId: Board string: %s\n", revision) ;
/**/ if (strncmp(revision, "orangepi3.", 10) == 0) { *model = PI_MODEL_3; }
else if (strncmp(revision, "orangepi3-lts.", 14) == 0) { *model = PI_MODEL_3; }
else if (strncmp(revision, "orangepioneplus.", 16) == 0) { *model = PI_MODEL_LTIE_2; }
else if (strncmp(revision, "orangepilite2.", 14) == 0) { *model = PI_MODEL_LTIE_2; }
else if (strncmp(revision, "orangepizero.", 13) == 0) { *model = PI_MODEL_ZERO; }
else if (strncmp(revision, "orangepizerolts.", 16) == 0) { *model = PI_MODEL_ZERO; }
else if (strncmp(revision, "orangepizero-lts.", 17) == 0) { *model = PI_MODEL_ZERO; }
else if (strncmp(revision, "orangepir1.", 11) == 0) { *model = PI_MODEL_ZERO; }
else if (strncmp(revision, "orangepi-r1.", 12) == 0) { *model = PI_MODEL_ZERO; }
else if (strncmp(revision, "orangepipc.", 11) == 0) { *model = PI_MODEL_H3; }
else if (strncmp(revision, "orangepipcplus.", 15) == 0) { *model = PI_MODEL_H3; }
else if (strncmp(revision, "orangepione.", 12) == 0) { *model = PI_MODEL_H3; }
else if (strncmp(revision, "orangepilite.", 13) == 0) { *model = PI_MODEL_H3; }
else if (strncmp(revision, "orangepiplus.", 13) == 0) { *model = PI_MODEL_H3; }
else if (strncmp(revision, "orangepiplue2e.", 15) == 0) { *model = PI_MODEL_H3; }
else if (strncmp(revision, "orangepizeroplus2h3.", 20) == 0) { *model = PI_MODEL_ZERO_PLUS_2; }
else if (strncmp(revision, "orangepizeroplus2-h3.", 21) == 0) { *model = PI_MODEL_ZERO_PLUS_2; }
else if (strncmp(revision, "orangepiwin.", 12) == 0) { *model = PI_MODEL_WIN; }
else if (strncmp(revision, "orangepiwinplus.", 16) == 0) { *model = PI_MODEL_WIN; }
else if (strncmp(revision, "orangepiprime.", 14) == 0) { *model = PI_MODEL_PRIME; }
else if (strncmp(revision, "orangepipc2.", 12) == 0) { *model = PI_MODEL_PC_2; }
else if (strncmp(revision, "orangepizeroplus.", 17) == 0) { *model = PI_MODEL_ZERO_PLUS; }
else if (strncmp(revision, "orangepizeroplus2h5.", 20) == 0) { *model = PI_MODEL_ZERO_PLUS_2; }
else if (strncmp(revision, "orangepizeroplus2-h5.", 21) == 0) { *model = PI_MODEL_ZERO_PLUS_2; }
else if (strncmp(revision, "orangepizero2.", 14) == 0) { *model = PI_MODEL_ZERO_2; }
else if (strncmp(revision, "orangepizero2w.", 14) == 0) { *model = PI_MODEL_ZERO_2_W; }
else if (strncmp(revision, "orangepizero3.", 14) == 0) { *model = PI_MODEL_ZERO_2; }
else if (strncmp(revision, "orangepirk3399.", 15) == 0) { *model = PI_MODEL_RK3399; }
else if (strncmp(revision, "orangepi-rk3399.", 16) == 0) { *model = PI_MODEL_RK3399; }
else if (strncmp(revision, "orangepi800.", 12) == 0) { *model = PI_MODEL_800; }
else if (strncmp(revision, "orangepi4.", 10) == 0) { *model = PI_MODEL_4; }
else if (strncmp(revision, "orangepi4-lts.", 14) == 0) { *model = PI_MODEL_4_LTS; }
else if (strncmp(revision, "orangepir1plus.", 15) == 0) { *model = PI_MODEL_R1_PLUS; }
else if (strncmp(revision, "orangepi-r1plus.", 16) == 0) { *model = PI_MODEL_R1_PLUS; }
else if (strncmp(revision, "orangepir1plus-lts.", 18) == 0) { *model = PI_MODEL_R1_PLUS; }
else if (strncmp(revision, "orangepi-r1plus-lts.", 20) == 0) { *model = PI_MODEL_R1_PLUS; }
else if (strncmp(revision, "orangepi5.", 10) == 0) { *model = PI_MODEL_5; }
else if (strncmp(revision, "orangepi5b.", 11) == 0) { *model = PI_MODEL_5B; }
else if (strncmp(revision, "orangepi5plus.", 14) == 0) { *model = PI_MODEL_5_PLUS; }
else if (strncmp(revision, "orangepi900.", 12) == 0) { *model = PI_MODEL_900; }
else if (strncmp(revision, "orangepicm4.", 12) == 0) { *model = PI_MODEL_CM4; }
else if (strncmp(revision, "orangepi3b.", 11) == 0) { *model = PI_MODEL_3B; }
if (wiringPiDebug)
printf("piBoardId: model = %d\n", *model);
}
/*
* wpiPinToGpio:
* Translate a wiringPi Pin number to native GPIO pin number.
* Provided for external support.
*********************************************************************************
*/
int wpiPinToGpio (int wpiPin)
{
return pinToGpio [wpiPin & 63] ;
}
/*
* physPinToGpio:
* Translate a physical Pin number to native GPIO pin number.
* Provided for external support.
*********************************************************************************
*/
int physPinToGpio (int physPin)
{
return physToGpio [physPin & 63] ;
}
/*
* setPadDrive:
* Set the PAD driver value
*********************************************************************************
*/
void setPadDrive (int group, int value)
{
uint32_t wrVal ;
if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO))
{
if ((group < 0) || (group > 2))
return ;
wrVal = BCM_PASSWORD | 0x18 | (value & 7) ;
*(pads + group + 11) = wrVal ;
if (wiringPiDebug)
{
printf ("setPadDrive: Group: %d, value: %d (%08X)\n", group, value, wrVal) ;
printf ("Read : %08X\n", *(pads + group + 11)) ;
}
}
}
/*
* getAlt:
* Returns the ALT bits for a given port. Only really of-use
* for the gpio readall command (I think)
*********************************************************************************
*/
int getAlt (int pin)
{
int alt;
pin &= 63;
if (wiringPiMode == WPI_MODE_PINS)
pin = pinToGpio [pin];
else if (wiringPiMode == WPI_MODE_PHYS)
pin = physToGpio [pin];
else if (wiringPiMode != WPI_MODE_GPIO)
return 0;
alt = OrangePi_get_gpio_mode(pin);
return alt;
}
/*
* pwmSetMode:
* Select the native "balanced" mode, or standard mark:space mode
*********************************************************************************
*/
void pwmSetMode(int mode) {
return;
}
/*
* pwmSetRange:
* Set the PWM range register. We set both range registers to the same
* value. If you want different in your own code, then write your own.
*********************************************************************************
*/
void pwmSetRange(unsigned int range) {
return;
}
/*
* pwmSetClock:
* Set/Change the PWM clock. Originally my code, but changed
* (for the better!) by Chris Hall, <chris@kchall.plus.com>
* after further study of the manual and testing with a 'scope
*********************************************************************************
*/
void pwmSetClock(int divisor) {
return;
}
/*
* gpioClockSet:
* Set the frequency on a GPIO clock pin
*********************************************************************************
*/
void gpioClockSet (int pin, int freq)
{
int divi, divr, divf ;
pin &= 63 ;
/**/ if (wiringPiMode == WPI_MODE_PINS)
pin = pinToGpio [pin] ;
else if (wiringPiMode == WPI_MODE_PHYS)
pin = physToGpio [pin] ;
else if (wiringPiMode != WPI_MODE_GPIO)
return ;
divi = 19200000 / freq ;
divr = 19200000 % freq ;
divf = (int)((double)divr * 4096.0 / 19200000.0) ;
if (divi > 4095)
divi = 4095 ;
*(clk + gpioToClkCon [pin]) = BCM_PASSWORD | GPIO_CLOCK_SOURCE ; // Stop GPIO Clock
while ((*(clk + gpioToClkCon [pin]) & 0x80) != 0) // ... and wait
;
*(clk + gpioToClkDiv [pin]) = BCM_PASSWORD | (divi << 12) | divf ; // Set dividers
*(clk + gpioToClkCon [pin]) = BCM_PASSWORD | 0x10 | GPIO_CLOCK_SOURCE ; // Start Clock
}
/*
* wiringPiFindNode:
* Locate our device node
*********************************************************************************
*/
struct wiringPiNodeStruct *wiringPiFindNode (int pin)
{
struct wiringPiNodeStruct *node = wiringPiNodes ;
while (node != NULL)
if ((pin >= node->pinBase) && (pin <= node->pinMax))
return node ;
else
node = node->next ;
return NULL ;
}
/*
* wiringPiNewNode:
* Create a new GPIO node into the wiringPi handling system
*********************************************************************************
*/
static void pinModeDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int mode) { return ; }
static void pullUpDnControlDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int pud) { return ; }
//static unsigned int digitalRead8Dummy (UNU struct wiringPiNodeStruct *node, UNU int UNU pin) { return 0 ; }
//static void digitalWrite8Dummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; }
static int digitalReadDummy (UNU struct wiringPiNodeStruct *node, UNU int UNU pin) { return LOW ; }
static void digitalWriteDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; }
static void pwmWriteDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; }
static int analogReadDummy (UNU struct wiringPiNodeStruct *node, UNU int pin) { return 0 ; }
static void analogWriteDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; }
struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins)
{
int pin ;
struct wiringPiNodeStruct *node ;
// Minimum pin base is 64
if (pinBase < 64)
(void)wiringPiFailure (WPI_FATAL, "wiringPiNewNode: pinBase of %d is < 64\n", pinBase) ;
// Check all pins in-case there is overlap:
for (pin = pinBase ; pin < (pinBase + numPins) ; ++pin)
if (wiringPiFindNode (pin) != NULL)
(void)wiringPiFailure (WPI_FATAL, "wiringPiNewNode: Pin %d overlaps with existing definition\n", pin) ;
node = (struct wiringPiNodeStruct *)calloc (sizeof (struct wiringPiNodeStruct), 1) ; // calloc zeros
if (node == NULL)
(void)wiringPiFailure (WPI_FATAL, "wiringPiNewNode: Unable to allocate memory: %s\n", strerror (errno)) ;
node->pinBase = pinBase ;
node->pinMax = pinBase + numPins - 1 ;
node->pinMode = pinModeDummy ;
node->pullUpDnControl = pullUpDnControlDummy ;
node->digitalRead = digitalReadDummy ;
//node->digitalRead8 = digitalRead8Dummy ;
node->digitalWrite = digitalWriteDummy ;
//node->digitalWrite8 = digitalWrite8Dummy ;
node->pwmWrite = pwmWriteDummy ;
node->analogRead = analogReadDummy ;
node->analogWrite = analogWriteDummy ;
node->next = wiringPiNodes ;
wiringPiNodes = node ;
return node ;
}
#ifdef notYetReady
/*
* pinED01:
* pinED10:
* Enables edge-detect mode on a pin - from a 0 to a 1 or 1 to 0
* Pin must already be in input mode with appropriate pull up/downs set.
*********************************************************************************
*/
void pinEnableED01Pi (int pin)
{
pin = pinToGpio [pin & 63] ;
}
#endif
/*
*********************************************************************************
* Core Functions
*********************************************************************************
*/
/*
* pinModeAlt:
* This is an un-documented special to let you set any pin to any mode
*********************************************************************************
*/
void pinModeAlt (int pin, int mode)
{
int fSel, shift ;
setupCheck ("pinModeAlt") ;
/*
#ifdef CONFIG_ORANGEPI
#if !(defined CONFIG_ORANGEPI_RK3399 || defined CONFIG_ORANGEPI_4 || defined CONFIG_ORANGEPI_4_LTS || defined CONFIG_ORANGEPI_800 || defined CONFIG_ORANGEPI_R1PLUS || CONFIG_ORANGEPI_2G_IOT)
if(version == ORANGEPI) {
if (wiringPiDebug)
printf("PinModeAlt: pin:%d,mode:%d\n", pin, mode);
if ((pin & PI_GPIO_MASK) == 0) {
if (wiringPiMode == WPI_MODE_PINS)
pin = pinToGpio[pin];
else if (wiringPiMode == WPI_MODE_PHYS)
pin = physToGpio[pin];
else if (wiringPiMode != WPI_MODE_GPIO)
return;
if (-1 == pin) {
printf("[%s:L%d] the pin:%d is invaild,please check it over!\n",
__func__, __LINE__, pin);
return;
}
if ( mode <= 1 || mode >= 8){
printf("[%s:L%d] the mode:%d is invaild,please check it over!\n",
__func__, __LINE__, mode);
return;
}
OrangePi_set_gpio_alt(pin, mode);
return;
} else {
return ;
}
}
#endif
#endif
*/
/*
if ((pin & PI_GPIO_MASK) == 0)
{
if (wiringPiMode == WPI_MODE_PINS)
pin = pinToGpio [pin] ;
else if (wiringPiMode == WPI_MODE_PHYS)
pin = physToGpio [pin] ;
else if (wiringPiMode != WPI_MODE_GPIO)
return ;
fSel = gpioToGPFSEL [pin] ;
shift = gpioToShift [pin] ;
*(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | ((mode & 0x7) << shift) ;
}
*/
}
/*
* pinMode:
* Sets the mode of a pin to be input, output or PWM output
*********************************************************************************
*/
void pinMode (int pin, int mode)
{
int fSel, shift, alt ;
struct wiringPiNodeStruct *node = wiringPiNodes ;
int origPin = pin ;
setupCheck ("pinMode") ;
if (wiringPiDebug)
printf("PinMode: pin:%d,mode:%d\n", pin, mode);
if ((pin & PI_GPIO_MASK) == 0)
{
if (wiringPiMode == WPI_MODE_PINS)
pin = pinToGpio[pin];
else if (wiringPiMode == WPI_MODE_PHYS)
pin = physToGpio[pin];
else if (wiringPiMode != WPI_MODE_GPIO)
return;
if (-1 == pin)
{
printf("[%s:L%d] the pin:%d is invaild,please check it over!\n",
__func__, __LINE__, pin);
return;
}
if (mode == INPUT) {
OrangePi_set_gpio_mode(pin, INPUT);
return;
}
else if (mode == OUTPUT)
{
OrangePi_set_gpio_mode(pin, OUTPUT);
return ;
}
else if (mode == PWM_OUTPUT)
{
if(pin != 5)
{
printf("the pin you choose doesn't support hardware PWM\n");
printf("you can select wiringPi pin %d for PWM pin\n", 42);
printf("or you can use it in softPwm mode\n");
return;
}
OrangePi_set_gpio_mode(pin, PWM_OUTPUT);
return;
}
else
return;
}
else
{
if ((node = wiringPiFindNode (pin)) != NULL)
node->pinMode(node, pin, mode);
return ;
}
}
/*
* pullUpDownCtrl:
* Control the internal pull-up/down resistors on a GPIO pin.
*********************************************************************************
*/
void pullUpDnControl (int pin, int pud)
{
struct wiringPiNodeStruct *node = wiringPiNodes ;
setupCheck ("pullUpDnControl") ;
if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin
{
/**/ if (wiringPiMode == WPI_MODE_PINS)
pin = pinToGpio [pin] ;
else if (wiringPiMode == WPI_MODE_PHYS)
pin = physToGpio [pin] ;
else if (wiringPiMode != WPI_MODE_GPIO)
return ;
if (pud == PUD_OFF) {
OrangePi_set_gpio_pullUpDnControl(pin, PUD_OFF);
}
else if (pud == PUD_UP){
OrangePi_set_gpio_pullUpDnControl(pin, PUD_UP);
}
else if (pud == PUD_DOWN){
OrangePi_set_gpio_pullUpDnControl(pin, PUD_DOWN);
}
}
else // Extension module
{
if ((node = wiringPiFindNode (pin)) != NULL)
node->pullUpDnControl (node, pin, pud) ;
return ;
}
}
/*
* digitalRead:
* Read the value of a given Pin, returning HIGH or LOW
*********************************************************************************
*/
int digitalRead (int pin)
{
char c ;
int ret;
struct wiringPiNodeStruct *node = wiringPiNodes ;
if ((pin & PI_GPIO_MASK) == 0)
{
if (wiringPiMode == WPI_MODE_GPIO_SYS) // Sys mode
{
if (sysFds [pin] == -1)
return LOW ;
ret = lseek(sysFds [pin], 0L, SEEK_SET) ;
ret = read(sysFds [pin], &c, 1);
if (ret < 0)
return -1;
return (c == '0') ? LOW : HIGH ;
}
else if (wiringPiMode == WPI_MODE_PINS)
pin = pinToGpio[pin];
else if (wiringPiMode == WPI_MODE_PHYS)
pin = physToGpio[pin];
else if (wiringPiMode != WPI_MODE_GPIO)
return -1;
if (pin == -1)
{
printf("[%s %d]Pin %d is invalid, please check it over!\n", __func__, __LINE__, pin);
return LOW;
}
return OrangePi_digitalRead(pin);
}
else
{
if ((node = wiringPiFindNode (pin)) == NULL)
return LOW ;
return node->digitalRead (node, pin) ;
}
}
/*
* digitalRead8:
* Read 8-bits (a byte) from given start pin.
*********************************************************************************
unsigned int digitalRead8 (int pin)
{
struct wiringPiNodeStruct *node = wiringPiNodes ;
if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin
return 0 ;
else
{
if ((node = wiringPiFindNode (pin)) == NULL)
return LOW ;
return node->digitalRead8 (node, pin) ;
}
}
*/
/*
* digitalWrite:
* Set an output bit
*********************************************************************************
*/
void digitalWrite (int pin, int value)
{
struct wiringPiNodeStruct *node = wiringPiNodes ;
int ret;
if ((pin & PI_GPIO_MASK) == 0)
{
if (wiringPiMode == WPI_MODE_GPIO_SYS)
{
if (sysFds [pin] != -1) {
if (value == LOW)
{
ret = write (sysFds [pin], "0\n", 2);
if (ret < 0)
return;
}
else
{
ret = write (sysFds [pin], "1\n", 2);
if (ret < 0)
return;
}
}
return ;
}
else if (wiringPiMode == WPI_MODE_PINS)
{
pin = pinToGpio[pin];
}
else if (wiringPiMode == WPI_MODE_PHYS)
pin = physToGpio[pin];
else
return;
if(-1 == pin)
{
printf("[%s:L%d] the pin:%d is invaild,please check it over!\n", __func__, __LINE__, pin);
printf("[%s:L%d] the mode is: %d, please check it over!\n", __func__, __LINE__, wiringPiMode);
return;
}
OrangePi_digitalWrite(pin, value);
}
else
{
if ((node = wiringPiFindNode(pin)) != NULL)
node->digitalWrite(node, pin, value);
}
return;
}
/*
* digitalWrite8:
* Set an output 8-bit byte on the device from the given pin number
*********************************************************************************
void digitalWrite8 (int pin, int value)
{
struct wiringPiNodeStruct *node = wiringPiNodes ;
if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin
return ;
else
{
if ((node = wiringPiFindNode (pin)) != NULL)
node->digitalWrite8 (node, pin, value) ;
}
}
*/
/*
* pwmWrite:
* Set an output PWM value
*********************************************************************************
*/
void pwmWrite(int pin, int value) {
return;
}
/*
* analogRead:
* Read the analog value of a given Pin.
* There is no on-board Pi analog hardware,
* so this needs to go to a new node.
*********************************************************************************
*/
int analogRead (int pin)
{
struct wiringPiNodeStruct *node = wiringPiNodes ;
if ((node = wiringPiFindNode (pin)) == NULL)
return 0 ;
else
return node->analogRead (node, pin) ;
}
/*
* analogWrite:
* Write the analog value to the given Pin.
* There is no on-board Pi analog hardware,
* so this needs to go to a new node.
*********************************************************************************
*/
void analogWrite (int pin, int value)
{
struct wiringPiNodeStruct *node = wiringPiNodes ;
if ((node = wiringPiFindNode (pin)) == NULL)
return ;
node->analogWrite (node, pin, value) ;
}
/*
* pwmToneWrite:
* Pi Specific.
* Output the given frequency on the Pi's PWM pin
*********************************************************************************
*/
void pwmToneWrite (int pin, int freq)
{
int range ;
setupCheck ("pwmToneWrite") ;
if (freq == 0)
pwmWrite (pin, 0) ; // Off
else
{
range = 600000 / freq ;
pwmSetRange (range) ;
pwmWrite (pin, freq / 2) ;
}
}
/*
* digitalWriteByte:
* digitalReadByte:
* Pi Specific
* Write an 8-bit byte to the first 8 GPIO pins - try to do it as
* fast as possible.
* However it still needs 2 operations to set the bits, so any external
* hardware must not rely on seeing a change as there will be a change
* to set the outputs bits to zero, then another change to set the 1's
* Reading is just bit fiddling.
* These are wiringPi pin numbers 0..7, or BCM_GPIO pin numbers
* 17, 18, 22, 23, 24, 24, 4 on a Pi v1 rev 0-3
* 17, 18, 27, 23, 24, 24, 4 on a Pi v1 rev 3 onwards or B+, 2, 3, zero
*********************************************************************************
*/
void digitalWriteByte (const int value)
{
int mask = 1 ;
int pin ;
for (pin = 0 ; pin < 8 ; ++pin) {
digitalWrite (pin, (value >> pin) & mask) ;
}
return ;
}
unsigned int digitalReadByte (void)
{
int pin, x ;
uint32_t data = 0 ;
for (pin = 7 ; pin >= 0 ; --pin){
x = digitalRead(pin);
data = (data << 1) | x ;
}
return data ;
}
/*
* digitalWriteByte2:
* digitalReadByte2:
* Pi Specific
* Write an 8-bit byte to the second set of 8 GPIO pins. This is marginally
* faster than the first lot as these are consecutive BCM_GPIO pin numbers.
* However they overlap with the original read/write bytes.
*********************************************************************************
*/
void digitalWriteByte2 (const int value)
{
register int mask = 1 ;
register int pin ;
/**/ if (wiringPiMode == WPI_MODE_GPIO_SYS)
{
for (pin = 20 ; pin < 28 ; ++pin)
{
digitalWrite (pin, value & mask) ;
mask <<= 1 ;
}
return ;
}
else
{
*(gpio + gpioToGPCLR [0]) = (~value & 0xFF) << 20 ; // 0x0FF00000; ILJ > CHANGE: Old causes glitch
*(gpio + gpioToGPSET [0]) = ( value & 0xFF) << 20 ;
}
}
unsigned int digitalReadByte2 (void)
{
int pin, x ;
uint32_t data = 0 ;
/**/ if (wiringPiMode == WPI_MODE_GPIO_SYS)
{
for (pin = 20 ; pin < 28 ; ++pin)
{
x = digitalRead (pin) ;
data = (data << 1) | x ;
}
}
else
data = ((*(gpio + gpioToGPLEV [0])) >> 20) & 0xFF ; // First bank for these pins
return data ;
}
/*
* waitForInterrupt:
* Pi Specific.
* Wait for Interrupt on a GPIO pin.
* This is actually done via the /sys/class/gpio interface regardless of
* the wiringPi access mode in-use. Maybe sometime it might get a better
* way for a bit more efficiency.
*********************************************************************************
*/
int waitForInterrupt (int pin, int mS)
{
int fd, x ;
uint8_t c ;
struct pollfd polls ;
int ret;
/**/ if (wiringPiMode == WPI_MODE_PINS)
pin = pinToGpio [pin] ;
else if (wiringPiMode == WPI_MODE_PHYS)
pin = physToGpio [pin] ;
if ((fd = sysFds [pin]) == -1)
return -2 ;
// Setup poll structure
polls.fd = fd ;
polls.events = POLLPRI | POLLERR ;
// Wait for it ...
x = poll (&polls, 1, mS) ;
// If no error, do a dummy read to clear the interrupt
// A one character read appars to be enough.
if (x > 0)
{
lseek (fd, 0, SEEK_SET) ; // Rewind
ret = read (fd, &c, 1) ; // Read & clear
if (ret < 0)
return -1;
}
return x ;
}
/*
* interruptHandler:
* This is a thread and gets started to wait for the interrupt we're
* hoping to catch. It will call the user-function when the interrupt
* fires.
*********************************************************************************
*/
static void *interruptHandler (UNU void *arg)
{
int myPin ;
(void)piHiPri (55) ; // Only effective if we run as root
myPin = pinPass ;
pinPass = -1 ;
for (;;)
if (waitForInterrupt (myPin, -1) > 0)
isrFunctions [myPin] () ;
return NULL ;
}
/*
* wiringPiISR:
* Pi Specific.
* Take the details and create an interrupt handler that will do a call-
* back to the user supplied function.
*********************************************************************************
*/
int wiringPiISR (int pin, int mode, void (*function)(void))
{
pthread_t threadId ;
const char *modeS ;
char fName [64] ;
char pinS [8] ;
pid_t pid ;
int count, i ;
char c ;
int bcmGpioPin ;
int ret;
if ((pin < 0) || (pin > 63))
return wiringPiFailure (WPI_FATAL, "wiringPiISR: pin must be 0-63 (%d)\n", pin) ;
/**/ if (wiringPiMode == WPI_MODE_UNINITIALISED)
return wiringPiFailure (WPI_FATAL, "wiringPiISR: wiringPi has not been initialised. Unable to continue.\n") ;
else if (wiringPiMode == WPI_MODE_PINS)
bcmGpioPin = pinToGpio [pin] ;
else if (wiringPiMode == WPI_MODE_PHYS)
bcmGpioPin = physToGpio [pin] ;
else
bcmGpioPin = pin ;
// Now export the pin and set the right edge
// We're going to use the gpio program to do this, so it assumes
// a full installation of wiringPi. It's a bit 'clunky', but it
// is a way that will work when we're running in "Sys" mode, as
// a non-root user. (without sudo)
if (mode != INT_EDGE_SETUP)
{
/**/ if (mode == INT_EDGE_FALLING)
modeS = "falling" ;
else if (mode == INT_EDGE_RISING)
modeS = "rising" ;
else
modeS = "both" ;
sprintf (pinS, "%d", pin) ;
if ((pid = fork ()) < 0) // Fail
return wiringPiFailure (WPI_FATAL, "wiringPiISR: fork failed: %s\n", strerror (errno)) ;
if (pid == 0) // Child, exec
{
/**/ if (access ("/usr/local/bin/gpio", X_OK) == 0)
{
execl ("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ;
return wiringPiFailure (WPI_FATAL, "wiringPiISR: execl failed: %s\n", strerror (errno)) ;
}
else if (access ("/usr/bin/gpio", X_OK) == 0)
{
execl ("/usr/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ;
return wiringPiFailure (WPI_FATAL, "wiringPiISR: execl failed: %s\n", strerror (errno)) ;
}
else
return wiringPiFailure (WPI_FATAL, "wiringPiISR: Can't find gpio program\n") ;
}
else // Parent, wait
wait (NULL) ;
}
// Now pre-open the /sys/class node - but it may already be open if
// we are in Sys mode...
if (sysFds [bcmGpioPin] == -1)
{
sprintf (fName, "/sys/class/gpio/gpio%d/value", bcmGpioPin) ;
if ((sysFds [bcmGpioPin] = open (fName, O_RDWR)) < 0)
return wiringPiFailure (WPI_FATAL, "wiringPiISR: unable to open %s: %s\n", fName, strerror (errno)) ;
}
// Clear any initial pending interrupt
ioctl (sysFds [bcmGpioPin], FIONREAD, &count) ;
for (i = 0 ; i < count ; ++i){
ret = read (sysFds [bcmGpioPin], &c, 1) ;
if (ret < 0)
return -1;
}
isrFunctions [pin] = function ;
pthread_mutex_lock (&pinMutex) ;
pinPass = pin ;
pthread_create (&threadId, NULL, interruptHandler, NULL) ;
while (pinPass != -1)
delay (1) ;
pthread_mutex_unlock (&pinMutex) ;
return 0 ;
}
/*
* initialiseEpoch:
* Initialise our start-of-time variable to be the current unix
* time in milliseconds and microseconds.
*********************************************************************************
*/
static void initialiseEpoch (void)
{
#ifdef OLD_WAY
struct timeval tv ;
gettimeofday (&tv, NULL) ;
epochMilli = (uint64_t)tv.tv_sec * (uint64_t)1000 + (uint64_t)(tv.tv_usec / 1000) ;
epochMicro = (uint64_t)tv.tv_sec * (uint64_t)1000000 + (uint64_t)(tv.tv_usec) ;
#else
struct timespec ts ;
clock_gettime (CLOCK_MONOTONIC_RAW, &ts) ;
epochMilli = (uint64_t)ts.tv_sec * (uint64_t)1000 + (uint64_t)(ts.tv_nsec / 1000000L) ;
epochMicro = (uint64_t)ts.tv_sec * (uint64_t)1000000 + (uint64_t)(ts.tv_nsec / 1000L) ;
#endif
}
/*
* delay:
* Wait for some number of milliseconds
*********************************************************************************
*/
void delay (unsigned int howLong)
{
struct timespec sleeper, dummy ;
sleeper.tv_sec = (time_t)(howLong / 1000) ;
sleeper.tv_nsec = (long)(howLong % 1000) * 1000000 ;
nanosleep (&sleeper, &dummy) ;
}
/*
* delayMicroseconds:
* This is somewhat intersting. It seems that on the Pi, a single call
* to nanosleep takes some 80 to 130 microseconds anyway, so while
* obeying the standards (may take longer), it's not always what we
* want!
*
* So what I'll do now is if the delay is less than 100uS we'll do it
* in a hard loop, watching a built-in counter on the ARM chip. This is
* somewhat sub-optimal in that it uses 100% CPU, something not an issue
* in a microcontroller, but under a multi-tasking, multi-user OS, it's
* wastefull, however we've no real choice )-:
*
* Plan B: It seems all might not be well with that plan, so changing it
* to use gettimeofday () and poll on that instead...
*********************************************************************************
*/
void delayMicrosecondsHard (unsigned int howLong)
{
struct timeval tNow, tLong, tEnd ;
gettimeofday (&tNow, NULL) ;
tLong.tv_sec = howLong / 1000000 ;
tLong.tv_usec = howLong % 1000000 ;
timeradd (&tNow, &tLong, &tEnd) ;
while (timercmp (&tNow, &tEnd, <))
gettimeofday (&tNow, NULL) ;
}
void delayMicroseconds (unsigned int howLong)
{
struct timespec sleeper ;
unsigned int uSecs = howLong % 1000000 ;
unsigned int wSecs = howLong / 1000000 ;
/**/ if (howLong == 0)
return ;
else if (howLong < 100)
delayMicrosecondsHard (howLong) ;
else
{
sleeper.tv_sec = wSecs ;
sleeper.tv_nsec = (long)(uSecs * 1000L) ;
nanosleep (&sleeper, NULL) ;
}
}
/*
* millis:
* Return a number of milliseconds as an unsigned int.
* Wraps at 49 days.
*********************************************************************************
*/
unsigned int millis (void)
{
uint64_t now ;
#ifdef OLD_WAY
struct timeval tv ;
gettimeofday (&tv, NULL) ;
now = (uint64_t)tv.tv_sec * (uint64_t)1000 + (uint64_t)(tv.tv_usec / 1000) ;
#else
struct timespec ts ;
clock_gettime (CLOCK_MONOTONIC_RAW, &ts) ;
now = (uint64_t)ts.tv_sec * (uint64_t)1000 + (uint64_t)(ts.tv_nsec / 1000000L) ;
#endif
return (uint32_t)(now - epochMilli) ;
}
/*
* micros:
* Return a number of microseconds as an unsigned int.
* Wraps after 71 minutes.
*********************************************************************************
*/
unsigned int micros (void)
{
uint64_t now ;
#ifdef OLD_WAY
struct timeval tv ;
gettimeofday (&tv, NULL) ;
now = (uint64_t)tv.tv_sec * (uint64_t)1000000 + (uint64_t)tv.tv_usec ;
#else
struct timespec ts ;
clock_gettime (CLOCK_MONOTONIC_RAW, &ts) ;
now = (uint64_t)ts.tv_sec * (uint64_t)1000000 + (uint64_t)(ts.tv_nsec / 1000) ;
#endif
return (uint32_t)(now - epochMicro) ;
}
/*
* wiringPiVersion:
* Return our current version number
*********************************************************************************
*/
void wiringPiVersion (int *major, int *minor)
{
*major = VERSION_MAJOR ;
*minor = VERSION_MINOR ;
}
void set_soc_info(void)
{
switch (OrangePiModel)
{
case PI_MODEL_3:
case PI_MODEL_LTIE_2:
case PI_MODEL_ZERO_2:
case PI_MODEL_ZERO_2_W:
sunxi_gpio_info_t.gpio_base_addr = H6_GPIO_BASE_ADDR;
sunxi_gpio_info_t.r_gpio_base_addr = H6_R_GPIO_BASE_ADDR;
sunxi_gpio_info_t.gpio_base_offset = 0x0;
sunxi_gpio_info_t.r_gpio_base_offset = 0x0;
break;
case PI_MODEL_ZERO:
case PI_MODEL_ZERO_PLUS_2:
case PI_MODEL_WIN:
case PI_MODEL_PRIME:
case PI_MODEL_PC_2:
case PI_MODEL_ZERO_PLUS:
case PI_MODEL_H3:
sunxi_gpio_info_t.gpio_base_addr = H3_GPIO_BASE_ADDR;
sunxi_gpio_info_t.r_gpio_base_addr = H3_R_GPIO_BASE_ADDR;
sunxi_gpio_info_t.gpio_base_offset = 0x800;
sunxi_gpio_info_t.r_gpio_base_offset = 0xc00;
break;
default:
break;
}
}
/*
* wiringPiSetup:
* Must be called once at the start of your program execution.
*
* Default setup: Initialises the system into wiringPi Pin mode and uses the
* memory mapped hardware directly.
*
* Changed now to revert to "gpio" mode if we're running on a Compute Module.
*********************************************************************************
*/
int wiringPiSetup (void)
{
int fd;
// It's actually a fatal error to call any of the wiringPiSetup routines more than once,
// (you run out of file handles!) but I'm fed-up with the useless twats who email
// me bleating that there is a bug in my code, so screw-em.
if (wiringPiSetuped)
return 0 ;
wiringPiSetuped = TRUE ;
if (getenv (ENV_DEBUG) != NULL)
wiringPiDebug = TRUE ;
if (getenv (ENV_CODES) != NULL)
wiringPiReturnCodes = TRUE ;
if (wiringPiDebug)
printf ("wiringPi: wiringPiSetup called\n") ;
piBoardId (&OrangePiModel) ;
wiringPiMode = WPI_MODE_PINS ;
switch (OrangePiModel)
{
case PI_MODEL_3:
pinToGpio = pinToGpio_3;
physToGpio = physToGpio_3;
ORANGEPI_PIN_MASK = ORANGEPI_PIN_MASK_3;
break;
case PI_MODEL_LTIE_2:
pinToGpio = pinToGpio_LITE_2;
physToGpio = physToGpio_LITE_2;
ORANGEPI_PIN_MASK = ORANGEPI_PIN_MASK_LITE_2;
break;
case PI_MODEL_ZERO:
pinToGpio = pinToGpio_ZERO;
physToGpio = physToGpio_ZERO;
ORANGEPI_PIN_MASK = ORANGEPI_PIN_MASK_ZERO;
break;
case PI_MODEL_ZERO_PLUS_2:
pinToGpio = pinToGpio_ZERO_PLUS_2;
physToGpio = physToGpio_ZERO_PLUS_2;
ORANGEPI_PIN_MASK = ORANGEPI_PIN_MASK_ZERO_PLUS_2;
break;
case PI_MODEL_WIN:
pinToGpio = pinToGpio_WIN;
physToGpio = physToGpio_WIN;
ORANGEPI_PIN_MASK = ORANGEPI_PIN_MASK_WIN;
break;
case PI_MODEL_PRIME:
pinToGpio = pinToGpio_PRIME;
physToGpio = physToGpio_PRIME;
ORANGEPI_PIN_MASK = ORANGEPI_PIN_MASK_PRIME;
break;
case PI_MODEL_PC_2:
pinToGpio = pinToGpio_PC_2;
physToGpio = physToGpio_PC_2;
ORANGEPI_PIN_MASK = ORANGEPI_PIN_MASK_PC_2;
break;
case PI_MODEL_ZERO_PLUS:
pinToGpio = pinToGpio_ZERO_PLUS;
physToGpio = physToGpio_ZERO_PLUS;
ORANGEPI_PIN_MASK = ORANGEPI_PIN_MASK_ZERO_PLUS;
break;
case PI_MODEL_ZERO_2:
pinToGpio = pinToGpio_ZERO_2;
physToGpio = physToGpio_ZERO_2;
ORANGEPI_PIN_MASK = ORANGEPI_PIN_MASK_ZERO_2;
break;
case PI_MODEL_ZERO_2_W:
pinToGpio = pinToGpio_ZERO_2_W;
physToGpio = physToGpio_ZERO_2_W;
ORANGEPI_PIN_MASK = ORANGEPI_PIN_MASK_ZERO_2_W;
break;
case PI_MODEL_800:
pinToGpio = pinToGpio_800;
physToGpio = physToGpio_800;
ORANGEPI_PIN_MASK = ORANGEPI_PIN_MASK_800;
break;
case PI_MODEL_4:
pinToGpio = pinToGpio_4;
physToGpio = physToGpio_4;
ORANGEPI_PIN_MASK = ORANGEPI_PIN_MASK_4;
break;
case PI_MODEL_4_LTS:
pinToGpio = pinToGpio_4_LTS;
physToGpio = physToGpio_4_LTS;
ORANGEPI_PIN_MASK = ORANGEPI_PIN_MASK_4_LTS;
break;
case PI_MODEL_RK3399:
pinToGpio = pinToGpio_RK3399;
physToGpio = physToGpio_RK3399;
ORANGEPI_PIN_MASK = ORANGEPI_PIN_MASK_RK3399;
break;
case PI_MODEL_R1_PLUS:
pinToGpio = pinToGpio_R1_PLUS;
physToGpio = physToGpio_R1_PLUS;
ORANGEPI_PIN_MASK = ORANGEPI_PIN_MASK_R1_PLUS;
break;
case PI_MODEL_H3:
pinToGpio = pinToGpio_H3;
physToGpio = physToGpio_H3;
ORANGEPI_PIN_MASK = ORANGEPI_PIN_MASK_H3;
break;
case PI_MODEL_5:
pinToGpio = pinToGpio_5;
physToGpio = physToGpio_5;
ORANGEPI_PIN_MASK = ORANGEPI_PIN_MASK_5;
break;
case PI_MODEL_5B:
pinToGpio = pinToGpio_5B;
physToGpio = physToGpio_5B;
ORANGEPI_PIN_MASK = ORANGEPI_PIN_MASK_5B;
break;
case PI_MODEL_5_PLUS:
pinToGpio = pinToGpio_5PLUS;
physToGpio = physToGpio_5PLUS;
ORANGEPI_PIN_MASK = ORANGEPI_PIN_MASK_5PLUS;
break;
case PI_MODEL_900:
pinToGpio = pinToGpio_900;
physToGpio = physToGpio_900;
ORANGEPI_PIN_MASK = ORANGEPI_PIN_MASK_900;
break;
case PI_MODEL_CM4:
case PI_MODEL_3B:
pinToGpio = pinToGpio_CM4;
physToGpio = physToGpio_CM4;
ORANGEPI_PIN_MASK = ORANGEPI_PIN_MASK_CM4;
break;
default:
printf ("Oops - unable to determine board type... model: %d\n", OrangePiModel);
break ;
}
set_soc_info();
// Open the master /dev/ memory control device
// Device strategy: December 2016:
// Try /dev/mem. If that fails, then
// try /dev/gpiomem. If that fails then game over.
if ((fd = open ("/dev/mem", O_RDWR | O_SYNC | O_CLOEXEC)) < 0){
if ((fd = open ("/dev/gpiomem", O_RDWR | O_SYNC | O_CLOEXEC) ) >= 0){ // We're using gpiomem
piGpioBase = 0 ;
usingGpioMem = TRUE ;
}
else
return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: Unable to open /dev/mem or /dev/gpiomem: %s.\n"
" Aborting your program because if it can not access the GPIO\n"
" hardware then it most certianly won't work\n"
" Try running with sudo?\n", strerror (errno)) ;
}
switch (OrangePiModel)
{
case PI_MODEL_3: case PI_MODEL_LTIE_2: case PI_MODEL_ZERO_2:
case PI_MODEL_ZERO: case PI_MODEL_ZERO_PLUS_2: case PI_MODEL_WIN:
case PI_MODEL_PRIME: case PI_MODEL_PC_2: case PI_MODEL_ZERO_PLUS:
case PI_MODEL_H3: case PI_MODEL_ZERO_2_W:
sunxi_gpio_info_t.gpio = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, sunxi_gpio_info_t.gpio_base_addr);
if ((int32_t)(unsigned long)sunxi_gpio_info_t.gpio == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (GPIO) failed: %s\n", strerror(errno));
sunxi_gpio_info_t.r_gpio = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, sunxi_gpio_info_t.r_gpio_base_addr);
if ((int32_t)(unsigned long)sunxi_gpio_info_t.r_gpio == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (GPIO) failed: %s\n", strerror(errno));
break;
case PI_MODEL_R1_PLUS:
rk3328_soc_info_t.cru_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3328_CRU_BASE);
if ((int32_t)(unsigned long)rk3328_soc_info_t.cru_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (CRU_BASE) failed: %s\n", strerror(errno));
rk3328_soc_info_t.grf_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3328_GRF_BASE);
if ((int32_t)(unsigned long)rk3328_soc_info_t.grf_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (GRF_BASE) failed: %s\n", strerror(errno));
rk3328_soc_info_t.gpio2_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3328_GPIO2_BASE);
if ((int32_t)(unsigned long)rk3328_soc_info_t.gpio2_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (GPIO2_BASE) failed: %s\n", strerror(errno));
rk3328_soc_info_t.gpio3_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3328_GPIO3_BASE);
if ((int32_t)(unsigned long)rk3328_soc_info_t.gpio3_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (GPIO3_BASE) failed: %s\n", strerror(errno));
break;
case PI_MODEL_RK3399: case PI_MODEL_4: case PI_MODEL_4_LTS: case PI_MODEL_800:
rk3399_soc_info_t.gpio2_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3399_GPIO2_BASE);
if ((int32_t)(unsigned long)rk3399_soc_info_t.gpio2_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (GPIO2_BASE) failed: %s\n", strerror(errno));
rk3399_soc_info_t.cru_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3399_CRU_BASE);
if ((int32_t)(unsigned long)rk3399_soc_info_t.cru_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (CRU_BASE) failed: %s\n", strerror(errno));
rk3399_soc_info_t.pmucru_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3399_PMUCRU_BASE);
if ((int32_t)(unsigned long)rk3399_soc_info_t.pmucru_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (PMUCRU_BASE) failed: %s\n", strerror(errno));
rk3399_soc_info_t.grf_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3399_GRF_BASE);
if ((int32_t)(unsigned long)rk3399_soc_info_t.grf_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (GRF_BASE) failed: %s\n", strerror(errno));
rk3399_soc_info_t.pmugrf_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3399_PMUGRF_BASE);
if ((int32_t)(unsigned long)rk3399_soc_info_t.pmugrf_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (PMUGRF_BASE) failed: %s\n", strerror(errno));
rk3399_soc_info_t.gpio1_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3399_GPIO1_BASE);
if ((int32_t)(unsigned long)rk3399_soc_info_t.grf_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (GPIO1_BASE) failed: %s\n", strerror(errno));
rk3399_soc_info_t.gpio4_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3399_GPIO4_BASE);
if ((int32_t)(unsigned long)rk3399_soc_info_t.gpio4_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (GPIO4_BASE) failed: %s\n", strerror(errno));
break;
case PI_MODEL_5: case PI_MODEL_5B: case PI_MODEL_5_PLUS: case PI_MODEL_900:
/* GPIO Register */
rk3588_soc_info_t.gpio0_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3588_GPIO0_BASE);
if ((int32_t)(unsigned long)rk3588_soc_info_t.gpio0_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (RK3588_GPIO0_BASE) failed: %s\n", strerror(errno));
rk3588_soc_info_t.gpio1_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3588_GPIO1_BASE);
if ((int32_t)(unsigned long)rk3588_soc_info_t.gpio1_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (RK3588_GPIO1_BASE) failed: %s\n", strerror(errno));
rk3588_soc_info_t.gpio2_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3588_GPIO2_BASE);
if ((int32_t)(unsigned long)rk3588_soc_info_t.gpio2_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (RK3588_GPIO2_BASE) failed: %s\n", strerror(errno));
rk3588_soc_info_t.gpio3_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3588_GPIO3_BASE);
if ((int32_t)(unsigned long)rk3588_soc_info_t.gpio3_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (RK3588_GPIO3_BASE) failed: %s\n", strerror(errno));
rk3588_soc_info_t.gpio4_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3588_GPIO4_BASE);
if ((int32_t)(unsigned long)rk3588_soc_info_t.gpio4_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (RK3588_GPIO4_BASE) failed: %s\n", strerror(errno));
rk3588_soc_info_t.pmu1_ioc_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3588_PMU1_IOC_BASE);
if ((int32_t)(unsigned long)rk3588_soc_info_t.pmu1_ioc_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (RK3588_PMU1_IOC_BASE) failed: %s\n", strerror(errno));
rk3588_soc_info_t.pmu2_ioc_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3588_PMU2_IOC_BASE);
if ((int32_t)(unsigned long)rk3588_soc_info_t.pmu2_ioc_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (RK3588_PMU2_IOC_BASE) failed: %s\n", strerror(errno));
rk3588_soc_info_t.bus_ioc_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3588_BUS_IOC_BASE);
if ((int32_t)(unsigned long)rk3588_soc_info_t.bus_ioc_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (RK3588_BUS_IOC_BASE) failed: %s\n", strerror(errno));
rk3588_soc_info_t.cur_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3588_CRU_BASE);
if ((int32_t)(unsigned long)rk3588_soc_info_t.cur_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (RK3588_CRU_BASE) failed: %s\n", strerror(errno));
rk3588_soc_info_t.pmu1cur_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3588_PMU1CRU_BASE);
if ((int32_t)(unsigned long)rk3588_soc_info_t.pmu1cur_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (RK3588_PMU1CRU_BASE) failed: %s\n", strerror(errno));
rk3588_soc_info_t.vccio1_4_ioc_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3588_VCCIO1_4_IOC_BASE);
if ((int32_t)(unsigned long)rk3588_soc_info_t.pmu1cur_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (RK3588_VCCIO1_4_IOC_BASE) failed: %s\n", strerror(errno));
rk3588_soc_info_t.vccio3_5_ioc_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3588_VCCIO3_5_IOC_BASE);
if ((int32_t)(unsigned long)rk3588_soc_info_t.pmu1cur_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (RK3588_VCCIO3_5_IOC_BASE) failed: %s\n", strerror(errno));
rk3588_soc_info_t.vccio6_ioc_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3588_VCCIO6_IOC_BASE);
if ((int32_t)(unsigned long)rk3588_soc_info_t.pmu1cur_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (RK3588_VCCIO6_IOC_BASE) failed: %s\n", strerror(errno));
break;
case PI_MODEL_CM4:
case PI_MODEL_3B:
/* GPIO Register */
rk3566_soc_info_t.gpio0_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3566_GPIO0_BASE);
if ((int32_t)(unsigned long)rk3566_soc_info_t.gpio0_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (RK3566_GPIO0_BASE) failed: %s\n", strerror(errno));
rk3566_soc_info_t.gpio1_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3566_GPIO1_BASE);
if ((int32_t)(unsigned long)rk3566_soc_info_t.gpio1_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (RK3566_GPIO1_BASE) failed: %s\n", strerror(errno));
rk3566_soc_info_t.gpio2_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3566_GPIO2_BASE);
if ((int32_t)(unsigned long)rk3566_soc_info_t.gpio2_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (RK3566_GPIO2_BASE) failed: %s\n", strerror(errno));
rk3566_soc_info_t.gpio3_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3566_GPIO3_BASE);
if ((int32_t)(unsigned long)rk3566_soc_info_t.gpio3_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (RK3566_GPIO3_BASE) failed: %s\n", strerror(errno));
rk3566_soc_info_t.gpio4_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3566_GPIO4_BASE);
if ((int32_t)(unsigned long)rk3566_soc_info_t.gpio4_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (RK3566_GPIO4_BASE) failed: %s\n", strerror(errno));
rk3566_soc_info_t.pmu_grf_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3566_PMU_GRF_BASE);
if ((int32_t)(unsigned long)rk3566_soc_info_t.pmu_grf_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (RK3566_PMU_GRF_BASE) failed: %s\n", strerror(errno));
rk3566_soc_info_t.sys_grf_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3566_SYS_GRF_BASE);
if ((int32_t)(unsigned long)rk3566_soc_info_t.sys_grf_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (RK3566_SYS_GRF_BASE) failed: %s\n", strerror(errno));
rk3566_soc_info_t.cru_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3566_CRU_BASE);
if ((int32_t)(unsigned long)rk3566_soc_info_t.cru_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (RK3566_CRU_BASE) failed: %s\n", strerror(errno));
rk3566_soc_info_t.pmu_cru_base = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, RK3566_PMU_CRU_BASE);
if ((int32_t)(unsigned long)rk3566_soc_info_t.pmu_cru_base == -1)
return wiringPiFailure(WPI_ALMOST, "wiringPiSetup: mmap (RK3566_PMU_CRU_BASE) failed: %s\n", strerror(errno));
break;
default:
printf("model %d is error\n", OrangePiModel);
break ;
}
initialiseEpoch () ;
return 0 ;
}
/*
* wiringPiSetupGpio:
* Must be called once at the start of your program execution.
*
* GPIO setup: Initialises the system into GPIO Pin mode and uses the
* memory mapped hardware directly.
*********************************************************************************
*/
int wiringPiSetupGpio (void)
{
(void)wiringPiSetup () ;
if (wiringPiDebug)
printf ("wiringPi: wiringPiSetupGpio called\n") ;
wiringPiMode = WPI_MODE_GPIO ;
return 0 ;
}
/*
* wiringPiSetupPhys:
* Must be called once at the start of your program execution.
*
* Phys setup: Initialises the system into Physical Pin mode and uses the
* memory mapped hardware directly.
*********************************************************************************
*/
int wiringPiSetupPhys (void)
{
(void)wiringPiSetup () ;
if (wiringPiDebug)
printf ("wiringPi: wiringPiSetupPhys called\n") ;
wiringPiMode = WPI_MODE_PHYS ;
return 0 ;
}
/*
* wiringPiSetupSys:
* Must be called once at the start of your program execution.
*
* Initialisation (again), however this time we are using the /sys/class/gpio
* interface to the GPIO systems - slightly slower, but always usable as
* a non-root user, assuming the devices are already exported and setup correctly.
*/
int wiringPiSetupSys (void)
{
int pin ;
int tmpGpio;
char fName [128] ;
if (wiringPiSysSetuped)
return 0 ;
wiringPiSysSetuped = TRUE ;
if (getenv (ENV_DEBUG) != NULL)
wiringPiDebug = TRUE ;
if (getenv (ENV_CODES) != NULL)
wiringPiReturnCodes = TRUE ;
if (wiringPiDebug)
printf ("wiringPi: wiringPiSetupSys called\n") ;
piBoardId (&OrangePiModel) ;
switch (OrangePiModel)
{
case PI_MODEL_3:
pinToGpio = pinToGpio_3;
physToGpio = physToGpio_3;
break;
case PI_MODEL_LTIE_2:
pinToGpio = pinToGpio_LITE_2;
physToGpio = physToGpio_LITE_2;
break;
case PI_MODEL_ZERO:
pinToGpio = pinToGpio_LITE_2;
physToGpio = physToGpio_LITE_2;
break;
case PI_MODEL_ZERO_PLUS_2:
pinToGpio = pinToGpio_ZERO_PLUS_2;
physToGpio = physToGpio_ZERO_PLUS_2;
break;
case PI_MODEL_WIN:
pinToGpio = pinToGpio_WIN;
physToGpio = physToGpio_WIN;
break;
case PI_MODEL_PRIME:
pinToGpio = pinToGpio_PRIME;
physToGpio = physToGpio_PRIME;
break;
case PI_MODEL_PC_2:
pinToGpio = pinToGpio_PC_2;
physToGpio = physToGpio_PC_2;
break;
case PI_MODEL_ZERO_PLUS:
pinToGpio = pinToGpio_ZERO_PLUS;
physToGpio = physToGpio_ZERO_PLUS;
break;
case PI_MODEL_ZERO_2:
pinToGpio = pinToGpio_ZERO_2;
physToGpio = physToGpio_ZERO_2;
break;
case PI_MODEL_ZERO_2_W:
pinToGpio = pinToGpio_ZERO_2_W;
physToGpio = physToGpio_ZERO_2_W;
break;
case PI_MODEL_800:
pinToGpio = pinToGpio_800;
physToGpio = physToGpio_800;
break;
case PI_MODEL_4:
pinToGpio = pinToGpio_4;
physToGpio = physToGpio_4;
break;
case PI_MODEL_4_LTS:
pinToGpio = pinToGpio_4_LTS;
physToGpio = physToGpio_4_LTS;
break;
case PI_MODEL_RK3399:
pinToGpio = pinToGpio_RK3399;
physToGpio = physToGpio_RK3399;
break;
case PI_MODEL_R1_PLUS:
pinToGpio = pinToGpio_R1_PLUS;
physToGpio = physToGpio_R1_PLUS;
break;
default:
pinToGpio = pinToGpio_H3;
physToGpio = physToGpio_H3;
break ;
}
// Open and scan the directory, looking for exported GPIOs, and pre-open
// the 'value' interface to speed things up for later
for (pin = 1 ; pin < 28 ; ++pin)
{
tmpGpio = pinToGpio[pin];
sprintf (fName, "/sys/class/gpio/gpio%d/value", tmpGpio) ;
sysFds [pin] = open (fName, O_RDWR) ;
}
initialiseEpoch () ;
wiringPiMode = WPI_MODE_GPIO_SYS;
return 0 ;
}
/*
* Read register value helper
*/
unsigned int readR(unsigned int addr)
{
unsigned int val = 0;
unsigned int mmap_base;
unsigned int mmap_seek;
switch (OrangePiModel)
{
case PI_MODEL_5: case PI_MODEL_5B:
case PI_MODEL_5_PLUS:
case PI_MODEL_900:
val = 0;
mmap_base = (addr & (0xfffff000));
mmap_seek = (addr - mmap_base);
if(mmap_base == RK3588_GPIO0_BASE)
val = *((unsigned int *)((unsigned char *)rk3588_soc_info_t.gpio0_base + mmap_seek));
else if(mmap_base == RK3588_GPIO1_BASE)
val = *((unsigned int *)((unsigned char *)rk3588_soc_info_t.gpio1_base + mmap_seek));
else if(mmap_base == RK3588_GPIO2_BASE)
val = *((unsigned int *)((unsigned char *)rk3588_soc_info_t.gpio2_base + mmap_seek));
else if(mmap_base == RK3588_GPIO3_BASE)
val = *((unsigned int *)((unsigned char *)rk3588_soc_info_t.gpio3_base + mmap_seek));
else if(mmap_base == RK3588_GPIO4_BASE)
val = *((unsigned int *)((unsigned char *)rk3588_soc_info_t.gpio4_base + mmap_seek));
else if(mmap_base == RK3588_PMU1_IOC_BASE)
val = *((unsigned int *)((unsigned char *)rk3588_soc_info_t.pmu1_ioc_base + mmap_seek));
else if(mmap_base == RK3588_BUS_IOC_BASE)
val = *((unsigned int *)((unsigned char *)rk3588_soc_info_t.bus_ioc_base + mmap_seek));
else if(mmap_base == RK3588_CRU_BASE)
val = *((unsigned int *)((unsigned char *)rk3588_soc_info_t.cur_base + mmap_seek));
else if(mmap_base == RK3588_PMU1CRU_BASE)
val = *((unsigned int *)((unsigned char *)rk3588_soc_info_t.pmu1cur_base + mmap_seek));
else if(mmap_base == RK3588_PMU2_IOC_BASE)
val = *((unsigned int *)((unsigned char *)rk3588_soc_info_t.pmu2_ioc_base + mmap_seek));
else if(mmap_base == RK3588_VCCIO1_4_IOC_BASE)
val = *((unsigned int *)((unsigned char *)rk3588_soc_info_t.vccio1_4_ioc_base + mmap_seek));
else if(mmap_base == RK3588_VCCIO3_5_IOC_BASE)
val = *((unsigned int *)((unsigned char *)rk3588_soc_info_t.vccio3_5_ioc_base + mmap_seek));
else if(mmap_base == RK3588_VCCIO6_IOC_BASE)
val = *((unsigned int *)((unsigned char *)rk3588_soc_info_t.vccio6_ioc_base + mmap_seek));
return val;
break;
case PI_MODEL_800: case PI_MODEL_4_LTS:
case PI_MODEL_4: case PI_MODEL_RK3399:
val = 0;
mmap_base = (addr & (0xfffff000));
mmap_seek = (addr - mmap_base);
if(mmap_base == RK3399_CRU_BASE)
val = *((unsigned int *)((unsigned char *)rk3399_soc_info_t.cru_base + mmap_seek));
else if(mmap_base == RK3399_GRF_BASE)
val = *((unsigned int *)((unsigned char *)rk3399_soc_info_t.grf_base + mmap_seek));
else if(mmap_base == RK3399_GPIO2_BASE)
val = *((unsigned int *)((unsigned char *)rk3399_soc_info_t.gpio2_base + mmap_seek));
else if(mmap_base == RK3399_GPIO1_BASE)
val = *((unsigned int *)((unsigned char *)rk3399_soc_info_t.gpio1_base + mmap_seek));
else if(mmap_base == RK3399_PMUCRU_BASE)
val = *((unsigned int *)((unsigned char *)rk3399_soc_info_t.pmucru_base + mmap_seek));
else if(mmap_base == RK3399_PMUGRF_BASE)
val = *((unsigned int *)((unsigned char *)rk3399_soc_info_t.pmugrf_base + mmap_seek));
else if(mmap_base == RK3399_GPIO4_BASE)
val = *((unsigned int *)((unsigned char *)rk3399_soc_info_t.gpio4_base + mmap_seek));
return val;
break;
case PI_MODEL_R1_PLUS:
val = 0;
mmap_base = (addr & (0xfffff000));
mmap_seek = (addr - mmap_base);
if(mmap_base == RK3328_CRU_BASE)
val = *((unsigned int *)((unsigned char *)rk3328_soc_info_t.cru_base + mmap_seek));
else if(mmap_base == RK3328_GRF_BASE)
val = *((unsigned int *)((unsigned char *)rk3328_soc_info_t.grf_base + mmap_seek));
else if(mmap_base == RK3328_GPIO2_BASE)
val = *((unsigned int *)((unsigned char *)rk3328_soc_info_t.gpio2_base + mmap_seek));
else if(mmap_base == RK3328_GPIO3_BASE)
val = *((unsigned int *)((unsigned char *)rk3328_soc_info_t.gpio3_base + mmap_seek));
return val;
break;
case PI_MODEL_CM4:
case PI_MODEL_3B:
val = 0;
mmap_base = (addr & (0xfffff000));
mmap_seek = (addr - mmap_base);
if(mmap_base == RK3566_GPIO0_BASE)
val = *((unsigned int *)((unsigned char *)rk3566_soc_info_t.gpio0_base + mmap_seek));
else if(mmap_base == RK3566_GPIO1_BASE)
val = *((unsigned int *)((unsigned char *)rk3566_soc_info_t.gpio1_base + mmap_seek));
else if(mmap_base == RK3566_GPIO2_BASE)
val = *((unsigned int *)((unsigned char *)rk3566_soc_info_t.gpio2_base + mmap_seek));
else if(mmap_base == RK3566_GPIO3_BASE)
val = *((unsigned int *)((unsigned char *)rk3566_soc_info_t.gpio3_base + mmap_seek));
else if(mmap_base == RK3566_GPIO4_BASE)
val = *((unsigned int *)((unsigned char *)rk3566_soc_info_t.gpio4_base + mmap_seek));
else if(mmap_base == RK3566_PMU_GRF_BASE)
val = *((unsigned int *)((unsigned char *)rk3566_soc_info_t.pmu_grf_base + mmap_seek));
else if(mmap_base == RK3566_SYS_GRF_BASE)
val = *((unsigned int *)((unsigned char *)rk3566_soc_info_t.sys_grf_base + mmap_seek));
else if(mmap_base == RK3566_CRU_BASE)
val = *((unsigned int *)((unsigned char *)rk3566_soc_info_t.cru_base + mmap_seek));
else if(mmap_base == RK3566_PMU_CRU_BASE)
val = *((unsigned int *)((unsigned char *)rk3566_soc_info_t.pmu_cru_base + mmap_seek));
return val;
break;
default:
val = 0;
mmap_base = (addr & 0xfffff000);
mmap_seek = ((addr - mmap_base) >> 2);
if (addr >= sunxi_gpio_info_t.r_gpio_base_addr)
val = *(sunxi_gpio_info_t.r_gpio + mmap_seek);
else
val = *(sunxi_gpio_info_t.gpio + mmap_seek);
return val;
break;
}
return -1;
}
/*
* Wirte value to register helper
*/
void writeR(unsigned int val, unsigned int addr)
{
unsigned int mmap_base;
unsigned int mmap_seek;
switch (OrangePiModel)
{
case PI_MODEL_5: case PI_MODEL_5B:
case PI_MODEL_5_PLUS:
case PI_MODEL_900:
mmap_base = (addr & (~0xfff));
mmap_seek = (addr - mmap_base);
if(mmap_base == RK3588_GPIO0_BASE)
*((unsigned int *)((unsigned char *)rk3588_soc_info_t.gpio0_base + mmap_seek)) = val;
else if(mmap_base == RK3588_GPIO1_BASE)
*((unsigned int *)((unsigned char *)rk3588_soc_info_t.gpio1_base + mmap_seek)) = val;
else if(mmap_base == RK3588_GPIO2_BASE)
*((unsigned int *)((unsigned char *)rk3588_soc_info_t.gpio2_base + mmap_seek)) = val;
else if(mmap_base == RK3588_GPIO3_BASE)
*((unsigned int *)((unsigned char *)rk3588_soc_info_t.gpio3_base + mmap_seek)) = val;
else if(mmap_base == RK3588_GPIO4_BASE)
*((unsigned int *)((unsigned char *)rk3588_soc_info_t.gpio4_base + mmap_seek)) = val;
else if(mmap_base == RK3588_PMU1_IOC_BASE)
*((unsigned int *)((unsigned char *)rk3588_soc_info_t.pmu1_ioc_base + mmap_seek)) = val;
else if(mmap_base == RK3588_BUS_IOC_BASE)
*((unsigned int *)((unsigned char *)rk3588_soc_info_t.bus_ioc_base + mmap_seek)) = val;
else if(mmap_base == RK3588_CRU_BASE)
*((unsigned int *)((unsigned char *)rk3588_soc_info_t.cur_base + mmap_seek)) = val;
else if(mmap_base == RK3588_PMU1CRU_BASE)
*((unsigned int *)((unsigned char *)rk3588_soc_info_t.pmu1cur_base + mmap_seek)) = val;
else if(mmap_base == RK3588_PMU2_IOC_BASE)
*((unsigned int *)((unsigned char *)rk3588_soc_info_t.pmu2_ioc_base + mmap_seek)) = val;
else if(mmap_base == RK3588_VCCIO1_4_IOC_BASE)
*((unsigned int *)((unsigned char *)rk3588_soc_info_t.vccio1_4_ioc_base + mmap_seek)) = val;
else if(mmap_base == RK3588_VCCIO3_5_IOC_BASE)
*((unsigned int *)((unsigned char *)rk3588_soc_info_t.vccio3_5_ioc_base + mmap_seek)) = val;
else if(mmap_base == RK3588_VCCIO6_IOC_BASE)
*((unsigned int *)((unsigned char *)rk3588_soc_info_t.vccio6_ioc_base + mmap_seek)) = val;
break;
case PI_MODEL_800: case PI_MODEL_4_LTS:
case PI_MODEL_4: case PI_MODEL_RK3399:
mmap_base = (addr & (~0xfff));
mmap_seek = (addr - mmap_base);
if(mmap_base == RK3399_CRU_BASE)
*((unsigned int *)((unsigned char *)rk3399_soc_info_t.cru_base + mmap_seek)) = val;
else if(mmap_base == RK3399_GRF_BASE)
*((unsigned int *)((unsigned char *)rk3399_soc_info_t.grf_base + mmap_seek)) = val;
else if(mmap_base == RK3399_GPIO2_BASE)
*((unsigned int *)((unsigned char *)rk3399_soc_info_t.gpio2_base + mmap_seek)) = val;
else if(mmap_base == RK3399_GPIO1_BASE)
*((unsigned int *)((unsigned char *)rk3399_soc_info_t.gpio1_base + mmap_seek)) = val;
else if(mmap_base == RK3399_PMUCRU_BASE)
*((unsigned int *)((unsigned char *)rk3399_soc_info_t.pmucru_base + mmap_seek)) = val;
else if(mmap_base == RK3399_PMUGRF_BASE)
*((unsigned int *)((unsigned char *)rk3399_soc_info_t.pmugrf_base + mmap_seek)) = val;
else if(mmap_base == RK3399_GPIO4_BASE)
*((unsigned int *)((unsigned char *)rk3399_soc_info_t.gpio4_base + mmap_seek)) = val;
break;
case PI_MODEL_R1_PLUS:
mmap_base = (addr & (~0xfff));
mmap_seek = (addr - mmap_base);
if(mmap_base == RK3328_CRU_BASE)
*((unsigned int *)((unsigned char *)rk3328_soc_info_t.cru_base + mmap_seek)) = val;
else if(mmap_base == RK3328_GRF_BASE)
*((unsigned int *)((unsigned char *)rk3328_soc_info_t.grf_base + mmap_seek)) = val;
else if(mmap_base == RK3328_GPIO2_BASE)
*((unsigned int *)((unsigned char *)rk3328_soc_info_t.gpio2_base + mmap_seek)) = val;
else if(mmap_base == RK3328_GPIO3_BASE)
*((unsigned int *)((unsigned char *)rk3328_soc_info_t.gpio3_base + mmap_seek)) = val;
break;
case PI_MODEL_CM4:
case PI_MODEL_3B:
mmap_base = (addr & (~0xfff));
mmap_seek = (addr - mmap_base);
if(mmap_base == RK3566_GPIO0_BASE)
*((unsigned int *)((unsigned char *)rk3566_soc_info_t.gpio0_base + mmap_seek)) = val;
else if(mmap_base == RK3566_GPIO1_BASE)
*((unsigned int *)((unsigned char *)rk3566_soc_info_t.gpio1_base + mmap_seek)) = val;
else if(mmap_base == RK3566_GPIO2_BASE)
*((unsigned int *)((unsigned char *)rk3566_soc_info_t.gpio2_base + mmap_seek)) = val;
else if(mmap_base == RK3566_GPIO3_BASE)
*((unsigned int *)((unsigned char *)rk3566_soc_info_t.gpio3_base + mmap_seek)) = val;
else if(mmap_base == RK3566_GPIO4_BASE)
*((unsigned int *)((unsigned char *)rk3566_soc_info_t.gpio4_base + mmap_seek)) = val;
else if(mmap_base == RK3566_PMU_GRF_BASE)
*((unsigned int *)((unsigned char *)rk3566_soc_info_t.pmu_grf_base + mmap_seek)) = val;
else if(mmap_base == RK3566_SYS_GRF_BASE)
*((unsigned int *)((unsigned char *)rk3566_soc_info_t.sys_grf_base + mmap_seek)) = val;
else if(mmap_base == RK3566_CRU_BASE)
*((unsigned int *)((unsigned char *)rk3566_soc_info_t.cru_base + mmap_seek)) = val;
else if(mmap_base == RK3566_PMU_CRU_BASE)
*((unsigned int *)((unsigned char *)rk3566_soc_info_t.pmu_cru_base + mmap_seek)) = val;
break;
default:
mmap_base = (addr & 0xfffff000);
mmap_seek = ((addr - mmap_base) >> 2);
if (addr >= sunxi_gpio_info_t.r_gpio_base_addr)
*(sunxi_gpio_info_t.r_gpio + mmap_seek) = val;
else
*(sunxi_gpio_info_t.gpio + mmap_seek) = val;
break;
}
}
int OrangePi_get_gpio_mode(int pin)
{
unsigned int regval = 0;
unsigned int bank = pin >> 5;
unsigned int index = pin - (bank << 5);
unsigned int phyaddr = 0;
unsigned char mode = -1;
unsigned int grf_phyaddr = 0, ddr_phyaddr = 0;
unsigned int rk3588_pmu1_ioc_phyaddr;
unsigned int rk3588_bus_ioc_phyaddr;
int offset;
switch (OrangePiModel)
{
case PI_MODEL_800: case PI_MODEL_4_LTS:
case PI_MODEL_4: case PI_MODEL_RK3399:
offset = ((index - ((index >> 3) << 3)));
if(bank == 1){
grf_phyaddr = RK3399_PMUGRF_BASE + ((index >> 3) << 2) + 0x10;
ddr_phyaddr = RK3399_GPIO1_BASE + RK3399_GPIO_SWPORTA_DDR_OFFSET;
}
else if(bank == 2){
grf_phyaddr = RK3399_GRF_BASE + ((index >> 3) << 2);
ddr_phyaddr = RK3399_GPIO2_BASE + RK3399_GPIO_SWPORTA_DDR_OFFSET;
}
else if(bank == 4){
grf_phyaddr = RK3399_GRF_BASE + ((index >> 3) << 2) +0x20;
ddr_phyaddr = RK3399_GPIO4_BASE + RK3399_GPIO_SWPORTA_DDR_OFFSET;
}
if (ORANGEPI_PIN_MASK[bank][index] != -1) {
regval = readR(grf_phyaddr);
mode = (regval >> (offset << 1)) & 0x3;//获取控制模式的那两位的值
if(mode == 0){ //如果是gpio模式
regval = readR(ddr_phyaddr);//获取gpio方向寄存器的值
return (regval >> index) & 1;//index对应的gpio的方向值0为in1为out
}
return mode + 1;//如果不是gpio模式返回的alt从2开始0和1是in和out
}
break;
case PI_MODEL_5: case PI_MODEL_5B:
case PI_MODEL_5_PLUS:
case PI_MODEL_900:
rk3588_bus_ioc_phyaddr = RK3588_BUS_IOC_BASE + (0x20 * bank) + ((index >> 2) << 2);
if(bank == 0){
if (index < 12){
;/* Todo */
}else{
ddr_phyaddr = RK3588_GPIO0_BASE + RK3588_GPIO_SWPORT_DDR_L_OFFSET + ((index / 16) << 2);
}
}
else if(bank == 1){
ddr_phyaddr = RK3588_GPIO1_BASE + RK3588_GPIO_SWPORT_DDR_L_OFFSET + ((index / 16) << 2);
}
else if(bank == 2){
ddr_phyaddr = RK3588_GPIO2_BASE + RK3588_GPIO_SWPORT_DDR_L_OFFSET + ((index / 16) << 2);
}
else if(bank == 3){
ddr_phyaddr = RK3588_GPIO3_BASE + RK3588_GPIO_SWPORT_DDR_L_OFFSET + ((index / 16) << 2);
}
else if(bank == 4){
ddr_phyaddr = RK3588_GPIO4_BASE + RK3588_GPIO_SWPORT_DDR_L_OFFSET + ((index / 16) << 2);
}
if (ORANGEPI_PIN_MASK[bank][index] != -1) {
if ( bank == 0 && index < 12 )
;/*Todo*/
else
regval = readR(rk3588_bus_ioc_phyaddr);
mode = (regval >> ((index % 4) << 2)) & 0xf;//获取控制模式的那四位的值
if(mode == 0){ //如果是gpio模式
regval = readR(ddr_phyaddr); //获取gpio方向寄存器的值
return (regval >> (index % 16)) & 0x1; //index对应的gpio的方向值0为in1为out
}
return mode + 1; //如果不是gpio模式返回的alt从2开始0和1是in和out
}
break;
case PI_MODEL_R1_PLUS:
offset = ((index - ((index >> 3) << 3)));
if(bank == 2)
{
//ddr_phyaddr = GPIO2_BASE + GPIO_SWPORTA_DDR_OFFSET;
ddr_phyaddr = 0xff230004;
//grf_phyaddr = GRF_BASE + ((index >> 3) << 2) + 0x10;
if(0 == (index >> 3))//gpio2_ax
{
grf_phyaddr = RK3328_GRF_BASE + 0x20;
}
else if(3 == (index >> 3))//gpio2_dx
{
grf_phyaddr = RK3328_GRF_BASE + 0x34;
}
}
else if(bank == 3)
{
//grf_phyaddr = GRF_BASE + ((index >> 3) << 2) +0x20;
ddr_phyaddr = RK3328_GPIO3_BASE + RK3328_GPIO_SWPORTA_DDR_OFFSET;
if (0 == (index >> 3))
{
if(4 == offset)//gpio3_a4
{
grf_phyaddr = RK3328_GRF_BASE + 0x38;
}
else//gpio3_a567
{
grf_phyaddr = RK3328_GRF_BASE + 0x3c;
}
}
else if(2 == (index >> 3)) //gpio3_c
{
grf_phyaddr = RK3328_GRF_BASE + 0x48;
}
}
if (ORANGEPI_PIN_MASK[bank][index] != -1)
{
regval = readR(grf_phyaddr);
writeR(0xffff9877, 0xff440240);
if(3 == bank && (0 == (index >> 3))) //gpio3_ax需要写3位
{
mode = (regval >> ((offset % 5) * 3)) & 0x7;
}
else
{
mode = (regval >> (offset << 1)) & 0x3;
}
if(mode == 0){
regval = readR(ddr_phyaddr);
return (regval >> index) & 1;
}
return mode + 1;
}
break;
case PI_MODEL_CM4:
case PI_MODEL_3B:
if(bank == 0){
grf_phyaddr = RK3566_PMU_GRF_BASE + RK3566_PMU_GRF_GPIO0A_IOMUX_L_OFFSET + ((pin >> 2) << 2);
ddr_phyaddr = RK3566_GPIO0_BASE + RK3566_GPIO_SWPORT_DDR_L_OFFSET + ((index >> 4) << 2);
}
else{
grf_phyaddr = RK3566_SYS_GRF_BASE + RK3566_GRF_GPIO1A_IOMUX_L_OFFSET + (((pin - 32) >> 2) << 2);
ddr_phyaddr = RK3566_GPIO1_BASE + ((bank - 1) << 16) + RK3566_GPIO_SWPORT_DDR_L_OFFSET + ((index >> 4) << 2);
}
offset = (index % 4) << 2;
if (ORANGEPI_PIN_MASK[bank][index] != -1) {
regval = readR(grf_phyaddr);
mode = (regval >> offset) & 0x7;
if(mode == 0){ //如果是gpio模式
regval = readR(ddr_phyaddr);//获取gpio方向寄存器的值
return (regval >> (index % 16)) & 0x1;//index对应的gpio的方向值0为in1为out
}
return mode + 1;//如果不是gpio模式返回的alt从2开始0和1是in和out
}
break;
default:
offset = ((index - ((index >> 3) << 3)) << 2);
if (bank == 11)
phyaddr = sunxi_gpio_info_t.r_gpio_base_addr + sunxi_gpio_info_t.r_gpio_base_offset + ((index >> 3) << 2);
else
phyaddr = sunxi_gpio_info_t.gpio_base_addr + sunxi_gpio_info_t.gpio_base_offset + (bank * 36) + ((index >> 3) << 2);
/* Ignore unused gpio */
if (ORANGEPI_PIN_MASK[bank][index] != -1)
{
regval = readR(phyaddr);
mode = (regval >> offset) & 7;
}
return mode;
break;
}
return -1;
}
/*
* Set GPIO Mode
*/
int OrangePi_set_gpio_mode(int pin, int mode)
{
unsigned int regval = 0;
unsigned int bank = pin >> 5;
unsigned int index = pin - (bank << 5);
unsigned int phyaddr = 0;
int offset;
unsigned int cru_phyaddr =0, grf_phyaddr = 0, gpio_phyaddr = 0, ddr_phyaddr = 0;
unsigned int cru_val = 0;
unsigned int rk3588_pmu1_ioc_phyaddr;
unsigned int rk3588_bus_ioc_phyaddr;
unsigned int temp = 0;
unsigned int bit_enable;
unsigned int grf_val = 0;
switch (OrangePiModel)
{
case PI_MODEL_5: case PI_MODEL_5B:
case PI_MODEL_5_PLUS:
case PI_MODEL_900:
rk3588_bus_ioc_phyaddr = RK3588_BUS_IOC_BASE + (0x20 * bank) + ((index >> 2) << 2);
if(bank == 0){
if (index < 12){
;/* Todo */
}else{
ddr_phyaddr = RK3588_GPIO0_BASE + RK3588_GPIO_SWPORT_DDR_L_OFFSET + ((index / 16) << 2);
}
cru_phyaddr = RK3588_PMU1CRU_BASE + RK3588_PMU1CRU_GATE_CON5_OFFSET;
cru_val = 0xffff9fff;
}
else if(bank == 1){
ddr_phyaddr = RK3588_GPIO1_BASE + RK3588_GPIO_SWPORT_DDR_L_OFFSET + ((index / 16) << 2);
cru_phyaddr = RK3588_CRU_BASE + RK3588_CRU_GATE_CON16_OFFSET;
cru_val = 0xffff3fff;
}
else if(bank == 2){
ddr_phyaddr = RK3588_GPIO2_BASE + RK3588_GPIO_SWPORT_DDR_L_OFFSET + ((index / 16) << 2);
cru_phyaddr = RK3588_CRU_BASE + RK3588_CRU_GATE_CON17_OFFSET;
cru_val = 0xffffffc0;
}
else if(bank == 3){
ddr_phyaddr = RK3588_GPIO3_BASE + RK3588_GPIO_SWPORT_DDR_L_OFFSET + ((index / 16) << 2);
cru_phyaddr = RK3588_CRU_BASE + RK3588_CRU_GATE_CON17_OFFSET;
cru_val = 0xffffffc0;
}
else if(bank == 4){
ddr_phyaddr = RK3588_GPIO4_BASE + RK3588_GPIO_SWPORT_DDR_L_OFFSET + ((index / 16) << 2);
cru_phyaddr = RK3588_CRU_BASE + RK3588_CRU_GATE_CON17_OFFSET;
cru_val = 0xffffffc0;
}
/* Ignore unused gpio */
if (ORANGEPI_PIN_MASK[bank][index] != -1)
{
regval = readR(cru_phyaddr);
regval &= cru_val;
writeR(regval, cru_phyaddr);
regval = readR(rk3588_bus_ioc_phyaddr);
regval |= 0xffff0000;
regval &= ~(0xf << ((index % 4) << 2));
writeR(regval, rk3588_bus_ioc_phyaddr);
regval = readR(rk3588_bus_ioc_phyaddr);
/* Set Input */
if(INPUT == mode)
{
regval = readR(ddr_phyaddr);
regval |= 0xffff0000;
regval &= ~(1 << (index % 16));
writeR(regval, ddr_phyaddr);
if (wiringPiDebug){
regval = readR(ddr_phyaddr);
printf("Input mode set over reg val: %#x\n",regval);
}
}
else if(OUTPUT == mode)
{
regval = readR(ddr_phyaddr);
regval |= 0xffff0000;
regval |= (1 << (index % 16));
writeR(regval, ddr_phyaddr);
if (wiringPiDebug){
regval = readR(ddr_phyaddr);
printf("Input mode set over reg val: %#x\n",regval);
}
}
else
{
printf("Unknow mode\n");
}
}
else
{
printf("Pin mode failed!\n");
}
break;
case PI_MODEL_800: case PI_MODEL_4_LTS:
case PI_MODEL_4: case PI_MODEL_RK3399:
offset = ((index - ((index >> 3) << 3)));
if(bank == 1){
cru_phyaddr = RK3399_PMUCRU_BASE + RK3399_PMUCRU_CLKGATE_CON1_OFFSET;
grf_phyaddr = RK3399_PMUGRF_BASE + ((index >> 3) << 2) + 0x10;
gpio_phyaddr = RK3399_GPIO1_BASE + RK3399_GPIO_SWPORTA_DDR_OFFSET;
}
else if(bank == 2){
cru_phyaddr = RK3399_CRU_BASE + RK3399_CRU_CLKGATE_CON31_OFFSET;
grf_phyaddr = RK3399_GRF_BASE + ((index >> 3) << 2);
gpio_phyaddr = RK3399_GPIO2_BASE + RK3399_GPIO_SWPORTA_DDR_OFFSET;
}
else if(bank == 4){
cru_phyaddr = RK3399_CRU_BASE + RK3399_CRU_CLKGATE_CON31_OFFSET;
grf_phyaddr = RK3399_GRF_BASE + ((index >> 3) << 2) +0x20;
gpio_phyaddr = RK3399_GPIO4_BASE + RK3399_GPIO_SWPORTA_DDR_OFFSET;
}
/* Ignore unused gpio */
if (ORANGEPI_PIN_MASK[bank][index] != -1)
{
if (wiringPiDebug)
printf("Register[%#x]: %#x index:%d\n", phyaddr, regval, index);
/* Set Input */
if(INPUT == mode)
{
writeR(0xffff0180, cru_phyaddr);
regval = readR(grf_phyaddr);
regval |= 0x3 << ((offset << 1) | 0x10);
regval &= ~(0x3 << (offset << 1));
writeR(regval, grf_phyaddr);
regval = readR(gpio_phyaddr);
regval &= ~(1 << index);
writeR(regval, gpio_phyaddr);
if (wiringPiDebug){
regval = readR(gpio_phyaddr);
printf("Input mode set over reg val: %#x\n",regval);
}
}
else if(OUTPUT == mode)
{
/* Set Output */
writeR(0xffff0180, cru_phyaddr);
regval = readR(grf_phyaddr);
regval |= 0x3 << ((offset << 1) | 0x10);
regval &= ~(0x3 << (offset << 1));
writeR(regval, grf_phyaddr);
regval = readR(gpio_phyaddr);
regval |= 1 << index;
writeR(regval, gpio_phyaddr);
if (wiringPiDebug)
{
regval = readR(gpio_phyaddr);
printf("Out mode get value: 0x%x\n",regval);
}
}
else
{
printf("Unknow mode\n");
}
}
else
{
printf("Pin mode failed!\n");
}
break;
case PI_MODEL_R1_PLUS:
offset = ((index - ((index >> 3) << 3)));
if(bank == 2)
{
cru_phyaddr = RK3328_CRU_BASE + RK3328_CRU_CLKGATE_CON16_OFFSET;
//grf_phyaddr = GRF_BASE + ((index >> 3) << 2) + 0x10;
gpio_phyaddr = RK3328_GPIO2_BASE + RK3328_GPIO_SWPORTA_DDR_OFFSET;
if(0 == (index >> 3))//gpio2_ax
{
grf_phyaddr = RK3328_GRF_BASE + 0x20;
}
else if(3 == (index >> 3))//gpio2_dx
{
grf_phyaddr = RK3328_GRF_BASE + 0x34;
}
}
else if(bank == 3)
{
cru_phyaddr = RK3328_CRU_BASE + RK3328_CRU_CLKGATE_CON16_OFFSET;
//grf_phyaddr = GRF_BASE + ((index >> 3) << 2) +0x20;
gpio_phyaddr = RK3328_GPIO3_BASE + RK3328_GPIO_SWPORTA_DDR_OFFSET;
if (0 == (index >> 3))
{
if(4 == offset)//gpio3_a4
{
grf_phyaddr = RK3328_GRF_BASE + 0x38;
}
else//gpio3_a567
{
grf_phyaddr = RK3328_GRF_BASE + 0x3c;
}
}
else if(2 == (index >> 3)) //gpio3_c
{
grf_phyaddr = RK3328_GRF_BASE + 0x48;
}
}
/* Ignore unused gpio */
if (ORANGEPI_PIN_MASK[bank][index] != -1)
{
if (wiringPiDebug)
printf("Register[%#x]: %#x index:%d\n", phyaddr, regval, index);
/* Set Input */
if(INPUT == mode)
{
writeR(0xffff9877, cru_phyaddr);
regval = readR(grf_phyaddr);
if(3 == bank && (0 == (index >> 3))) //gpio3_a iomux需要写3位
{
regval |= 0xffff0000;
regval &= ~(0x7 << ((offset % 5) * 3));
}
else //其他的写两位
{
regval |= 0xffff0000;
regval &= ~(0x3 << (offset << 1));
}
writeR(regval, grf_phyaddr);
regval = readR(gpio_phyaddr);
regval &= ~(1 << index);
writeR(regval, gpio_phyaddr);
if (wiringPiDebug)
{
regval = readR(gpio_phyaddr);
printf("Input mode set over reg val: %#x\n",regval);
}
}
else if(OUTPUT == mode)
{
/* Set Output */
writeR(0xffff9877, cru_phyaddr);
regval = readR(grf_phyaddr);
if(3 == bank && (0 == (index >> 3))) //gpio3_a iomux需要写3位
{
regval |= 0xffff0000;
regval &= ~(0x7 << ((offset % 5) * 3));
}
else //其他的写两位
{
regval |= 0xffff0000;
regval &= ~(0x3 << (offset << 1));
}
writeR(regval, grf_phyaddr);
regval = readR(gpio_phyaddr);
regval |= 1 << index;
writeR(regval, gpio_phyaddr);
if (wiringPiDebug)
{
regval = readR(gpio_phyaddr);
printf("Out mode get value: 0x%x\n",regval);
}
}
else
{
printf("Unknow mode\n");
}
}
else
{
printf("Pin mode failed!\n");
}
break;
case PI_MODEL_CM4:
case PI_MODEL_3B:
if(bank == 0){
cru_phyaddr = RK3566_PMU_CRU_BASE + RK3566_PMUCRU_PMUGATE_CON01_OFFSET;
cru_val = ~((0x3 << 9) | (0x3 << (16 + 9)));
grf_phyaddr = RK3566_PMU_GRF_BASE + RK3566_PMU_GRF_GPIO0A_IOMUX_L_OFFSET + ((pin >> 2) << 2);
ddr_phyaddr = RK3566_GPIO0_BASE + RK3566_GPIO_SWPORT_DDR_L_OFFSET + ((index >> 4) << 2);
}
else{
cru_phyaddr = RK3566_CRU_BASE + RK3566_CRU_GATE_CON31_OFFSET;
cru_val = ~((0xff << 2) | (0xff << (16 + 2)));
grf_phyaddr = RK3566_SYS_GRF_BASE + RK3566_GRF_GPIO1A_IOMUX_L_OFFSET + (((pin - 32) >> 2) << 2);
ddr_phyaddr = RK3566_GPIO1_BASE + ((bank - 1) << 16) + RK3566_GPIO_SWPORT_DDR_L_OFFSET + ((index >> 4) << 2);
}
offset = (index % 4) << 2;
bit_enable = 0x7 << (16 + offset);
/* Ignore unused gpio */
if (ORANGEPI_PIN_MASK[bank][index] != -1)
{
regval = readR(cru_phyaddr);
regval &= cru_val;
writeR(regval, cru_phyaddr);
regval = readR(grf_phyaddr);
if(wiringPiDebug)
printf("read val(%#x) from register[%#x]\n", regval, grf_phyaddr);
regval |= bit_enable;
regval &= ~(0x7 << offset);
if (wiringPiDebug)
printf("write val(%#x) to register[%#x]\n", regval, grf_phyaddr);
writeR(regval, grf_phyaddr);
regval = readR(grf_phyaddr);
if(wiringPiDebug)
printf("set over reg val: 0x%x\n", regval);
regval = readR(ddr_phyaddr);
if(wiringPiDebug)
printf("read val ddr (%#x) from register[%#x]\n", regval, ddr_phyaddr);
regval |= 0x1 << (16 + (index % 16));
if(INPUT == mode)
regval &= ~(1 << (index % 16));
else
regval |= (1 << (index % 16));
writeR(regval, ddr_phyaddr);
if (wiringPiDebug)
printf("write val(%#x) to register[%#x]\n", regval, ddr_phyaddr);
regval = readR(ddr_phyaddr);
if (wiringPiDebug)
printf("set over reg val: 0x%x\n", regval);
}
else
{
printf("Pin mode failed!\n");
}
break;
default:
offset = ((index - ((index >> 3) << 3)) << 2);
if (bank == 11)
phyaddr = sunxi_gpio_info_t.r_gpio_base_addr + sunxi_gpio_info_t.r_gpio_base_offset + ((index >> 3) << 2);
else
phyaddr = sunxi_gpio_info_t.gpio_base_addr + sunxi_gpio_info_t.gpio_base_offset + (bank * 36) + ((index >> 3) << 2);
/* Ignore unused gpio */
if (ORANGEPI_PIN_MASK[bank][index] != -1)
{
regval = readR(phyaddr);
if (wiringPiDebug)
printf("Before read reg val: 0x%x offset:%d\n",regval,offset);
if (wiringPiDebug)
printf("Register[%#x]: %#x index:%d\n", phyaddr, regval, index);
/* Set Input */
if(INPUT == mode)
{
regval &= ~(7 << offset);
writeR(regval, phyaddr);
regval = readR(phyaddr);
if (wiringPiDebug)
printf("Input mode set over reg val: %#x\n",regval);
}
else if(OUTPUT == mode)
{
/* Set Output */
regval &= ~(7 << offset);
regval |= (1 << offset);
if (wiringPiDebug)
printf("Out mode ready set val: 0x%x\n",regval);
writeR(regval, phyaddr);
regval = readR(phyaddr);
if (wiringPiDebug)
printf("Out mode get value: 0x%x\n",regval);
}
else
{
printf("Unknow mode\n");
}
}
else
{
printf("Pin mode failed!\n");
}
break;
}
return 0;
}
int OrangePi_set_gpio_alt(int pin, int mode)
{
unsigned int regval = 0;
unsigned int bank = pin >> 5;
unsigned int index = pin - (bank << 5);
unsigned int phyaddr = 0;
int offset = ((index - ((index >> 3) << 3)) << 2);
if (bank == 11)
phyaddr = sunxi_gpio_info_t.r_gpio_base_addr + ((index >> 3) << 2);
else
phyaddr = sunxi_gpio_info_t.gpio_base_addr + (bank * 36) + ((index >> 3) << 2);
/* Ignore unused gpio */
if (ORANGEPI_PIN_MASK[bank][index] != -1)
{
if (wiringPiDebug)
printf("Register[%#x]: %#x index:%d\n", phyaddr, regval, index);
regval = readR(phyaddr);
regval &= ~(7 << offset);
regval |= (mode << offset);
writeR(regval, phyaddr);
}
else
{
printf("Pin alt mode failed!\n");
}
return 0;
}
/*
* OrangePi Digital write
*/
int OrangePi_digitalWrite(int pin, int value)
{
unsigned int bank = pin >> 5;
unsigned int index = pin - (bank << 5);
unsigned int phyaddr = 0;
unsigned int regval = 0;
unsigned int cru_phyaddr =0, gpio_phyaddr = 0, dr_phyaddr = 0;
unsigned int cru_val = 0;
unsigned int temp = 0;
unsigned int bit_enable = 0;
unsigned int offset;
switch (OrangePiModel)
{
case PI_MODEL_5: case PI_MODEL_5B:
case PI_MODEL_5_PLUS:
case PI_MODEL_900:
if(bank == 0){
dr_phyaddr = RK3588_GPIO0_BASE + RK3588_GPIO_SWPORT_DR_L_OFFSET + ((index / 16) << 2);
cru_phyaddr = RK3588_PMU1CRU_BASE + RK3588_PMU1CRU_GATE_CON5_OFFSET;
cru_val = 0xffff9fff;
}
else if(bank == 1){
dr_phyaddr = RK3588_GPIO1_BASE + RK3588_GPIO_SWPORT_DR_L_OFFSET + ((index / 16) << 2);
cru_phyaddr = RK3588_CRU_BASE + RK3588_CRU_GATE_CON16_OFFSET;
cru_val = 0xffff3fff;
}
else if(bank == 2){
dr_phyaddr = RK3588_GPIO2_BASE + RK3588_GPIO_SWPORT_DR_L_OFFSET + ((index / 16) << 2);
cru_phyaddr = RK3588_CRU_BASE + RK3588_CRU_GATE_CON17_OFFSET;
cru_val = 0xffffffc0;
}
else if(bank == 3){
dr_phyaddr = RK3588_GPIO3_BASE + RK3588_GPIO_SWPORT_DR_L_OFFSET + ((index / 16) << 2);
cru_phyaddr = RK3588_CRU_BASE + RK3588_CRU_GATE_CON17_OFFSET;
cru_val = 0xffffffc0;
}
else if(bank == 4){
dr_phyaddr = RK3588_GPIO4_BASE + RK3588_GPIO_SWPORT_DR_L_OFFSET + ((index / 16) << 2);
cru_phyaddr = RK3588_CRU_BASE + RK3588_CRU_GATE_CON17_OFFSET;
cru_val = 0xffffffc0;
}
/* Ignore unused gpio */
if (ORANGEPI_PIN_MASK[bank][index] != -1)
{
regval = readR(cru_phyaddr);
regval &= cru_val;
writeR(regval, cru_phyaddr);
if(0 == value)
{
regval = readR(dr_phyaddr);
regval |= 0xffff0000;
regval &= ~(1 << (index % 16));
writeR(regval, dr_phyaddr);
regval = readR(dr_phyaddr);
if (wiringPiDebug)
printf("LOW val set over reg val: 0x%x\n", regval);
}
else
{
regval = readR(dr_phyaddr);
regval |= 0xffff0000;
regval |= (1 << (index % 16));
writeR(regval, dr_phyaddr);
regval = readR(dr_phyaddr);
if (wiringPiDebug)
printf("HIGH val set over reg val: 0x%x\n", regval);
}
}
else
{
printf("Pin mode failed!\n");
}
break;
case PI_MODEL_800: case PI_MODEL_4_LTS:
case PI_MODEL_4: case PI_MODEL_RK3399:
if(bank == 1)
{
phyaddr = RK3399_GPIO1_BASE + RK3399_GPIO_SWPORTA_DR_OFFSET;
cru_phyaddr = RK3399_PMUCRU_BASE + RK3399_PMUCRU_CLKGATE_CON1_OFFSET;
}
else if(bank == 2)
{
phyaddr = RK3399_GPIO2_BASE + RK3399_GPIO_SWPORTA_DR_OFFSET;
cru_phyaddr = RK3399_CRU_BASE + RK3399_CRU_CLKGATE_CON31_OFFSET;
}
else if(bank == 4)
{
phyaddr = RK3399_GPIO4_BASE + RK3399_GPIO_SWPORTA_DR_OFFSET;
cru_phyaddr = RK3399_CRU_BASE + RK3399_CRU_CLKGATE_CON31_OFFSET;
}
/* Ignore unused gpio */
if (ORANGEPI_PIN_MASK[bank][index] != -1)
{
writeR(0xffff0180, cru_phyaddr);
regval = readR(phyaddr);
if (wiringPiDebug)
printf("befor write reg val: 0x%x,index:%d\n", regval, index);
if(0 == value)
{
regval &= ~(1 << index);
writeR(regval, phyaddr);
regval = readR(phyaddr);
if (wiringPiDebug)
printf("LOW val set over reg val: 0x%x\n", regval);
}
else
{
regval |= (1 << index);
writeR(regval, phyaddr);
regval = readR(phyaddr);
if (wiringPiDebug)
printf("HIGH val set over reg val: 0x%x\n", regval);
}
}
else
{
printf("Pin mode failed!\n");
}
break;
case PI_MODEL_R1_PLUS:
if(bank == 2)
{
phyaddr = RK3328_GPIO2_BASE + RK3328_GPIO_SWPORTA_DR_OFFSET;
cru_phyaddr = RK3328_CRU_BASE + RK3328_CRU_CLKGATE_CON16_OFFSET;
}
else if(bank == 3)
{
phyaddr = RK3328_GPIO3_BASE + RK3328_GPIO_SWPORTA_DR_OFFSET;
cru_phyaddr = RK3328_CRU_BASE + RK3328_CRU_CLKGATE_CON16_OFFSET;
}
/* Ignore unused gpio */
if (ORANGEPI_PIN_MASK[bank][index] != -1)
{
writeR(0xffff9877, cru_phyaddr);
regval = readR(phyaddr);
if (wiringPiDebug)
printf("befor write reg val: 0x%x,index:%d\n", regval, index);
if(0 == value)
{
regval &= ~(1 << index);
writeR(regval, phyaddr);
regval = readR(phyaddr);
if (wiringPiDebug)
printf("LOW val set over reg val: 0x%x\n", regval);
}
else
{
regval |= (1 << index);
writeR(regval, phyaddr);
regval = readR(phyaddr);
if (wiringPiDebug)
printf("HIGH val set over reg val: 0x%x\n", regval);
}
}
else
{
printf("Pin mode failed!\n");
}
break;
case PI_MODEL_CM4:
case PI_MODEL_3B:
if(bank == 0){
dr_phyaddr = RK3566_GPIO0_BASE + RK3566_GPIO_SWPORT_DR_L_OFFSET + ((index >> 4) << 2);
cru_phyaddr = RK3566_PMU_CRU_BASE + RK3566_PMUCRU_PMUGATE_CON01_OFFSET;
cru_val = ~((0x3 << 9) | (0x3 << (16 + 9)));
}
else{
dr_phyaddr = RK3566_GPIO1_BASE + ((bank - 1) << 16) + RK3566_GPIO_SWPORT_DR_L_OFFSET + ((index >> 4) << 2);
cru_phyaddr = RK3566_CRU_BASE + RK3566_CRU_GATE_CON31_OFFSET;
cru_val = ~((0xff << 2) | (0xff << (16 + 2)));
}
offset = index % 16;
bit_enable = 0x1 << (16 + offset);
/* Ignore unused gpio */
if (ORANGEPI_PIN_MASK[bank][index] != -1)
{
regval = readR(cru_phyaddr);
regval &= cru_val;
writeR(regval, cru_phyaddr);
regval = readR(dr_phyaddr);
if(wiringPiDebug)
printf("read val(%#x) from register[%#x]\n", regval, dr_phyaddr);;
regval |= bit_enable;
if(0 == value)
regval &= ~(1 << offset);
else
regval |= (1 << offset);
writeR(regval, dr_phyaddr);
if (wiringPiDebug)
printf("write val(%#x) to register[%#x]\n", regval, dr_phyaddr);
regval = readR(dr_phyaddr);
if (wiringPiDebug)
printf("set over reg val: 0x%x\n", regval);
}
else
{
printf("Pin mode failed!\n");
}
break;
default:
if (bank == 11)
{
phyaddr = sunxi_gpio_info_t.r_gpio_base_addr + sunxi_gpio_info_t.r_gpio_base_offset + 0x10;
}
else
{
phyaddr = sunxi_gpio_info_t.gpio_base_addr + sunxi_gpio_info_t.gpio_base_offset + (bank * 36) + 0x10;
}
/* Ignore unused gpio */
if (ORANGEPI_PIN_MASK[bank][index] != -1)
{
regval = readR(phyaddr);
if (wiringPiDebug)
printf("befor write reg val: 0x%x,index:%d\n", regval, index);
if(0 == value)
{
regval &= ~(1 << index);
writeR(regval, phyaddr);
regval = readR(phyaddr);
if (wiringPiDebug)
printf("LOW val set over reg val: 0x%x\n", regval);
}
else
{
regval |= (1 << index);
writeR(regval, phyaddr);
regval = readR(phyaddr);
if (wiringPiDebug)
printf("HIGH val set over reg val: 0x%x\n", regval);
}
}
else
{
printf("Pin mode failed!\n");
}
break;
}
return 0;
}
/*
* OrangePi Digital Read
*/
int OrangePi_digitalRead(int pin)
{
int bank = pin >> 5;
int index = pin - (bank << 5);
int val;
unsigned int phyaddr = 0;
switch (OrangePiModel)
{
case PI_MODEL_5: case PI_MODEL_5B:
case PI_MODEL_5_PLUS:
case PI_MODEL_900:
if(bank == 0)
phyaddr = RK3588_GPIO0_BASE + RK3588_GPIO_EXT_PORT_OFFSET;
else if(bank == 1)
phyaddr = RK3588_GPIO1_BASE + RK3588_GPIO_EXT_PORT_OFFSET;
else if(bank == 2)
phyaddr = RK3588_GPIO2_BASE + RK3588_GPIO_EXT_PORT_OFFSET;
else if(bank == 3)
phyaddr = RK3588_GPIO3_BASE + RK3588_GPIO_EXT_PORT_OFFSET;
else if(bank == 4)
phyaddr = RK3588_GPIO4_BASE + RK3588_GPIO_EXT_PORT_OFFSET;
break;
case PI_MODEL_800: case PI_MODEL_4_LTS:
case PI_MODEL_4: case PI_MODEL_RK3399:
if(bank == 1)
phyaddr = RK3399_GPIO1_BASE + RK3399_GPIO_EXT_PORTA_OFFSET;
else if(bank == 2)
phyaddr = RK3399_GPIO2_BASE + RK3399_GPIO_EXT_PORTA_OFFSET;
else if(bank == 4)
phyaddr = RK3399_GPIO4_BASE + RK3399_GPIO_EXT_PORTA_OFFSET;
break;
case PI_MODEL_R1_PLUS:
if(bank == 2)
phyaddr = RK3328_GPIO2_BASE + RK3328_GPIO_EXT_PORTA_OFFSET;
else if(bank == 3)
phyaddr = RK3328_GPIO3_BASE + RK3328_GPIO_EXT_PORTA_OFFSET;
break;
case PI_MODEL_CM4:
case PI_MODEL_3B:
if(bank == 0)
phyaddr = RK3566_GPIO0_BASE + RK3566_GPIO_EXT_PORT_OFFSET;
else
phyaddr = RK3566_GPIO1_BASE + ((bank - 1) << 16) + RK3566_GPIO_EXT_PORT_OFFSET;
break;
default:
if (bank == 11)
{
phyaddr = sunxi_gpio_info_t.r_gpio_base_addr + sunxi_gpio_info_t.r_gpio_base_offset + 0x10;
}
else
{
phyaddr = sunxi_gpio_info_t.gpio_base_addr + sunxi_gpio_info_t.gpio_base_offset + (bank * 36) + 0x10;
}
break;
}
if (ORANGEPI_PIN_MASK[bank][index] != -1)
{
val = readR(phyaddr);
val = val >> index;
val &= 1;
if (wiringPiDebug)
printf("Read reg val: 0x%#x, bank:%d, index:%d\n", val, bank, index);
return val;
}
return 0;
}
void OrangePi_set_gpio_pullUpDnControl (int pin, int pud)
{
unsigned int bank = pin >> 5;
unsigned int index = pin - (bank << 5);
unsigned int regval;
unsigned int offset;
unsigned int phyaddr = 0;
unsigned int bit_enable;
unsigned int bit_value = 0;
switch (OrangePiModel)
{
case PI_MODEL_5: case PI_MODEL_5B:
case PI_MODEL_5_PLUS:
case PI_MODEL_900:
if(bank == 0 && index < 12)
phyaddr = RK3588_PMU1_IOC_BASE + RK3588_PMU1_IOC_GPIO0A_P + ((index >> 3) << 2);
else if(bank == 0 && index > 11 && index < 31)
phyaddr = RK3588_PMU2_IOC_BASE + RK3588_PMU2_IOC_GPIO0B_P + (((index - 8) >> 3) << 2);
else if(bank == 1)
phyaddr = RK3588_VCCIO1_4_IOC_BASE + RK3588_VCCIO1_4_IOC_GPIO1A_P + ((index >> 3) << 2);
else if(bank < 4 || (bank == 4 && index > 17))
phyaddr = RK3588_VCCIO3_5_IOC_BASE + RK3588_VCCIO3_5_IOC_GPIO2A_P + (((pin - 64) >> 3) << 2);
else if(bank == 4 && index < 18)
phyaddr = RK3588_VCCIO6_IOC_BASE + RK3588_VCCIO6_IOC_GPIO4A_P + ((index >> 3) << 2);
offset = (index % 8) << 1;
bit_enable = 3 << ( 16 + offset);
/* */if (PUD_UP == pud)
bit_value = 3;
else if (PUD_DOWN == pud)
bit_value = 1;
else if (PUD_OFF == pud)
bit_value = 0;
break;
case PI_MODEL_800: case PI_MODEL_4_LTS:
case PI_MODEL_4: case PI_MODEL_RK3399:
/* */if ( bank > 1)
phyaddr = RK3399_GRF_BASE + RK3399_GRF_GPIO2_3_4_P_OFFSET + (((pin - 64) >> 3) << 2);
else if ( bank == 1 || pin < 16)
phyaddr = RK3399_PMUGRF_BASE + RK3399_PMUGRF_GPIO0_1_P_OFFSET + (((pin - 0) >> 3) << 2);
else {
printf("gpio0 Group c,d does not support PU/PD control\n");
return ;
}
//offset = index - ((index >> 3) << 3);
offset = (index % 8) << 1;
bit_enable = 3 << ( 16 + offset);
/* */if (PUD_UP == pud) {
if ( pin < 8 || (bank == 2 && index > 15)) /* gpio0a, gpio2c, gpio2d */
bit_value = 3;
else
bit_value = 1;
}
else if (PUD_DOWN == pud) {
if ( pin < 8 || (bank == 2 && index > 15)) /* gpio0a, gpio2c, gpio2d */
bit_value = 1;
else
bit_value = 2;
}
else if (PUD_OFF == pud) {
bit_value = 0;
}
break;
case PI_MODEL_CM4:
case PI_MODEL_3B:
if (bank == 0)
phyaddr = RK3566_PMU_GRF_BASE + RK3566_PMU_GRF_GPIO0A_P_OFFSET + (((pin - 0) >> 3) << 2);
else
phyaddr = RK3566_SYS_GRF_BASE + RK3566_GRF_GPIO1A_P_OFFSET + (((pin - 32) >> 3) << 2);
offset = (index % 8) << 1;
bit_enable = 3 << ( 16 + offset);
/* */if (PUD_UP == pud)
bit_value = 1;
else if (PUD_DOWN == pud)
bit_value = 2;
else if (PUD_OFF == pud)
bit_value = 0;
break;
default:
//int offset = ((index - ((index >> 4) << 4)) << 1);
offset = ((index % 16) << 1);
if (bank == 11)
phyaddr = sunxi_gpio_info_t.r_gpio_base_addr + sunxi_gpio_info_t.r_gpio_base_offset + ((index >> 4) << 2) + 0x1c;
else
phyaddr = sunxi_gpio_info_t.gpio_base_addr + sunxi_gpio_info_t.gpio_base_offset + (bank * 36) + ((index >> 4) << 2) + 0x1c;
bit_enable = 0;
/* */if (PUD_UP == pud)
bit_value = 1;
else if (PUD_DOWN == pud)
bit_value = 2;
else if (PUD_OFF == pud)
bit_value = 0;
break;
}
/* Ignore unused gpio */
if (ORANGEPI_PIN_MASK[bank][index] != -1)
{
if (wiringPiDebug)
printf("bank: %d, index: %d\n", bank, index);
regval = readR(phyaddr);
if (wiringPiDebug)
printf("read val(%#x) from register[%#x]\n", regval, phyaddr);
/* clear bit */
regval &= ~(3 << offset);
/* bit write enable*/
regval |= bit_enable;
/* set bit */
regval |= (bit_value & 3) << offset;
if (wiringPiDebug)
printf("write val(%#x) to register[%#x]\n", regval, phyaddr);
writeR(regval, phyaddr);
regval = readR(phyaddr);
if (wiringPiDebug)
printf("over reg val: %#x\n", regval);
}
}