2023年7月9日星期日

Sharp LC-40SF466T 電視,開不了機,綠燈恆亮,可以試試看這個方法

 今天電視突然無預警的沒有畫面,關閉電源再度開啟後,電視綠燈恆亮

 按電源按鈕開啟電視,都沒有反應,這台電視才使用4年,想說會不會是主機板的電源管理部分出了問題,於是上網找了一些資訊

  這台電視,只有一個主機板 + 邏輯版,主機板的部分,是三合一板 (),把電源板與主機板合在一起,然後找到下面方法,試了之後,還真的讓我的螢幕亮了起來

  接著按下電源按鈕之後,就可以讓電視回到紅燈狀態,資訊與步驟如下:


夏普液晶電視的很多機型主板有5次記憶保護,當背光或者電源發生故障時,只要開機5次以上,就形成保護記憶,解除方法步驟如下

Step1: 按住 信號源鍵(INPUT/AV/TV) 音量減鍵,同時拔掉電源插頭

Step2: 之前按住的鍵,到這步驟都不要放開,再度插上電源插頭


我完成以上兩個步驟後,電視就恢復正常了~ 不用花大錢了 :D

2023/11/09 更新最新狀況,後來還是遇到綠燈恆亮問題,上蝦皮買了一塊二手主機板 $1200
自行拆開更換後,正常服役中~

2023年7月3日星期一

[Linux Audio] 使用ALSA API 實作amixer command: amixer -c0 set i2s_clock on,Bug 修正

 之前有寫了一篇 ALSA API 實作amixer command:  amixer -c0 set i2s_clock on

 後來發現,有兩個 Bug 需要被修正,分別如下:

 1. 第一次如果使用 i2s_clock off,會造成 kernel 端出現 core_dump 錯誤,導致執行時間會變很長 (原本大概只需要 20ms,結果時間拉長到 200ms)

 2. 發現這個上層的API程式,呼叫Linux Kernel 層,去triger I2S,出現 non-blocking的現象(application 呼叫底層程式,但沒有等待底層做完,就直接繼續執行application層的事情)


因此加入底下一些程式,來解決這兩個問題 (用不同顏色標出)

#include <stdio.h>

#include <alsa/asoundlib.h>


int set_mixer_onoff(const char *control_name,
                            int option)
{
    const char *device = "hw:0";  // 音訊設備的名稱或識別符號
    //const char *control_name = "i2s_clock";  // 控制元素的名稱, 由API參數帶入

    snd_ctl_t *handle;
    snd_ctl_elem_id_t *elem_id;
    snd_ctl_elem_value_t *elem_value;
    int err;
    int ori_value;
    int i2s_is_set = 0;

    // 打開音訊設備的控制界面
    err = snd_ctl_open(&handle, device, 0);
    if (err < 0) {
        printf(":Cannot open device interface: %s\n", snd_strerror(err));  //無法打開音訊設備的控制界面
        return err;
    }


    // 分配並初始化 snd_ctl_elem_id_t 結構
    snd_ctl_elem_id_alloca(&elem_id);
    snd_ctl_elem_id_set_name(elem_id, control_name);


    // 獲取控制元素的索引
    snd_ctl_elem_id_set_interface(elem_id, SND_CTL_ELEM_IFACE_MIXER);

    // 獲取控制元素的數值
    snd_ctl_elem_value_alloca(&elem_value);
    snd_ctl_elem_value_set_id(elem_value, elem_id);
    snd_ctl_elem_value_set_boolean(elem_value, 0, option);  // 設置boolean值,由API參數option帶入

     

    // This is for fixing the core_dump issue
    // 先取得之前狀態,如果跟這次要設定的狀態相同,就不需要再做,直接 return.
    err = snd_ctl_elem_read(handle, elem_value);

    if (err < 0) {

            printf("Cannot read value: %s\n", snd_strerror(err));

            snd_ctl_close(handle);

            return err;

    }


    ori_value = snd_ctl_elem_value_get_boolean(elem_value, 0);

    if( option == ori_value )

    {

        printf("No need to Set, option equal to ori_value\n");

        snd_ctl_close(handle);

        return 0;

    }

    else

        snd_ctl_elem_value_set_boolean(elem_value, 0, option); //設定boolean值,由API參數option帶入

    /////////////////////////////////////////////


    // 設置控制元素的數值
    err = snd_ctl_elem_write(handle, elem_value);
    if (err < 0) {
        printf("Cannot set value: %s\n", snd_strerror(err));  //無法設置控制元素的數值
        snd_ctl_close(handle);
        return err;

    }

    // Poll the control value until it reaches the desired state

    // For fix the non-blocking issue

    while (!i2s_is_set) {

        // Sleep for a short period to avoid busy-waiting

        usleep(5000); // Sleep for 5 milliseconds


        // Read the control value

        err = snd_ctl_elem_read(handle, elem_value);

        if (err < 0) {

            printf("Cannot read value 2th: %s\n", snd_strerror(err));

            snd_ctl_close(handle);

            return err;

        }


        // Check if the control value is equal to the desired state

        int cur_value = snd_ctl_elem_value_get_boolean(elem_value, 0);

        if (cur_value == option) {

            i2s_is_set = 1;

        }

    }

    // 關閉音訊設備的控制界面
    snd_ctl_close(handle);
    printf("Setting %s %d success\n", control_name, option);  //已成功設置 i2s_clock 為 on
    return 0;

}


在Linux當中,應用程式,計算執行時間的範例程式

這個範例,計算單位為 microSecond(10-6)

#include <time.h>

 


clock_t start, end;

double cpu_time_used;

 

 

printf("** Start to measure time **\n");

start = clock();

...

...

...

end = clock();


cpu_time_used = ((double) (end - start))*1000000 / (CLOCKS_PER_SEC);

printf("** execution time:%f microseconds\n", cpu_time_used);

printf("** End of measure time **\n");


Linux kernel 4.19版 中,計算執行時間的方法,範例程式

首先需要 include 這個 header file 

#include <linux/time.h>


然後使用下面的方式,搭配 printk 在kernel 端印出計算時間,
這邊我們取 microseconds (10-6)

struct timeval start_time, end_time;

unsigned long elapsed_time;


 printk(KERN_ERR "#### measure time start %s ####\n", __func__);

do_gettimeofday(&start_time);   // Get the starting time

...

...

...

do_gettimeofday(&end_time);     // Get the ending time

 

// Calculate the executing time

elapsed_time = (end_time.tv_sec - start_time.tv_sec) * 1000000 +

                              (end_time.tv_usec - start_time.tv_usec);


printk(KERN_ERR "#### Elapsed time: %lu microseconds\n", elapsed_time);

printk(KERN_ERR "#### measure time end %s ####\n", __func__);



另外在 kernel 較新的版本當中,如果 do_gettimeofday() 無法使用,可以試試看下列方法

#include <linux/ktime.h>
#include <linux/types.h>

ktime_t start, end;
s64 elapsed_ns, 
elapsed_us;

start = ktime_get();

...
...
...

end = ktime_get();

elapsed_ns = ktime_to_ns(ktime_sub(end, start));
elapsed_us = ktime_to_us(elapsed_ns );

printk(KERN_ERR "#### Elapsed time: %lld microseconds\n", elapsed_us);


使用 lsblk 印出 emmc 每個 partition的"名字"與"size"

使用以下的command可以印出 eMMC的 partition資訊 lsblk --bytes --output name,partlabel,size   參數說明 --bytes: partition的大小,以byte的方式輸出 --output: 後面可以指定要輸出的內容...