音樂播放器之 CD 轉成 mp3《三》下‧中

雖說作者揣測︰

或許因為 Adafruit 的『 PiTFT 3.5″觸控螢幕』已經使用了兩個 SPI 裝置,為了避免可能的『衝突』,所以當『驅動程式』 fbtft_device 載入時,它就將系統原始的『 spidev0.0 』以及『 spidev0.1 』裝置給刪除了。

然而考之於『 fbtft_device 』的開發網頁『驅動程式』載入說明,證明作者的揣想『錯誤sudo modprobe fbtft_device name=adafruit22

dmesg

fbtft_device: SPI devices registered:
fbtft_device: spidev spi0.0 500kHz 8 bits mode=0x00
fbtft_device: spidev spi0.1 500kHz 8 bits mode=0x00
fbtft_device: ‘fb’ Platform devices registered:
fbtft_device: bcm2708_fb id=-1 pdata? no
fbtft_device: Deleting spi0.0
fbtft_device: GPIOS used by ‘adafruit22’:
fbtft_device: ‘reset’ = GPIO25
fbtft_device: ‘led’ = GPIO23
fbtft_device: SPI devices registered:
fbtft_device: spidev spi0.1 500kHz 8 bits mode=0x00
fbtft_device: fb_hx8340bn spi0.0 32000kHz 8 bits mode=0x00
graphics fb1: fb_hx8340bn frame buffer, 176×220, 75 KiB video memory, 16 KiB buffer memory, fps=20, spi0.0 at 32 MHz

1.  First it lists all SPI devices and platform devices with a name containing ‘fb’ (framebuffer) that was registered before the module was loaded.

2. Then it deletes the device connected to spi0.0 (spidev) so we can register a new one.

3. Then it tells which GPIOs that is associated with this display.

4. Then it lists which SPI devices that are currently registered (spi0.0 means SPI busnum.chipselect).

5. And lastly the driver is loaded.

再從『 fbtft Performance 』上考察,現今的『驅動程式』預設的是高速的『直接記憶體存取DMA Direct Memory Access。假使就 Adafruit 文件的 FAQ 【 page 43 】來看,這個 『驅動程式』可以『超頻』 overclock。Adafruit 版的『觸控輸入』與『螢幕輸出』之『原始碼』 Source Code 是放在『 adafruit-raspberrypi-linux forked from raspberrypi/linux 』這裡,有興趣的讀者可以研究看看。

如果仔細讀過 Adafruit 的文件,我們當然可以知道如何『測試』與『校正』觸控螢幕︰

page 25裝置檢查
ls -l /dev/input/touchscreen

page 26裝置測試
sudo evtest /dev/input/touchscreen

page 28裝置校正
sudo TSLIB_FBDEVICE=/dev/fb1 TSLIB_TSDEVICE=/dev/input/touchscreen ts_calibrate

page 29裝置操作實測
sudo TSLIB_FBDEVICE=/dev/fb1 TSLIB_TSDEVICE=/dev/input/touchscreen ts_test

ResistiveTouchscreen
電阻式觸控輸入

TouchScreen_projective_capacitive.svg
電容式觸控輸入

tscalibration
顯示器區域 (x, y) 與觸控輸入區域 (x^{\prime}, y^{\prime}) 不同,所以才需要校正。

假使我們略為了解觸控螢幕的『設計』與『工作原理』,就可以知道『理想』的點對點『平面觸控』裝置,回報『觸控點』的幾何『座標(x^{\prime}, y^{\prime}) ,它在『觸控區域』內應該是『線性的』。因此從幾何『平移』與『旋轉』的角度來看,這樣的『校正』只需要『三個點』。然而『實際裝置』通常只能足夠『線性』,而且『 X 軸』與『 Y 軸』的『解析度』未必相同,因而一般常會用『多點校正』來減少使用上之『座標誤差』。

由於在『製造過程』中所可能引起的『區域誤差』,這個『校正程序』常常是避免不了的。雖然 Adafruit 文件說『 PiTFT 3.5″觸控螢幕』已經校正過,也只能假設是使用『設計』時的『校正數據』來做的了。所以是否需要再次校正的問題,應當看『使用者界面』的規格要求而定。假使以『手指』或『手勢』的操作界面來講,就作者所知 Adafruit 的『原始校正』足以作為『基礎』,即使說需要更『精細的控制』,也許在那個『基礎』上,再寫一個應用所需之『校正程序』比較方便的吧!

由於作者考慮使用『 pygame 』來設計簡易的『使用者界面』,於是先做了一些在『 PiTFT 3.5″觸控螢幕』上如何使用『 pygame 』的『驗證』,下面的小程式修改自『 fbtft pygame 』,讀者可以用『 ssh 』指令連上『原型機』後,以

sudo python pygametest.py

跑跑看,當觸碰螢幕時,你的『 ssh 』連線終端機上會顯示︰

Pos: 322×129
Pos: 369×231
Pos: 208×259

# Source: http://inventwithpython.com/drawing.py

import pygame, sys, os
from pygame.locals import *
os.environ[“SDL_FBDEV”] = “/dev/fb1”
# Uncomment if you have a touch panel and find the X value for your device
os.environ[“SDL_MOUSEDRV”] = “TSLIB”
os.environ[“SDL_MOUSEDEV”] = “/dev/input/touchscreen”

pygame.init()

# set up the window
DISPLAYSURF = pygame.display.set_mode((480, 320), 0, 32)
pygame.display.set_caption(‘Drawing’)

# set up the colors
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = ( 0, 255, 0)
BLUE = ( 0, 0, 255)

# draw on the surface object
DISPLAYSURF.fill(WHITE)
pygame.draw.polygon(DISPLAYSURF, GREEN, ((16, 0), (111, 106), (36, 277), (56, 27), (0, 106)))
pygame.draw.line(DISPLAYSURF, BLUE, (60, 60), (120, 60), 4)
pygame.draw.line(DISPLAYSURF, BLUE, (120, 60), (60, 120))
pygame.draw.line(DISPLAYSURF, BLUE, (60, 120), (120, 120), 4)
pygame.draw.circle(DISPLAYSURF, BLUE, (40, 50), 20, 0)
pygame.draw.ellipse(DISPLAYSURF, RED, (110, 200, 40, 80), 1)
box = pygame.draw.rect(DISPLAYSURF, RED, (100, 150, 100, 50))

pixObj = pygame.PixelArray(DISPLAYSURF)
pixObj[120][144] = BLACK
pixObj[122][146] = BLACK
pixObj[124][148] = BLACK
pixObj[126][158] = BLACK
pixObj[126][158] = BLACK
del pixObj

# run the game loop
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
print(“Pos: %sx%s\n” % pygame.mouse.get_pos())
if box.collidepoint(pygame.mouse.get_pos()):
pygame.quit()
sys.exit()
pygame.display.update()

 

奇怪!!為什麼一定要冠以『 sudo 』的呢??

 

─── 待續