MikuPi/MikuPi.c
2016-06-02 23:15:45 +08:00

271 lines
6.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>
#include "MikuPi.h"
const char *piModelNames [7] =
{
"Unknown",
"BPI-M1 ",
"BPI-R1 ",
"BPI-M2 ",
"BPI-M1+",
"BPI-M3 ",
"BPI-M2+",
} ;
int MikuPiDebug = FALSE;
static int *wPinToGpio ;
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
} ;
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) ;
}
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 (MikuPiDebug)
{
printf ("Hardware:%s\n",line) ;
printf ("processorCount:%d\n",processorCount) ;
}
}
else if (strstr(line,"sun7i") != NULL)
{
*model = PI_MODEL_M1;
*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) ;
}
}
void mikuPiSetup (void)
{
int fd;
unsigned int addr_start, addr_offset;
unsigned int PageSize, PageMask;
if (geteuid () != 0)
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_M2p)
{
wPinToGpio=wPinToGpioM2p;
}
if (model == PI_MODEL_M3)
{
wPinToGpio=wPinToGpioM3;
}
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 = (void *)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 = (void *)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)
{
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)
{
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);
}