2018/01/30

在 PC 編譯 wiringPi

參考了 raspberry pi 操控 gpio 的幾個方法
原本最想要的是直接存取,不知道哪裡沒弄好,gpio8 以上的行為怪怪的,只能 out,設定成 in 時,不管是拉 3.3v 還是 gnd 都是 low,所以改用 wiringpi 來處理。基於上篇,還是在 PC 上編譯 wiringPi 再拿去 raspberry pi 執行。

下載 wiringPi 原始碼

參考官網
git clone git://git.drogon.net/wiringPi

編譯主元件

需要編譯的內容是 wiringPi 和 devLib 這兩支,因為原先的 Makefile 內容是放在 raspberry pi 上編譯用的,所以需要做一些小小的調整,以便符合在 PC 上進行 cross compile。

wiringPi/Makefile 在 LIBS = 後面追加下列內容來蓋掉前面的設定
RPI_BASE := $(HOME)/rpi
CROSS := $(RPI_BASE)/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-
CC := $(CROSS)gcc
AR := $(CROSS)ar
RANLIB := $(CROSS)ranlib

devLib/Makefile 一樣在 LIBS = 後面追加
RPI_BASE := $(HOME)/rpi
CROSS := $(RPI_BASE)/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-
CC := $(CROSS)gcc
AR := $(CROSS)ar
RANLIB := $(CROSS)ranlib
INCLUDE += -I../wiringPi

原先的 Makefile 只編出 shared object,如果想要編出 static object,就在 all: 追加 $(STATIC) 就可以了。

編譯 gpio

因為是要先測試功能,所以使用 static object 的 wiringPi 元件,這樣就只需要把 gpio 程式放到 nfs 就能執行。

gpio/Makefile 還是在 LIBS = 後面追加
RPI_BASE := $(HOME)/rpi
CROSS := $(RPI_BASE)/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-
CC := $(CROSS)gcc
AR := $(CROSS)ar
RANLIB := $(CROSS)ranlib
INCLUDE += -I../wiringPi -I../devLib
LDFLAGS += -L../wiringPi -L../devLib

把 gpio 放到 nfs 上面,把 raspberrypi 的 v33 接到 gpio26 進行測試,改接gnd 再測,再改回 v33 再測,終於可以正常當 input 了。

安裝 shared object

如果有多支程式需要用到 wiringPi,做成 shared object 會比較理想。先把編譯好的 libwiringPi.so.2.44 和 libwiringPiDev.so.2.44 複製到 host 的 nfs 上,然後從 raspberrypi 上複製到 /lib 同時處理 symbolic link。
sudo cp /mnt/nfs/libwiringPi.so.2.44 /lib
sudo ln -s /lib/libwiringPi.so.2.44 /lib/libwiringPi.so
sudo cp /mnt/nfs/libwiringPiDev.so.2.44 /lib
sudo ln -s /lib/libwiringPiDev.so.2.44 /lib/libwiringPiDev.so



完成

基本上到此已經能完全操控 gpio,如果為了效能跟空間,可以參考 wiringPi 的 gpio,把不需要的拿掉,放到自己的程式內部。由於 gpio 需要 sudo 執行,基於安全上的考量,可能要改寫成 gpiod,再透過 ipc 跟 shared memory 去要求或進行控制。

2018/01/27

Raspberry Pi 開發環境建置

raspberry pi 可以直接使用 debian linux 發行套件,安裝 makefile 跟 gcc 就可以拿 source code 去編譯,但是編譯速度絕對不比高速 x86 桌機,遇到需要除錯的程式,還是在 x86 linux 上面編譯好再給 raspberry pi 跑會是一個比較省時間的做法。想法很簡單,就是在 x86 linux 上安裝 raspberry pi cross tools,然後透過 nfs 讓 raspberry pi 直接 mount 去執行。

我目前使用的 x86 linux 是 debian 9 amd64,所以以下內容將以此為基準,使用 debian based 的發行套件應該都能直接套用,其他發行套件可能要做些修改。

安裝 cross tools


編譯環境不該使用 root,所以請用一般 user 登入,把 toolchain 放在 home

aimwang@debian:~$ mkdir rpi
aimwang$debian:~$ cd rpi
aimwang@debian:~/rpi$ git clone https://github.com/raspberrypi/tools.git

安裝並設定 nfs server


aimwang@debian:~$ sudo apt-get install nfs-kernel-server nfs-common
aimwang@debian:~$ sudo mkdir /srv/nfs
aimwang@debian:~$ sudo chmod 777 /srv/nfs

/etc/exports 最後增加 (IP 根據自己的環境改)
/srv/nfs 192.168.22.*(rw,sync,no_subtree_check,no_root_squash)

重新啟動 nfs server
aimwang@debian:~$ sudo /etc/init.d/nfs-kernel-server restart

準備編譯 hello world 等一下要透過 nfs 餵給 raspberry pi 執行
Makefile
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
ROOT_PATH := $(PWD)
RPI_BASE := $(HOME)/rpi
NFS_PATH := /srv/nfs
CROSS := $(RPI_BASE)/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-
CC := $(CROSS)gcc

all: hello nfs

nfs:
 @cp -f hello $(NFS_PATH)/.

hello:
 @$(CC) $(CFLAGS) -o hello hello.c

clean:
 @rm -f hello
hello.c
1
2
3
4
5
6
7
8
#include <stdio.h>
#include <stdlib.h>

void main (void)
{
 printf ("Hello world!\n");
 exit (0);
}

編譯啦
aimwang@debian:~/project/rpi/hello$ make

Raspberry Pi mount nfs 及執行

pi@raspberrypi:~ $ sudo mount -t nfs 192.168.22.200:/srv/nfs /mnt/nfs
pi@raspberrypi:~ $ /mnt/nfs/hello
Hello world!

完成

2016/08/10

LeetCode 65. Valid Number

Validate if a given string is numeric.
Some examples:
"0" => true
" 0.1 " => true
"abc" => false
"1 a" => false
"2e10" => true

解法真是非常呆,不過直覺也不是壞事
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
bool isNumber(char* s) {
    int len=strlen(s);
    int i;
    bool havedot=false;
    bool havee=false;
    bool havespace=false;
    bool havenum=false;
    bool havesymbol=false;

    for(i=0; i<len; i++)
    {
        if(s[i]<0x30 || s[i]>0x39)
        {
            if(' ' == s[i])
            {
                if(havenum || havee || havedot || havesymbol)
                {
                    havespace = true;
                }
            }
            else if('.' == s[i])
            {
                if(havee || havedot || havespace)
                {
                    return false;
                }
                else
                {
                    havedot = true;
                }
            }
            else if('e' == s[i])
            {
                if(havee || !havenum)
                {
                    return false;
                }
                else
                {
                    havee = true;
                    havenum = false;
                    havesymbol = false;
                }
            }
            else if('+' == s[i] || '-' == s[i])
            {
                if (havee)
                {
                    if (havesymbol || havenum)
                    {
                        return false;
                    }
                }
                else
                {
                    if (havesymbol || havenum || havedot)
                    {
                        return false;
                    }
                }
                havesymbol = true;
            }
            else
            {
                return false;
            }
        }
        else
        {
            if(havespace)
            {
                return false;
            }
            havenum = true;
        }
    }
    return havenum;
}

2016/07/14

leetcode Counting Bits

leetcode Counting Bits

Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calculate the number of 1's in their binary representation and return them as an array.
Example:
For num = 5 you should return [0,1,1,2,1,2].
Follow up:
  • It is very easy to come up with a solution with run time O(n*sizeof(integer)). But can you do it in linear time O(n) /possibly in a single pass?
  • Space complexity should be O(n).
  • Can you do it like a boss? Do it without using any builtin function like __builtin_popcount in c++ or in any other language.
給一個正整數,輸出 0 ≤ i ≤ num 的二進制數值 1 的數量,明明很簡單的題目。但是後面的條件說要在 O(n) 解決掉,而不能用到 O(n * sizeof(integer)),所以直覺的寫個 function 用 shift 去計算個別數值 1 的數量並不能滿足條件。只好回歸二進制的特性找線索。
二進制每次+1的時候,就是最後一位 0 變 1 或 1 變 0,每個位數從 1 變成 0 的時候,就往前進一位。
所以 1,2,4,8,16,32,64...在進位之後,低位數就開始循環。列個清單來驗證一下這樣的推論

十進制二進制1 的數量
00000 00000
10000 00011
20000 00101
30000 00112
40000 01001
50000 01012
60000 01102
70000 01113
80000 10001
90000 10012
100000 10102
110000 10113
120000 11002
130000 11013
140000 11103
150000 11114
從表格已經可以看出 1 的數量在 1, 2, 4, 8 的時候,就是複製前面 1, 2, 4, 8 個結果,並將新複製的結果 + 1,也就是重複前面的循環但是要再加上本身進位所增加的那一個。

十進制複製輸出結果
0
0
10 00 1
201 0101 12
40112 01120112 1223
801121223 0112122301121223 12232334
確定這個方法可行,開始動手寫程式啦
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int* countBits(int num, int* returnSize) {
    int s, ss, i;
    *returnSize = num+1;
    int * retvals = malloc(sizeof(int) * (num+1));
    memset(retvals, 0, sizeof(int));

    s=1;
    retvals[0] = 0;
    while(s <= num)
    {
 if(s*2 > num)
 {
     ss = num - s + 1;
 }
 else
 {
     ss = s;
 }
 memcpy(retvals + s, retvals, sizeof(int) * ss);
 for(i=0;i<ss;i++)
 {
     retvals[s+i]++;
 }
 s = s<<1;
   }
    return retvals;
}

void main(int argc, char *argv[])
{
 int * resarr;
 int rescnt, i;

 if(2 != argc)
 {
  printf("What?\n");
  return;
 }
 
 if(atoi(argv[1]))
 {
  resarr = countBits(atoi(argv[1]), &rescnt);
  printf("[%d", resarr[0]);
  for(i=1; i<rescnt; i++)
  {
   printf(",%d", resarr[i]);
  }
  printf("]\n");
 }
 else
 {
  printf("Oh! Oh!\n");
 }
}

2016/05/19

利用 ffmpeg 將 truehd 抽出 ac3 或是轉成 dts

擴大機還停留在上一個世代,無法解 truehd,只好祭出 ffmpeg

如果 truehd 有 ac3 core
        ffmpeg -i "src.thd" -c:a copy "dst.ac3"

如果沒有,乾脆轉成 dts
        ffmpeg -i "src.thd" -c:a dts -strict -2 "dst.dts"

最後再用 mkvtoolnix 或是 tsMuxeR 打包回去

話說上一世代的擴大機解 truehd 到現在還沒有成功過,而 DTS-MA 卻沒有失敗過,擴大機 RIP 換新的之前,還是只挑有 DTS-MA 的就好。