2020/6/29

ADATA SC860 240G, install ubuntu

家裡還是要有linux才行...
所以買了adata sc860 usb3.2 ssd 來裝。
pchome 特價 240G, 999

安裝 OK,但是很奇怪,SSD 端是 type C 頭,另一端雖然有 Type A 跟 Type C 頭。但是只有 type C 頭偵測得到開機碟。
-- 是因為當初安裝就是用 type C 頭?

速度果很快,比USB 3.1, 3.5" 外接硬碟還快。
安裝 ubuntu 18.03, Mate, cuda10.1 + pytorch 共用掉 20G。

原來還發生Power Off 卡住的狀況,後來沒有發生了。

實際的 Read/Write 速度沒有測,在另一個 blog,有用 windows 10 測過,Write speed 約 110MB/s
在這裡,用 ubuntu,, 開機是很快沒錯。

2020/6/24

conf , in linux kernel source

make menuconfig, qconfig, xconfig .. etc 都是 call scripts/kconfig 下的 tool

scripts/kconfig 是一個獨立的tools, 包含一堆 conf.
Makefile 有說明裡面的執行檔 (不是 target..)
# ===========================================================================
# Shared Makefile for the various kconfig executables:
# conf:   Used for defconfig, oldconfig and related targets
# nconf:  Used for the nconfig target.
#         Utilizes ncurses
# mconf:  Used for the menuconfig target
#         Utilizes the lxdialog package
# qconf:  Used for the xconfig target
#         Based on Qt which needs to be installed to compile it
# gconf:  Used for the gconfig target
#         Based on GTK+ which needs to be installed to compile it
這幾個 conf 有共用的部份。

  • conf : 沒有 ui,就是單純run check .config
  • mconf: 用lxdialog 這個 library 做出 ui 的 config

linux 的 kconfig 比較大,buildroot 的 kconfig 比較小,可以從buildroot 的 kconfig 看起。

Makefile : target with variable %

kernel 或是一堆使用 menuconfig 的 project 在 make 之前都要 make XXX_config 或是 make XXX_defconfig。
然後這個 XXX_config , XXX_defconfig 還很有趣的是某個 file 的 filename..

所以是怎麼動態知道 filename as target 的呢?
就是用 Makefile 的 萬用配對符號: %
%_config: $(BOARD_DIR)/config/%_config
    @$(GEN_CONF) $(TOPDIR)/build/kconfig/conf --defconfig=$<
當然也有先把conf 下所有的 _defconfig 找出來做成target 的方法..

Makefile and shell script : echo command out

有時候,希望 Makefile 和 shell script 把執行當時的 command 印出來,
這樣比較容易trace 變數
shell script 的話,參考 這一篇..
在 shell script 的開頭加上..
set -x
也可用
bash -x myscipt.sh
也可以
Makefile 的話,一般都會印出執行的 command,除非在 command rule 之前有加 '@' 符號。
所以記得,把 '@' 刪除。

另外,make 的 option '-s' 也是 silenct 的意思,ref: make options
所以要記得把 -s 刪掉。

Makefile : about folders.

Makefile 中檢查folder 在不在
這一個 是動作不多的時候,利用 "一行" 的特性..
foo.bak: foo.bar
    echo "foo"
    if [ -d "~/Dropbox" ]; then echo "Dir exists"; fi
oo.bak: foo.bar
    echo "foo"
    if [ -d "~/Dropbox" ]; then \
        echo "Dir exists"; \
    fi

另外這一篇 前同事的 blog,是一般的,用 wildcard檢查好 create...
OUTPUT_PATH := test

all:
ifeq "$(wildcard $(OUTPUT_PATH))" ""
    mkdir $(OUTPUT_PATH)
    echo "directory not existed"
else
    echo "directory existed"
endif

還有一個,看起來好像比較笨..在Makefile 中 call shell command 來做...
ifeq ($(shell [ -d $(OUTPUT_PATH) ] && echo y), y)
    echo "directory existed"
else
    echo "directory not existed"
endif

2020/6/23

mkfs.cramfs in 18.04

if [ ${OS_VERS_MAJ} -lt 18 ]; then
    INSTALLPKGS+=(mtd-tools)
    INSTALLPKGS+=(cramfsprogs)
else
    INSTALLPKGS+=(mtd-utils)
    INSTALLPKGS+=(util-linux)
fi
原來 mkfs.cramfs 在不同的 ubuntu 版本,在不同的 package 裡..

2020/6/15

OpenRadar ..使用說明..

OpenRadar 這個 python 專案,真的很佛心。
把TI 沒給的東西都寫出來了,還是用 python,不必用 matlab.
雖然只是基礎而已,已經很有幫助了。

這個 Project 是用 python 來分析 DCA1000EVM 送出的 LVDS (ADC Data),也是是 raw data
他包含了:
  • 送 command 給 DCA1000EVM,開始/停止 loggin
  • 讀取 UDP 封包,分析,組合成一個 frame data
  • rage fft, doppler fft, angle of arrival function library
所以,都是針對 DCA1000EVM,不包含會 AWR1642 的操作。
所以 AWR1642 的 command 要自己做..用 uart 連線,送 config command..

基本的處理是在 Presense Applied Radar/basic 目錄下的 jupyter file (*.ipyb)
  • Range - COMPLETED.ipynb : 畫出一個 chirp recived data的 range fft
  • Doppler - COMPLETED.ipynb : 畫出一個 frame 的 range-doppler diagram
  • Angle of Arrival - COMPLETED.ipynb : 畫出一個 frame 的 object 的 angle of arrival diagram
上面的 example 用的都是預存的資料,放在assets 目錄下。
可以看到每個 sample code,一開始都是用np.load('XXX') 讀取預存資料。

所以 log DCA1000EVM 的部份,要另外做。
可以參考 dataloader/adc.py 的註解:
    General steps are as follows:
        1. Power cycle DCA1000 and XWR1xxx sensor
        2. Open mmWaveStudio and setup normally until tab SensorConfig or use lua script
        3. Make sure to connect mmWaveStudio to the board via ethernet
        4. Start streaming data
        5. Read in frames using class

    Examples:
         dca = DCA1000()
         adc_data = dca.read(timeout=.1)
         frame = dca.organize(adc_data, 128, 4, 256)
這樣就取得一個 frame 的資料。
但是其中沒說明 AWR1642 chirp config 的內容,要和 adc.py 的參數。還有 orgnize( ) 的參數一致。
這部份,就要看 adc.py 的 source code,和blog 前面幾篇的內容。
因為 adc.py 要靠這些參數決定一個 frame 是多少packet。
同時,oragnize( ) 也需要這些參數才知道怎嬷分割 資料..

另外,adc.py 中,對 DCA1000EVM 的命令,並不會啟動udp 資料。
所以要照 blog 的修改,加上start_record( ) command .
大概就是這樣 (為什麼不修好?)


最後,總結 OpenRadar 這格 project 的使用方法...
  • checkout 出來 -- 因為依照說明,用 pip install default packcage 的話,adc.py 的 chirp 參數沒辦法修改
  • 修改source 的 module loading path. 這樣才 import 得到正確的 source
  • 依照AWR1642 的 chirp config,修改 adc.py 的chirp parameters
  • 把 start, stop record command 加到 adc.py 中
  • uart 連接 AWR1642, 送出config
  • follow adc.py 的example,config. start_record, 讀取 frame,存檔
  • 參考basic/*.ipynb, 讀取剛剛存檔的內容,做 range, doppler, aoa
然後,如果PC 夠快的話,就可以收一個 frame,話一次圖。作到 realtime RV-map..

2020/6/12

完整做一次... save frame, draw range FFT..

AWR1642BOOST config command:
sensorStop
flushCfg
dfeDataOutputMode 1
channelCfg 15 3 0
adcCfg 2 1
adcbufCfg -1 0 0 1 0
profileCfg 0 77 429 7 57.14 0 0 70 1 256 5209 0 0 30
chirpCfg 0 0 0 0 0 0 0 1
chirpCfg 1 1 0 0 0 0 0 2
frameCfg 0 1 16 0 100 1 0
lowPower 0 1
guiMonitor -1 1 1 0 0 0 1
cfarCfg -1 0 0 8 4 4 0 5120
cfarCfg -1 1 0 4 2 3 0 5120
peakGrouping -1 1 1 1 1 255
multiObjBeamForming -1 1 0.5
clutterRemoval -1 0
calibDcRangeSig -1 0 -5 8 256
extendedMaxVelocity -1 0
bpmCfg -1 0 0 1
lvdsStreamCfg -1 0 1 0
nearFieldCfg -1 0 0 0
compRangeBiasAndRxChanPhase 0.0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
measureRangeBiasAndRxChanPhase 0 1.5 0.2
CQRxSatMonitor 0 3 5 123 0
CQSigImgMonitor 0 127 4
analogMonitor 1 1
sensorStart
這樣,adc.py 的chirp/frame 參數是:
ADC_PARAMS = {'chirps': 16, 
              'rx': 4,
              'tx': 2,
              'samples': 256,
              'IQ': 2,
              'bytes': 2}
dca1000test:tryadc 的 testadc.c...
from adc import DCA1000
import numpy as np

dca = DCA1000()
dca.send_start_command()
adc_data = dca.read(timeout=.1)
np.save('framedata',adc_data)

dca.send_stop_command()
save 一個 frame 的資料 framedata.npy。

import numpy as np
import matplotlib.pyplot as plt

rawdata = np.load('framedata.npy')
rxdata = np.zeros(len(rawdata)//2, dtype=complex)

rxdata[0::2] = rawdata[0::4] + 1j * rawdata[2::4]
rxdata[1::2] = rawdata[1::4] + 1j * rawdata[3::4]

rxchirp = rxdata.reshape((16*4*2,256))
把 data 讀進來,依照 udp data format 的順序,和 chirp parameters, 轉成 complex,
然後再改成二維陣列,每個 chirp 一個element.

然後把一個rx 的 chirp 畫出來看...
plt.plot(np.abs(rxchirp[0]))
plt.show()


這個樣子..感覺應該是 signed 才對 (值很靠近 0, 所以負值以unsigned 看來看0xFFxx 變得很大)

看 OpenRadar 的 basic/range.ipynb,其中有說明:
#Read in chirp data
addc_samples = np.loadtxt('../assets/chirp.txt',dtype=np.complex)

#Manually cast to signed ints
adc_samples.real = adc_samples.real.astype(np.int16)
adc_samples.imag = adc_samples.imag.astype(np.int16)

#Take FFT across ADC samples
range_bins = np.fft.fft(adc_samples)

# Plot the magnititude of the range bins
plt.plot(np.abs(range_bins))
plt.show()
果然,讀近來之後,要 cast 成 int16

所以修改 adc.py,存的時候就用 int16,不用 uint16,這樣np.load 後,也會是 int16.
上面的 code ,不用修改,就變成:

看起來比剛剛正常。
進型 FFT 後...
plt.plot(np.abs(np.fft.fft(rxchirp[0])))
plt.show( )
顯示正確的 range peak:

2020/6/11

send, receive file in python

多電腦操作很麻煩...A NB 取得資料,B 分析。C對照。
用網路芳鄰還要用 mouse 拖拉很麻煩。
所以練習一下python...
ppscv localip  收檔,,不關掉的話會一直收...

ppsend targetip filename  傳檔,一次只能傳一個
.. 果然是很低級的....

附帶,, 在 Windows 上就是麻煩,不能直接 run py, 還要寫一個 bat.
所以把他 build 成 exe.
要用 tool : pyinstaller
conda install pyinstaller
pyinstaller -F pprcv.py
這樣就在 dist 下產生一個 pprcv.exe。
可以直接 run 了...

測試,exe copy 到其他機器上也可以正常執行,沒有環境問題。

Modify OpenRadar command code

python code to command DCA1000EVM Start/Stop Record
把這個啟動命令寫到 adc.py:

adc.py 的 command 宣告:
class CMD(Enum):
    RESET_FPGA_CMD_CODE = '0100'
    RESET_AR_DEV_CMD_CODE = '0200'
    CONFIG_FPGA_GEN_CMD_CODE = '0300'
    CONFIG_EEPROM_CMD_CODE = '0400'
    RECORD_START_CMD_CODE = '0500'
    RECORD_STOP_CMD_CODE = '0600'
    PLAYBACK_START_CMD_CODE = '0700'
    PLAYBACK_STOP_CMD_CODE = '0800'
    SYSTEM_CONNECT_CMD_CODE = '0900'
    SYSTEM_ERROR_CMD_CODE = '0a00'
    CONFIG_PACKET_DATA_CMD_CODE = '0b00'
    CONFIG_DATA_MODE_AR_DEV_CMD_CODE = '0c00'
    INIT_FPGA_PLAYBACK_CMD_CODE = '0d00'
    READ_FPGA_VERSION_CMD_CODE = '0e00'
對應ref 的內容,依序是送...
  • 5aa50300060001020102031eaaee : CONFIG_FPGA_GEN_CMD_CODE
  • 5aa509000000aaee : SYSTEM_CONNECT_CMD_COD
  • 5aa505000000aaee : RECORD_START_CMD_COD
然後停止的 command 是:
  • 5aa506000000aaee : RECORD_STOP_CMD_CODE
除了第一個 FPGA_GEN_CMD 之外,都沒有 data。

send command 的 function 是
    def _send_command(self, cmd, length='0000', body='', timeout=1):
        """Helper function to send a single commmand to the FPGA

        Args:
            cmd (CMD): Command code to send to the FPGA
            length (str): Length of the body of the command (if any)
            body (str): Body information of the command
            timeout (int): Time in seconds to wait for socket data until timeout

        Returns:
            str: Response message

        """
        # Create timeout exception
        self.config_socket.settimeout(timeout)

        # Create and send message
        resp = ''
        msg = codecs.decode(''.join((CONFIG_HEADER, str(cmd), length, body, CONFIG_FOOTER)), 'hex')
        try:
            self.config_socket.sendto(msg, self.cfg_dest)
            resp, addr = self.config_socket.recvfrom(MAX_PACKET_SIZE)
        except socket.timeout as e:
            print(e)
        return resp
所以對應上面的命令應該是...
_send_command(CONFIG_FPGA_GEN_CMD_CODE,'0600','01020102031e')
_send_command(SYSTEM_CONNECT_CMD_COD)
_send_command(RECORD_START_CMD_COD)
然後停止是
_send_command(RECORD_STOP_CMD_CODE)
所以在 adc.py 中增加兩個 functions:
    def send_start_command(self):
        print(self._send_command(CMD.CONFIG_FPGA_GEN_CMD_CODE,'0600','01020102031e'))
        print(self._send_command(CMD.SYSTEM_CONNECT_CMD_CODE))
        print(self._send_command(CMD.RECORD_START_CMD_CODE))
    
    def send_stop_command(self):
        print(self._send_command(CMD.RECORD_STOP_CMD_CODE))

2020/6/10

chirp config and adc.py parameters

再來一次。用 mmWave Demo Visualizer (2.1) 的 Best Range Resolution 的 command,並且改 lvdsStreamCfg 輸出..
sensorStop
flushCfg
dfeDataOutputMode 1
channelCfg 15 3 0
adcCfg 2 1
adcbufCfg -1 0 0 1 0
profileCfg 0 77 429 7 57.14 0 0 70 1 256 5209 0 0 30
chirpCfg 0 0 0 0 0 0 0 1
chirpCfg 1 1 0 0 0 0 0 2
frameCfg 0 1 16 0 100 1 0
lowPower 0 1
guiMonitor -1 1 1 0 0 0 1
cfarCfg -1 0 0 8 4 4 0 5120
cfarCfg -1 1 0 4 2 3 0 5120
peakGrouping -1 1 1 1 1 255
multiObjBeamForming -1 1 0.5
clutterRemoval -1 0
calibDcRangeSig -1 0 -5 8 256
extendedMaxVelocity -1 0
bpmCfg -1 0 0 1
lvdsStreamCfg -1 0 1 0
nearFieldCfg -1 0 0 0
compRangeBiasAndRxChanPhase 0.0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
measureRangeBiasAndRxChanPhase 0 1.5 0.2
CQRxSatMonitor 0 3 5 123 0
CQSigImgMonitor 0 127 4
analogMonitor 1 1
sensorStart
這個對應的參數:
  • ADC Samples: 256
  • Loop Per Frame : 16
  • TX : 2
  • RX : 4

numpy reshape

np.reshape( ) 是把 array 重新安排 (group) ,可以重新安排維度..

舉例,宣告出一個一維的 array..
import numpy as np
A = np.array([1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6])
把他分成6個group,每個 group 有 4 個 item..
A.reshape((6,3))

array([[1, 1, 1, 1],
       [2, 2, 2, 2],
       [3, 3, 3, 3],
       [4, 4, 4, 4],
       [5, 5, 5, 5],
       [6, 6, 6, 6]])
這樣就變成二維矩陣。
其中,第一個維度..
A.reshape((6,3))[0]

array([1,1,1,1])

三個維度的話...
先分成三個 group,每個 group 再分成兩個 group...
這樣每個最小 group 裡面有 4 個 item.
A.reshape((3,2,4))

array([[[1, 1, 1, 1],
        [2, 2, 2, 2]],

       [[3, 3, 3, 3],
        [4, 4, 4, 4]],

       [[5, 5, 5, 5],
        [6, 6, 6, 6]]])
每個維度的 index.. 和 item..
A.reshape((3,2,4))[1]

array([[3, 3, 3, 3],
       [4, 4, 4, 4]])


A.reshape((3,2,4))[1][0]

array([3, 3, 3, 3])

openradar , frame reshape and chirps. frame parameters

覺得有關 frame, chirps 的參數,在 realtime.py 和 adc.py 中不一致。
這個也和 AWR1642 config command 有關。

realtime.py 的參數:
numFrames = 300
numADCSamples = 128
numTxAntennas = 3
numRxAntennas = 4
numLoopsPerFrame = 128
numChirpsPerFrame = numTxAntennas * numLoopsPerFrame

numRangeBins = numADCSamples
numDopplerBins = numLoopsPerFrame
numAngleBins = 64
他有 numChirpsPFrame = numTxAntennas * numLoopsPerFrame
跟 stanley 說明的一樣,一個 loop ,就是 一個 profile.
一個 frame 的定義就是 N 個 loop。

這個 numLoopsPerFrame 只有在 這裡有用到,其他 source code 的地方都沒有用。

adc.py 的參數:
ADC_PARAMS = {'chirps': 128, 
              'rx': 4,
              'tx': 3,
              'samples': 128,
              'IQ': 2,
              'bytes': 2}

BYTES_IN_FRAME = (ADC_PARAMS['chirps'] * ADC_PARAMS['rx'] * ADC_PARAMS['tx'] *
                  ADC_PARAMS['IQ'] * ADC_PARAMS['samples'] * ADC_PARAMS['bytes'])
直接用 chirps.
但是 bytes_in_frame,刪掉 rx, samples. IO. bytes 後...
chirps * tx
這樣看起來 chirps 好像是 loops ?


回到 realtime.py,讀完一個 frame 後..
 frame = dca.organize(adc_data, num_chirps=numChirpsPerFrame, num_rx=numRxAntennas, num_samples=numADCSamples)
其中 organize() :
  def organize(raw_frame, num_chirps, num_rx, num_samples):
        """Reorganizes raw ADC data into a full frame

        Args:
            raw_frame (ndarray): Data to format
            num_chirps         : Number of chirps included in the frame
            num_rx             : Number of receivers used in the frame
            num_samples        : Number of ADC samples included in each chirp

        Returns:
            ndarray: Reformatted frame of raw data of shape (num_chirps, num_rx, num_samples)

        """
        ret = np.zeros(len(raw_frame) // 2, dtype=complex)

        # Separate IQ data
        ret[0::2] = raw_frame[0::4] + 1j * raw_frame[2::4]
        ret[1::2] = raw_frame[1::4] + 1j * raw_frame[3::4]
        return ret.reshape((num_chirps, num_rx, num_samples))
最後的 reshape(num_chirps, num_rx, num_samples)
說明,安排的方式...
([[S,......samples],   <--rx0    第一個 chirp
  [S,......samples]],  <--rx1

 [[S,......samples],   <--rx0    第二個 chirp
  [S,......samples]],  <--rx1
  
  ...
  ..
 [[S,......samples],               第 num_chirps-1 個chirp
  [S,......samples]])
上面就是一個 frame.的所有 chirps.

所以...
framedata = data.organize(...)
framedata[0]    <-- 這是第一個 chirp 的 rx0,rx1 矩陣
framedata[0][1] <-- 這是第一個 chirp 的 rx1 array (所有 sample point)

回到 adc.py 跟 realtime.py:

參考 DCA1000EVM UDP RAW data format
raw data 是.. 每個chirp(不管是那一個 tx 送的),依照順序送 rx0,rx1,rx1,rx2 的 adc samples
所以 tx0, tx1 如果是依序送出的話, raw data 的資料也會依序是..
TX0 :  rx0,
       rx1,
       rx2,
       rx3,
TX1 :  rx0,
       rx1,
       rx2,
       rx3
所以orgnize( ) 是不用管TX0, TX1..他只需要知道一個 frame 到底有多少 chirp (TX0 + TX1)

chirps 應該是 TX 發出的FMCW波。
每個 chirps 會有 N 個 rx 信號。
所以 chirps_number * rx_number = frame rx number

最後... adc.py 跟 realtime.py 要對的起來的地方...
adc.py 的 read( ) 一個 frame,要剛好跟 realtime.py 的 orgnize( ) 的一個 frame 的 size 一樣。
read( ) 一個 frame (扣除 IO 跟 bytes):
chirps * tx * rx * samples
realtime.py 的 orgnize:
numChirpsPerFrame(numLoopsPerFrame * numTxAntennas)  * numRxAntennas * numADCSamples
這樣看來...numLoopsPerFrame 好像就是 adc.y 的 ADC_PARAMS['chirps']

2020/6/9

openradar : show range and doppler

在 demo/visualizer/realtime.py 有 fft processing 的 code..
   ...
        # (1) Reading in adc data
        adc_data = dca.read()
        frame = dca.organize(adc_data, num_chirps=numChirpsPerFrame, num_rx=numRxAntennas, num_samples=numADCSamples)

        # (2) Range Processing
        from mmwave.dsp.utils import Window
        radar_cube = dsp.range_processing(frame, window_type_1d=Window.BLACKMAN)
        assert radar_cube.shape == (
        numChirpsPerFrame, numRxAntennas, numADCSamples), "[ERROR] Radar cube is not the correct shape!"

        # (3) Doppler Processing 
        det_matrix, aoa_input = dsp.doppler_processing(radar_cube, num_tx_antennas=3, clutter_removal_enabled=True)

        # --- Show output
        if plotRangeDopp:
            det_matrix_vis = np.fft.fftshift(det_matrix, axes=1)
            plt.imshow(det_matrix_vis / det_matrix_vis.max())
            plt.pause(0.05)
            plt.clf()

  ...

2020/6/8

cv2.VideoCapture() in Windows

簡單的測試 code;
import cv2

cap = cv2.VideoCapture(0)
ret, frame = cap.read()
print(ret)
print(frame)
cv2.release()
其中 cv2.VideoCapture(0) 的 0, 就是機器上的 camera index,有幾個 camera,就用 0, 1, 2 來選。
只是不知道那一個 index 是那一個 camera..

這樣的 code,在 run 完後會出現一個 Warning:
[WARN:0] terminating async callback
這個只有在 windows 上才會有。
google 說,在VideoCapture 加上 option:
cap = cv2.VideoCapture(0,cv2.CAP_DSHOW)
說明使用 directshow 裝置。舊可以消除。

另外,在 windows 系統上,取得 VideoCapture 後,前幾個 read( ) 到的 frame 都是 黑或是灰(16) 的內容…
好像跟 camera 有關,使用nb 內建的 camera,比較不會出現這個問題。
使用外接的 usb camera,不同的camera,第一個影像出現的時間會不一樣。
跟 cpu 的速度也有關係。


* 2022/02/23 update

Linux 系統也一樣,其實是 camera (capture) 有關。
有些 hdmi usb capture 裝置,程式開啟裝置後,都要等 0.5 sec,有些不用。
所以 safe 的作法 (要take snapshot 的話)。 delay 1s:
import cv2
import time

cap = cv2.VideoCapture(2)
time.sleep(1)

ret, frame = cap.read()
cv2.imshow('ff',frame)
cv2.imsave("abc.jpg",frame)
...

cv2.imshow fail on ubuntu 18.04 anaconda

好麻煩呀,ubuntu18.04 conda python 3.8 的話,opencv 的 imshow 會 fail:
Traceback (most recent call last):
  File "testvideocap.py", line 5, in 
    cv2.imshow('dd',frame)
cv2.error: OpenCV(3.4.2) /tmp/build/80754af9/opencv-suite_1535558553474/work/modules/highgui/src/window.cpp:632: 
error: (-2:Unspecified error) The function is not implemented. Rebuild the library with Windows, GTK+ 2.x or Carbon support. 
If you are on Ubuntu or Debian, install libgtk2.0-dev and pkg-config, then re-run cmake or configure script in function 'cvShowImage'
好像是conda repo 的這個(3.4.2) 沒有人 mantain 了。
但是新的 mantainer 有做,所以換安裝新版 opencv 舊可以。
conda remove opencv
conda install -c conda-forge opencv=4.1.0
-c 是 channel 的意思,用 conda-forge 這個 channel 的 opencv4.1.0 package 來安裝。
是社群貢獻的 conda package repo(?).

2020/6/1

chirp config file and adc.py parameters . set I

sensorStop
flushCfg
dfeDataOutputMode 1
channelCfg 15 3 0
adcCfg 2 1
adcbufCfg -1 0 0 1 0
profileCfg 0 77 429 7 57.14 0 0 70 1 256 5209 0 0 30
chirpCfg 0 0 0 0 0 0 0 1
chirpCfg 1 1 0 0 0 0 0 2
frameCfg 0 0 16 0 100 1 0
lowPower 0 1
guiMonitor -1 1 1 0 0 0 1
cfarCfg -1 0 0 8 4 4 0 5120
cfarCfg -1 1 0 4 2 3 0 5120
peakGrouping -1 1 1 1 1 255
multiObjBeamForming -1 1 0.5
clutterRemoval -1 0
calibDcRangeSig -1 0 -5 8 256
extendedMaxVelocity -1 0
bpmCfg -1 0 0 1
lvdsStreamCfg -1 0 1 0
nearFieldCfg -1 0 0 0
compRangeBiasAndRxChanPhase 0.0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
measureRangeBiasAndRxChanPhase 0 1.5 0.2
CQRxSatMonitor 0 3 5 123 0
CQSigImgMonitor 0 127 4
analogMonitor 1 1
sensorStart

這樣對應的 ADC 參數是
ADC_PARAMS = {'chirps' : 16,
              'rx'     : 4,
              'tx'     : 1,
              'samples': 256,
              'IQ'     : 2
              'bytes'  : 2}