413 lines
9.0 KiB
C++
Executable File
413 lines
9.0 KiB
C++
Executable File
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include <sys/mman.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
|
|
/*
|
|
* MikuPi.cpp:
|
|
*
|
|
* Welcome to MikuQ.com! MikuDuino for BananaPi
|
|
*
|
|
* by MikuQ(i@mikuq.com)
|
|
*
|
|
* https://github.com/bpiq/MikuPi
|
|
*
|
|
*/
|
|
|
|
#include "MikuPi.h"
|
|
|
|
char *i2cDevice;
|
|
|
|
int hasRoot = TRUE;
|
|
|
|
const char *i2cDevices[3] =
|
|
{
|
|
"/dev/i2c-0",
|
|
"/dev/i2c-1",
|
|
"/dev/i2c-2"
|
|
} ;
|
|
|
|
const char *piModelNames [9] =
|
|
{
|
|
"Unknown",
|
|
"BPI-M1",
|
|
"BPI-R1",
|
|
"BPI-M2",
|
|
"BPI-M1+",
|
|
"BPI-M3",
|
|
"BPI-M2+",
|
|
"BPI-M2U",
|
|
} ;
|
|
|
|
const char *piModelFullNames [9] =
|
|
{
|
|
"Unknown",
|
|
"BananaPi-M1",
|
|
"BananaPi-R1",
|
|
"BananaPi-M2",
|
|
"BananaPi-M1+",
|
|
"BananaPi-M3",
|
|
"BananaPi-M2+",
|
|
"BananaPi-M2U",
|
|
} ;
|
|
|
|
int MikuPiDebug = FALSE;
|
|
|
|
static int *wPinToGpio ;
|
|
|
|
static int wPinToGpioM1p [32] =
|
|
{
|
|
275,226,274,273, 244,245,272,259,
|
|
53,52,266,270, 268,269,267,224,
|
|
225,-1,-1,-1, -1,37,38,39,
|
|
40,35,44,277, 276,45,257,256
|
|
} ;
|
|
|
|
static int wPinToGpioM2 [32] =
|
|
{
|
|
199,234,198,201, 235,236,200,233,
|
|
243,242,205, 204, 207,208,206,132,
|
|
133,-1,-1, -1, -1,32,33,34,
|
|
35,36,39,134, 135,290,38,37
|
|
} ;
|
|
|
|
static int wPinToGpioM2p [32] =
|
|
{
|
|
1,16,0,3, 15,68,2,6,
|
|
12,11,67,71, 64,65,66,13,
|
|
14,-1,-1,-1, -1,7,8,9,
|
|
10,17,354,356, 21,20,19,18
|
|
} ;
|
|
|
|
static int wPinToGpioM3 [32] =
|
|
{
|
|
68,35,71,81, 34,360,361,362,
|
|
229,228,67,234, 64,65,66,32,
|
|
33,-1,-1,-1, -1,82,202,203,
|
|
204,132,205,133, 146,147,227,226
|
|
} ;
|
|
|
|
static int wPinToGpioM2u [32] =
|
|
{
|
|
276,273,277,249, 272,250,251,35,
|
|
53,52,87,248, 64,65,66,274,
|
|
275,-1,-1,-1, -1,224,225,226,
|
|
227,228,116,231, 230,229,257,256
|
|
} ;
|
|
|
|
const int bPinTowPin[41] =
|
|
{
|
|
-1, // 0
|
|
-1, -1, // 1, 2
|
|
8, -1, //3, 4
|
|
9, -1, //5, 6
|
|
7, 15, //7, 8
|
|
-1, 16, //9,10
|
|
0, 1, //11,12
|
|
2, -1, //13,14
|
|
3, 4, //15,16
|
|
-1, 5, //17,18
|
|
12, -1, //19,20
|
|
13, 6, //21,22
|
|
14, 10, //23, 24
|
|
-1, 11, // 25, 26
|
|
|
|
30, 31, //27, 28
|
|
21, -1, //29, 30
|
|
22, 26, //31, 32
|
|
23, -1, //33, 34
|
|
24, 27, //35, 36
|
|
25, 28, //37, 38
|
|
-1, 29, //39, 40
|
|
} ;
|
|
|
|
unsigned int SUNXI_PIO_BASE = 0;
|
|
unsigned int SUNXI_PIO_LM_BASE = 0;
|
|
static volatile long int *gpio_map = NULL;
|
|
|
|
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) ;
|
|
}
|
|
|
|
static void piBoardRevOops (const char *why)
|
|
{
|
|
//fprintf (stderr, "piBoardRev: Unable to determine board revision from /proc/cpuinfo\n") ;
|
|
fprintf (stderr, " -> %s\n", why) ;
|
|
fprintf (stderr, " -> You may want to check:\n") ;
|
|
fprintf (stderr, " -> http://MikuQ.com\n") ;
|
|
exit (EXIT_FAILURE) ;
|
|
}
|
|
|
|
int piCpuTemp(char* temp)
|
|
{
|
|
int model, mem;
|
|
int iTemp=-300000;
|
|
strcpy(temp,"none");
|
|
piBoardId (&model, &mem);
|
|
FILE *tempFd;
|
|
switch(model)
|
|
{
|
|
case PI_MODEL_UNKNOWN:
|
|
case PI_MODEL_M2:
|
|
break;
|
|
case PI_MODEL_M1:
|
|
case PI_MODEL_M1p:
|
|
case PI_MODEL_R1:
|
|
if ((tempFd = fopen ("/sys/devices/platform/sunxi-i2c.0/i2c-0/0-0034/temp1_input", "r")) == NULL)
|
|
{
|
|
printf("Unable to open /sys/devices/platform/sunxi-i2c.0/i2c-0/0-0034/temp1_input\n");
|
|
break;
|
|
}
|
|
while (fgets (temp, 20, tempFd) != NULL)
|
|
{
|
|
iTemp=atoi(temp);
|
|
float f=iTemp/1000.0f;
|
|
sprintf(temp,"%.1f",f);
|
|
break;
|
|
}
|
|
fclose(tempFd);
|
|
break;
|
|
default:
|
|
if ((tempFd = fopen ("/sys/class/thermal/thermal_zone0/temp", "r")) == NULL)
|
|
{
|
|
printf("Unable to open /sys/devices/platform/sunxi-i2c.0/i2c-0/0-0034/temp1_input\n");
|
|
break;
|
|
}
|
|
while (fgets (temp, 20, tempFd) != NULL)
|
|
{
|
|
iTemp=atoi(temp)*1000;
|
|
float f=iTemp/1000.0f;
|
|
sprintf(temp,"%.0f",f);
|
|
break;
|
|
}
|
|
fclose(tempFd);
|
|
}
|
|
return iTemp;
|
|
}
|
|
|
|
void piBoardId(int *model, int *mem)
|
|
{
|
|
FILE *cpuFd ;
|
|
char line [120] ;
|
|
char *d;
|
|
|
|
int processorCount=0;
|
|
|
|
if ((cpuFd = fopen ("/proc/cpuinfo", "r")) == NULL)
|
|
piBoardRevOops ("Unable to open /proc/cpuinfo") ;
|
|
while (fgets (line, 120, cpuFd) != NULL)
|
|
{
|
|
if (strncmp (line, "processor", 9) == 0)
|
|
processorCount++;
|
|
if (strncmp (line, "Hardware", 8) == 0)
|
|
break;
|
|
}
|
|
|
|
fclose (cpuFd) ;
|
|
if (strncmp (line, "Hardware", 8) != 0)
|
|
piBoardRevOops ("No \"Hardware\" line") ;
|
|
|
|
for (d = &line [strlen (line) - 1] ; (*d == '\n') || (*d == '\r') ; --d)
|
|
*d = 0 ;
|
|
if (MikuPiDebug)
|
|
printf ("piboardRev: Hardware string: %s\n", line) ;
|
|
|
|
if (strstr(line,"sun8i") != NULL)
|
|
{
|
|
if (processorCount==4)
|
|
{
|
|
//H3-M2p
|
|
*model = PI_MODEL_M2p;
|
|
*mem = 1024;
|
|
}
|
|
if (processorCount==8)
|
|
{
|
|
//A83T-M3
|
|
*model = PI_MODEL_M3;
|
|
*mem = 2048;
|
|
}
|
|
if (strstr(line,"sun8iw11p1") != NULL)
|
|
{
|
|
//R40-M2U
|
|
*model = PI_MODEL_M2u;
|
|
*mem = 2048;
|
|
}
|
|
if (MikuPiDebug)
|
|
{
|
|
printf ("Hardware:%s\n",line) ;
|
|
printf ("processorCount:%d\n",processorCount) ;
|
|
}
|
|
}
|
|
else if (strstr(line,"sun7i") != NULL)
|
|
{
|
|
//how to? M1\M1+\R1?
|
|
*model = PI_MODEL_M1p;
|
|
*mem = 1024;
|
|
}
|
|
else if (strstr(line,"sun6i") != NULL)
|
|
{
|
|
*model = PI_MODEL_M2;
|
|
*mem = 1024;
|
|
}
|
|
else
|
|
{
|
|
*model = PI_MODEL_UNKNOWN;
|
|
*mem = 0;
|
|
if (MikuPiDebug)
|
|
printf ("Hardware:%s\n",line) ;
|
|
}
|
|
}
|
|
|
|
void sayHello()
|
|
{
|
|
int model, mem;
|
|
printf("Welcome to MikuQ.com! MikuDuino for BananaPi version: %s\n", VERSION);
|
|
piBoardId (&model, &mem);
|
|
|
|
if (model == PI_MODEL_UNKNOWN)
|
|
{
|
|
printf ("Your Pi has an unknown model type. Please report this to\n") ;
|
|
printf (" i@mikuq.com\n") ;
|
|
printf ("with a copy of your /proc/cpuinfo if possible\n") ;
|
|
}
|
|
else
|
|
{
|
|
printf ("BananaPi Details:\n") ;
|
|
printf (" Type: %s, Memory: %dMB\n", piModelNames [model], mem) ;
|
|
printf (" I2C Device: %s\n",i2cDevice) ;
|
|
}
|
|
}
|
|
|
|
void mikuPiSetup (void)
|
|
{
|
|
int fd;
|
|
unsigned int addr_start, addr_offset;
|
|
unsigned int PageSize, PageMask;
|
|
|
|
if (geteuid () != 0) {
|
|
hasRoot = FALSE;
|
|
//piBoardRevOops("MikuPiSetup: Must be root. (Did you forget sudo?)");
|
|
}
|
|
|
|
int model, mem;
|
|
piBoardId (&model, &mem);
|
|
if (model == PI_MODEL_UNKNOWN)
|
|
{
|
|
printf ("Your Pi has an unknown model type. Please report this to\n") ;
|
|
printf (" i@mikuq.com\n") ;
|
|
piBoardRevOops ("with a copy of your /proc/cpuinfo if possible") ;
|
|
}
|
|
|
|
if (model == PI_MODEL_M1p) {
|
|
wPinToGpio=wPinToGpioM1p;
|
|
i2cDevice=(char *)i2cDevices[2];
|
|
}
|
|
if (model == PI_MODEL_M2) {
|
|
wPinToGpio=wPinToGpioM2;
|
|
i2cDevice=(char *)i2cDevices[2];
|
|
}
|
|
if (model == PI_MODEL_M2p) {
|
|
wPinToGpio=wPinToGpioM2p;
|
|
i2cDevice=(char *)i2cDevices[0];
|
|
}
|
|
if (model == PI_MODEL_M2u) {
|
|
wPinToGpio=wPinToGpioM2u;
|
|
i2cDevice=(char *)i2cDevices[2];
|
|
}
|
|
if (model == PI_MODEL_M3) {
|
|
wPinToGpio=wPinToGpioM3;
|
|
i2cDevice=(char *)i2cDevices[2];
|
|
}
|
|
|
|
if (hasRoot)
|
|
{
|
|
fd = open("/dev/mem", O_RDWR);
|
|
|
|
PageSize = sysconf(_SC_PAGESIZE);
|
|
PageMask = (~(PageSize-1));
|
|
|
|
addr_start = SW_PORTC_IO_BASE & PageMask;
|
|
addr_offset = SW_PORTC_IO_BASE & ~PageMask;
|
|
gpio_map = (volatile long int*)mmap(0, PageSize*2, PROT_READ|PROT_WRITE, MAP_SHARED, fd, addr_start);
|
|
|
|
SUNXI_PIO_BASE = (unsigned int)gpio_map;
|
|
SUNXI_PIO_BASE += addr_offset;
|
|
|
|
addr_start = SW_PORTL_IO_BASE & PageMask;
|
|
addr_offset = SW_PORTL_IO_BASE & ~PageMask;
|
|
gpio_map = (volatile long int*)mmap(0, PageSize*2, PROT_READ|PROT_WRITE, MAP_SHARED, fd, addr_start);
|
|
|
|
SUNXI_PIO_LM_BASE = (unsigned int)gpio_map;
|
|
SUNXI_PIO_LM_BASE += addr_offset;
|
|
|
|
close(fd);
|
|
}
|
|
}
|
|
|
|
void pinMode(int pin, int mode)
|
|
{
|
|
if (!hasRoot)
|
|
{
|
|
printf ("Warning! If u want control GPIO. Must be root. (Did you forget sudo?)\n") ;
|
|
return;
|
|
}
|
|
pin=wPinToGpio[pin];
|
|
unsigned int val = mode;
|
|
unsigned int cfg;
|
|
unsigned int bank = GPIO_BANK(pin);
|
|
unsigned int index = GPIO_CFG_INDEX(pin);
|
|
unsigned int offset = GPIO_CFG_OFFSET(pin);
|
|
|
|
if(SUNXI_PIO_BASE == 0)
|
|
return;
|
|
|
|
struct sunxi_gpio *pio;
|
|
if(bank>10)
|
|
pio = &((struct sunxi_gpio_reg *)SUNXI_PIO_LM_BASE)->gpio_bank[bank-11];
|
|
else
|
|
pio = &((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[bank];
|
|
|
|
cfg = *(&pio->cfg[0] + index);
|
|
cfg &= ~(0xf << offset);
|
|
cfg |= val << offset;
|
|
|
|
*(&pio->cfg[0] + index) = cfg;
|
|
}
|
|
|
|
void digitalWrite(int pin, int value)
|
|
{
|
|
if (!hasRoot)
|
|
{
|
|
printf ("Warning! If u want control GPIO. Must be root. (Did you forget sudo?)\n") ;
|
|
return;
|
|
}
|
|
pin=wPinToGpio[pin];
|
|
unsigned int val = value;
|
|
unsigned int bank = GPIO_BANK(pin);
|
|
unsigned int num = GPIO_NUM(pin);
|
|
|
|
if(SUNXI_PIO_BASE == 0)
|
|
return;
|
|
|
|
struct sunxi_gpio *pio;
|
|
if(bank>10)
|
|
pio = &((struct sunxi_gpio_reg *)SUNXI_PIO_LM_BASE)->gpio_bank[bank-11];
|
|
else
|
|
pio = &((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[bank];
|
|
|
|
if(val)
|
|
*(&pio->dat) |= 1 << num;
|
|
else
|
|
*(&pio->dat) &= ~(1 << num);
|
|
}
|
|
|