數字電視—DTV對我們來說早已不是一個新東西,在車載電子上DTV大多是以模塊的形式獨立存在的,是可配的。在車載的市場上,客戶的需求是多種多樣的,如果把DTV也做到車載導航主PCB上去,還是不靈活,不要DTV的就得是不同的PCB板,這對於售後維護、開發都不是一個好辦法。
DTV在家裡,大家一般都是通過遙控器來操作,當然現在有些android的電視盒子可以通過手機來控制,有個泰捷遙控器的apk,通過同一個wifi熱點的電視盒,可以用手機來操作也挺方便。但是在車上,怎麼去操作DTV呢?在小車上,一般空間都是比較狹窄的,使用遙控器是很不方便的,因此我們需要把控制做到導航主控上去。在遙控器的協議中,NEC協議是使用得最普遍的,下面就以NEC協議為例學習一下使用GPIO模擬IR按鍵消息的方法。
NEC的一條按鍵信息由數據頭、客戶碼、客戶碼反碼、鍵值、鍵值反碼、停止位組成,在此不介紹重復碼。數據頭是一個9ms + 4.5ms的高低組合,後面就是緊跟4個字節的數值,也就是32bit的0、1組合。IR口的gpio口一般是默認是高電平的,解碼驅動大多都是采用下降沿觸發中斷。在此我們主要是要編出一串IR脈沖。組合這一串脈沖的代碼如下:
gpio_write_one_pin_value(simulate_ir_gpio_hdle, 0, "simulate_ir_gpio"); Delay10us(900);// 9ms gpio_write_one_pin_value(simulate_ir_gpio_hdle, 1, "simulate_ir_gpio"); Delay10us(450);// 4.5ms //IR Customer Code: 0x807f , NEC IR protocol SendByteData(0x80); // DVB HEADER_CODE0 SendByteData(0x7F); // DVB HEADER_CODE1 SendByteData(IRData); SendByteData(~IRData); gpio_write_one_pin_value(simulate_ir_gpio_hdle, 0, "simulate_ir_gpio"); Delay10us(56); gpio_write_one_pin_value(simulate_ir_gpio_hdle, 1, "simulate_ir_gpio");
在此有一個問題,就是編這一段脈沖需要50ms以上,標准的一個完整的消息大概是108ms-110ms。這就要求我們在發送4字節數據以及停止碼中間不能被任務調度,因為任務一調度的話編的碼的寬度就會有很大出入,接收端解析就會認為是一個錯誤的遙控值。那我們怎麼去盡力保證呢?在linux中有一個spinlock,也就是自旋鎖,一旦獲得這個鎖就可以保證當然執行的進程不被調度搶占。因此在上面的這段代碼前後加上鎖以及取消鎖操作,筆者在實際操作中,在近百次的操作中,發送IR鍵值的成功率是百分之百。加鎖的相關代碼如下:
#include <linux/spinlock.h> spinlock_t lock; spin_lock_init(&lock); spin_lock(&lock); ////////////////for your process////////////////// spin_unlock(&lock);
在android上層,可以通過ioctl來控制,向上層可以封裝在service裡面供上層應用使用。