tag:blogger.com,1999:blog-53936937615099998412024-03-14T00:17:33.109+08:00jjhuang's Random NotesThis is my random notes of random topics or random data posted at random.Albert Huanghttp://www.blogger.com/profile/15756607906352002721noreply@blogger.comBlogger42125tag:blogger.com,1999:blog-5393693761509999841.post-91753136093170877482020-10-01T22:29:00.000+08:002020-10-01T22:29:04.108+08:00社群媒體關機一個月的實驗自從 2019 年五月看了《深度工作力》這本書之後,知道了以前我工作高效率的原因,也知道了我現在的效率跟以前有一段不小的差距,去年開始針對專注力的提升做了一些改變,今年八月又重看了這本書,還順便加碼了《深度專注力》與《最有生產力的一年》,其實講專注力或生產力的書都有幾個重點,就是要增加專注力,減少干擾,增加靈光乍現的機會。前兩者是大腦的「專注模式(focus mode)」,最後一個是大腦的「放鬆模式(diffuse mode)」。這是我在 "Learning How to Learn" 的線上課程裡面學到的,專注模式是得到思考的材料,放鬆模式則會把這些材料聯結起來。事實上我從研究所就開始這麼做,我喜歡專注研讀一些材料之後去散步,通常有很大的機會,在散步的時候就會出現靈感。但我其實發現,使用 social media 愈多,我的專注力就愈低,而且「放鬆模式」就愈少,因為滑手機滑多了,在我們等待任何事情的時候,都很容易拿起手機,然而,大腦覺得無聊的時候,正是進入「放鬆模式」的黃金時刻,也就是說滑手機其實剝奪了靈光乍現的機會。這個卻是我在最近才猛然驚覺的,而且也在這幾本書裡面證實我的想法。也因此,我就依照《深度工作力》一書的建議,來把我平常最常在休息時間滑的社群媒體關機一個月。
<br><br>
原先手機或網路幾乎都是不離身的,我想現代人大部分都是拿手機當鬧鐘,一起床就拿起來看時間,看看天氣,然後就順便滑一下臉書、推特或是 Instagram 等等社群媒體,接著上廁所可能也帶上手機順便看看新聞,或是繼續滑臉書,畢竟臉書真的很多內容要滑的啊(笑)。然後準備上班前用 Google 導航看一下路況,看看今天天氣預報,然後出門,出門依照每個人選擇的交通工具不同,搭大眾運輸的,全程繼續滑手機,騎機車或開車的,等個紅燈就會拿起來滑,到了公司搭電梯,很多人也是在等電梯的時候就拿出手機來滑,進了電梯繼續滑,有些人甚至走到座位前還繼續滑。工作的時候,雖然手機不方便拿起來滑,但現代辦公室也有公司用的 social media,還有 email,《最有生產力的一年》書中就有提到,根據 RescueTime 的調查,一名知識工作者每天平均打開電子郵箱五十次,並使用即時訊息七十七次。工作之餘的休息空檔,大腦會很想要補充多巴胺,就更想要趕快拿起手機滑了。吃飯時間,不管是獨自用餐或是話題開始冷掉的時候,都會拿起手機滑。等到回家休息,就是滑手機的重點時刻了,畢竟工作累了一天,大家也都是下班之後開始猛力 post 文章,有好多要滑的啊。到了晚上就寢時間,躺在床上等睡意來襲的時候,也會順便拿起手機滑,反正都要等嘛。於是一天之中,第一眼見到的是手機,最後一眼見到的也是手機,這就是現代人的網路生活。
<br><br>
在這一個月裡面,我盡我最大的努力減少網路的使用。我把我最常用的 social media 在我手機移除,只保留了無法避免或是很少在用的(我沒有要真的完全與世隔絕)。早上的鬧鐘也改成實體的鬧鐘,手機會放在房間充電以防有緊急事件,但不是我唾手可得的距離。上廁所也不帶手機(我相信很多人都會帶手機去滑啦,但大家可能都會很不好意思承認),我一天檢查必要的 social media 一到兩次,檢查 email 一天大約三次,儘量把網路都安排在同個時段處理(《深度工作力》中所謂的 shallow task 時段)。為了減少在辦公室被打擾,我也會戴上抗噪耳機。等電梯等紅燈這種無聊的時刻,也不拿起手機來滑。我的原則就是:<br>
- 不打開網路應用的通知<br>
- 需要用網路的時候,就把他們集中在同個時段處理<br>
- 大腦覺得無聊的時候,不拿起手機來排解這個無聊<br>
- 想到要在網路上查什麼資料,不要立刻去查,先記下來,至少等五分鐘以後才去查(避免大腦的獎勵迴路)<br>
- 大腦有任何想法出現都先記在筆記本上,以便清空短期記憶<br>
- 想到要在網路上分享什麼事情的時候,等個半個小時以上再說,通常這個念頭都會消失(也是避免大腦的獎勵迴路)<br><br>
這些改變不是一次到位,是逐漸加入的,以防止猛烈的戒斷症候群(笑)。我也依照《深度工作力》裡面的建議,一直不斷的安排一天接下來的行程,思考什麼時候要排深度工作,什麼時候要排淺薄工作,如果行程有變,那就繼續安排接下來的行程,保持彈性,也不去強迫自己一定要非常依照原先的行程,但原則就是一定要事先安排。然後深度工作我一定會跑番茄鐘,幫助自己快速進入專注模式,稍有分心,也會看一下時間,就繼續拉回原先專注的事情。有任何想法或要計畫什麼事情,也都是在筆記本上紀錄,我一直維持紙本萬用手冊的習慣,當然還有工作日誌也是紙本的。
<br><br>
那麼我有什麼改變呢?大約一週之後,我的專注程度就大幅增加了,而我在大約十五天之後很驚喜的發現,想要放鬆娛樂自己的時候,第一個念頭不是開 Netflix 也不是滑手機,而是拿起書來讀。比方說我吃完晚餐之後,坐到沙發休息的時候,就會順手拿起書來讀。有時候看 Netflix 也不再像以前一樣一直連續看下去,而是看個一兩集就停止了。大約三週之後,我的靈感回來了,我在散步的時候、淋浴的時候,靈感是源源不絕的出現,我都會隨身帶個小筆記本記錄下來。這段時間,我也發現自己會在路上或電梯中,跟陌生人交談。一個月後的今天,我很滿意自己的改變,可以說我的自信也提高了,這時候就讓我引述一下這段時間一直出現在我心中的一段聖經:「箴言 16:32 不輕易發怒的勝過勇士,制伏己心的強如取城。」
<br><br>
一個月關機的時間,其實很快就過去了,接下來 social media 重開機的漫漫長路,才更是對抗網路這個專注力殺手的長期抗戰。不過,把握上述幾個原則,就能把網路對於專注力的殺傷力降到最低。而且 social media 關機一個月的實驗也讓我了解到,這些 social media 真的沒有那麼重要,但我不是說人際互動不重要,事實上,關機的時刻,讓我更體會到人際互動的重要性,但 social media 的互動無法滿足人際互動需求的深度,只有當面或是電話才能夠滿足這種深度,而且也更節省時間,換句話說,更有生產力。
Albert Huanghttp://www.blogger.com/profile/09910403631033610841noreply@blogger.com0tag:blogger.com,1999:blog-5393693761509999841.post-10865863827552477792016-05-30T22:05:00.000+08:002018-04-05T19:43:28.702+08:00以頻率計數器來看 Undersampling<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<!-- 2016-05-30 Mon 22:02 -->
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>以頻率計數器來看 Undersampling</title>
<meta name="generator" content="Org-mode" />
<meta name="author" content="Albert Huang" />
<style type="text/css">
<!--/*--><![CDATA[/*><!--*/
.title { text-align: center;
margin-bottom: .2em; }
.subtitle { text-align: center;
font-size: medium;
font-weight: bold;
margin-top:0; }
.todo { font-family: monospace; color: red; }
.done { font-family: monospace; color: green; }
.priority { font-family: monospace; color: orange; }
.tag { background-color: #eee; font-family: monospace;
padding: 2px; font-size: 80%; font-weight: normal; }
.timestamp { color: #bebebe; }
.timestamp-kwd { color: #5f9ea0; }
.org-right { margin-left: auto; margin-right: 0px; text-align: right; }
.org-left { margin-left: 0px; margin-right: auto; text-align: left; }
.org-center { margin-left: auto; margin-right: auto; text-align: center; }
.underline { text-decoration: underline; }
#postamble p, #preamble p { font-size: 90%; margin: .2em; }
p.verse { margin-left: 3%; }
pre {
border: 1px solid #ccc;
box-shadow: 3px 3px 3px #eee;
padding: 8pt;
font-family: monospace;
overflow: auto;
margin: 1.2em;
}
pre.src {
position: relative;
overflow: visible;
padding-top: 1.2em;
}
pre.src:before {
display: none;
position: absolute;
background-color: white;
top: -10px;
right: 10px;
padding: 3px;
border: 1px solid black;
}
pre.src:hover:before { display: inline;}
pre.src-sh:before { content: 'sh'; }
pre.src-bash:before { content: 'sh'; }
pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
pre.src-R:before { content: 'R'; }
pre.src-perl:before { content: 'Perl'; }
pre.src-java:before { content: 'Java'; }
pre.src-sql:before { content: 'SQL'; }
table { border-collapse:collapse; }
caption.t-above { caption-side: top; }
caption.t-bottom { caption-side: bottom; }
td, th { vertical-align:top; }
th.org-right { text-align: center; }
th.org-left { text-align: center; }
th.org-center { text-align: center; }
td.org-right { text-align: right; }
td.org-left { text-align: left; }
td.org-center { text-align: center; }
dt { font-weight: bold; }
.footpara { display: inline; }
.footdef { margin-bottom: 1em; }
.figure { padding: 1em; }
.figure p { text-align: center; }
.inlinetask {
padding: 10px;
border: 2px solid gray;
margin: 10px;
background: #ffffcc;
}
#org-div-home-and-up
{ text-align: right; font-size: 70%; white-space: nowrap; }
textarea { overflow-x: auto; }
.linenr { font-size: smaller }
.code-highlighted { background-color: #ffff00; }
.org-info-js_info-navigation { border-style: none; }
#org-info-js_console-label
{ font-size: 10px; font-weight: bold; white-space: nowrap; }
.org-info-js_search-highlight
{ background-color: #ffff00; color: #000000; font-weight: bold; }
/*]]>*/-->
</style>
<script type="text/javascript">
/*
@licstart The following is the entire license notice for the
JavaScript code in this tag.
Copyright (C) 2012-2013 Free Software Foundation, Inc.
The JavaScript code in this tag is free software: you can
redistribute it and/or modify it under the terms of the GNU
General Public License (GNU GPL) as published by the Free Software
Foundation, either version 3 of the License, or (at your option)
any later version. The code is distributed WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
As additional permission under GNU GPL version 3 section 7, you
may distribute non-source (e.g., minimized or compacted) forms of
that code without the copy of the GNU GPL normally required by
section 4, provided you include this license notice and a URL
through which recipients can access the Corresponding Source.
@licend The above is the entire license notice
for the JavaScript code in this tag.
*/
<!--/*--><![CDATA[/*><!--*/
function CodeHighlightOn(elem, id)
{
var target = document.getElementById(id);
if(null != target) {
elem.cacheClassElem = elem.className;
elem.cacheClassTarget = target.className;
target.className = "code-highlighted";
elem.className = "code-highlighted";
}
}
function CodeHighlightOff(elem, id)
{
var target = document.getElementById(id);
if(elem.cacheClassElem)
elem.className = elem.cacheClassElem;
if(elem.cacheClassTarget)
target.className = elem.cacheClassTarget;
}
/*]]>*///-->
</script>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
displayAlign: "center",
displayIndent: "0em",
"HTML-CSS": { scale: 100,
linebreaks: { automatic: "false" },
webFont: "TeX"
},
SVG: {scale: 100,
linebreaks: { automatic: "false" },
font: "TeX"},
NativeMML: {scale: 100},
TeX: { equationNumbers: {autoNumber: "AMS"},
MultLineWidth: "85%",
TagSide: "right",
TagIndent: ".8em"
}
});
</script>
<script type="text/javascript" src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML"></script>
</head>
<body>
<div id="content">
<h1 class="title">以頻率計數器來看 Undersampling</h1>
<div id="table-of-contents">
<h2>Table of Contents</h2>
<div id="text-table-of-contents">
<ul>
<li><a href="#orgheadline1">1. 頻率計數器問題</a></li>
<li><a href="#orgheadline2">2. 如何計算頻率?</a></li>
<li><a href="#orgheadline3">3. 這跟取樣有什麼關係?</a></li>
<li><a href="#orgheadline4">4. 如果你的計數頻率低於要偵測的頻率呢?</a></li>
<li><a href="#orgheadline5">5. 結語</a></li>
</ul>
</div>
</div>
<div id="outline-container-orgheadline1" class="outline-2">
<h2 id="orgheadline1"><span class="section-number-2">1</span> 頻率計數器問題</h2>
<div class="outline-text-2" id="text-1">
<p>
想像一下你現在有一套嵌入式系統軟硬體,你只能偵測外部輸入是高或低電位(也就是 GPIO),你要測量外部的方波的頻率,你要怎麼達成呢?我想你能夠達成的就是,固定時間,比方說每隔 1 µs 「偵測」一次訊號位準是高或低,然後標定由低變高以及由高變低的地方,並且計算這個「由低變高」的週期,再轉換成頻率吧?你還能想到更簡單精準的方式嗎?歡迎來挑戰。
</p>
</div>
</div>
<div id="outline-container-orgheadline2" class="outline-2">
<h2 id="orgheadline2"><span class="section-number-2">2</span> 如何計算頻率?</h2>
<div class="outline-text-2" id="text-2">
<div id="orgparagraph1" class="figure">
<p><iframe src="https://jjhuang314.github.io/Org/FreqCounter/ZeroCrossingOversampling.jpeg" width="640" height="480"></iframe>
</p>
<p><span class="figure-number">Figure 1:</span> 頻率計數</p>
</div>
<p>
由圖 <a href="#orgparagraph1">1</a> 可以計算頻率,圖中黑色的方波是你要計算頻率的波形,而橘色的方波代表了你讀取外部 GPIO 值的時間點,綠色就是讀取到的值。\(T_0\) 是要計算的方波週期,從圖上的格子點來計算(假設一格是 1 µs),是 16 µs,\(T_s\) 是讀取 GPIO 的週期,是 4 µs,計算出來的頻率週期是 $T<sub>c</sub>$,是 16 µs,就是訊號「看起來變回一週期同樣位置的」週期(為什麼強調這一點?因為要真正計算頻率,也是有點技巧的,這技巧叫做 frequency estimation,有機會再講,你的大腦比數學公式強多了,呵呵)
</p>
<p>
這裡 \(T_0 = T_c = 16 \mu s\) , 咦?可以精確的計算出來方波頻率呢。
</p>
<p>
我們改用頻率來看這些數值
\(F_0 = F_c = \frac{1}{T_0} = \frac{1}{T_c} = 62500 Hz = 62.5 kHz, F_s = \frac{1}{T_s} = 250000 Hz = 250 kHz\)
</p>
</div>
</div>
<div id="outline-container-orgheadline3" class="outline-2">
<h2 id="orgheadline3"><span class="section-number-2">3</span> 這跟取樣有什麼關係?</h2>
<div class="outline-text-2" id="text-3">
<p>
啊,這就是取樣啊,取樣就是這麼單純的一件事。「用同樣的頻率去觀察這個世界」,就是取樣的基本意義。上一篇文章「淺談取樣定理」就是在闡述這件事,所以,用固定的週期,去觀察 GPIO 的值,你說他跟取樣定理沒關係嗎?錯啦,他就是取樣定理的一個應用,所以取樣定理的 Nyquist rate 一樣會應用在這個過程中。所以 \(F_s \ge 2 * F_c\) 所以可以成功的取樣完整的訊號,等等,好像哪裡不對吧?先別說這個了,我們來看萬一你的計數頻率低於要偵測的頻率怎麼辦。
</p>
</div>
</div>
<div id="outline-container-orgheadline4" class="outline-2">
<h2 id="orgheadline4"><span class="section-number-2">4</span> 如果你的計數頻率低於要偵測的頻率呢?</h2>
<div class="outline-text-2" id="text-4">
<p>
如果你要計數的頻率低於要偵測的頻率,會發生什麼事呢?按照前面的流程,我們就畫一下波形來看看。
</p>
<div id="orgparagraph2" class="figure">
<p><img src="https://jjhuang314.github.io/Org/FreqCounter/ZeroCrossingUndersampling.jpeg" alt="ZeroCrossingUnderSampling.jpeg" />
</p>
<p><span class="figure-number">Figure 2:</span> 頻率計數 Undersampling</p>
</div>
<p>
圖 <a href="#orgparagraph2">2</a> 就是 undersampling 的情況,一樣黑色方波是要計算頻率的波形,而橘色方波代表讀取外部 GPIO 值的時間點,綠色就是讀到的值。
</p>
<p>
\(T_0 = 4 \mu s, T_s = 6 \mu s, T_c = 12 \mu s\)
</p>
<p>
換算成頻率
</p>
<p>
\(F_0 = 250 kHz, F_s = 166.667 kHz, F_c = 83.333 kHz\)
</p>
<p>
哇,你說這怪怪的吧,我原本的頻率是 250 kHz,取樣後變成 83.333 kHz,你說,啊對,因為低於 Nyquist rate,所以無法取樣到正確的頻率,所以把這個資訊丟棄吧!不,這個資訊還是有用的,這個是低於 Nyquist rate 的時候,會看到的現象。在這裡,因為你在方波的正緣與負緣都取樣,所以其實真正的取樣率 $F<sub>s</sub> = 333.333 kHz$,這就是上一節怪怪的地方(有看出來嗎?)我為什麼這麼做呢?因為在某些數位的計數器就是這麼做的,正緣與負緣都偵測一次,如果值改變了,就累計一次,沒改變就不累計。這種情況下的取樣頻率你要乘以二。
</p>
<p>
好啦,重點來了,\(F_s - F_0 = 333.333 - 250 = 83.333 kHz\) ,這巧合吧,你說。再次有圖有真相,我們來畫圖。
</p>
<div id="orgparagraph3" class="figure">
<p><img src="https://jjhuang314.github.io/Org/FreqCounter/FrequencyAmbiguity.jpeg" alt="FrequencyAmbiguity.jpeg" />
</p>
<p><span class="figure-number">Figure 3:</span> Frequency Ambiguity</p>
</div>
<p>
圖 <a href="#orgparagraph3">3</a> 是我們常見的取樣圖形化分析方式<sup><a id="fnr.1" class="footref" href="#fn.1">1</a></sup>, \(F_0\) 是你觀察的訊號,他的頻率高於 \(\frac{F_s}{2}\) 。取樣後我們能看到的頻率範圍只有橘色所框住的 \([-\frac{F_s}{2}, \frac{F_s}{2}]\) 而已,所以高於 \(\frac{F_s}{2}\) 的我們就畫一條水平線,看他與橘色範圍的三角形交叉的點在哪裡,計算其頻率,那就是你取樣後的頻率。在我們這個例子中可以看到 $F<sub>c</sub> < 0$,計算出來是 $F<sub>c</sub> = F<sub>0</sub> - F<sub>s</sub> = 250 - 333.333 = -83.333 kHz$,先不看正負號,週期跟圖 <a href="#orgparagraph2">2</a> 算出來是一樣的吧?負號只是影響相位而已,不影響頻率。
</p>
</div>
</div>
<div id="outline-container-orgheadline5" class="outline-2">
<h2 id="orgheadline5"><span class="section-number-2">5</span> 結語</h2>
<div class="outline-text-2" id="text-5">
<p>
筆者發現每次寫部落格文章,最頭痛的就是畫出那精美的圖形,本來用 Python matplotlib 已經夠簡單了,不過還是要花點時間,所以部落格文章發表都拖很久,從這篇文章開始,筆者改用手繪!讓大家看到我醜醜的手寫字真是有點不好意思,不過這樣子可以發文章發得比較快一些。本篇就是承襲上一篇文章的取樣定理,在嵌入式系統或是數位設計常常會遇到的計數器問題上舉個例子,讓大家看看取樣定理是怎麼應用的,其實很常見啊,不是只有你在接收 ADC 傳進來的資料才會遇到喔!希望大家喜歡今天的文章!
</p>
</div>
</div>
<div id="footnotes">
<h2 class="footnotes">Footnotes: </h2>
<div id="text-footnotes">
<div class="footdef"><sup><a id="fn.1" class="footnum" href="#fnr.1">1</a></sup> <div class="footpara"><p class="footpara">
參見 Richard G. Lyons, "Understanding Digital Signal Processing," 3ed, Prentice-Hall, 2011.
</p></div></div>
</div>
</div></div>
<div id="postamble" class="status">
<p class="author">Author: Albert Huang</p>
<p class="date">Created: 2016-05-30 Mon 22:02</p>
<p class="validation"><a href="http://validator.w3.org/check?uri=referer">Validate</a></p>
</div>
</body>
</html>Albert Huanghttp://www.blogger.com/profile/09910403631033610841noreply@blogger.com1tag:blogger.com,1999:blog-5393693761509999841.post-57738513770055485362016-05-25T18:30:00.000+08:002018-04-05T19:46:37.257+08:00淺談取樣定理<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<!-- 2016-05-25 Wed 23:33 -->
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>淺談取樣定理</title>
<meta name="generator" content="Org-mode" />
<meta name="author" content="Albert Huang" />
<style type="text/css">
<!--/*--><![CDATA[/*><!--*/
.title { text-align: center;
margin-bottom: .2em; }
.subtitle { text-align: center;
font-size: medium;
font-weight: bold;
margin-top:0; }
.todo { font-family: monospace; color: red; }
.done { font-family: monospace; color: green; }
.priority { font-family: monospace; color: orange; }
.tag { background-color: #eee; font-family: monospace;
padding: 2px; font-size: 80%; font-weight: normal; }
.timestamp { color: #bebebe; }
.timestamp-kwd { color: #5f9ea0; }
.org-right { margin-left: auto; margin-right: 0px; text-align: right; }
.org-left { margin-left: 0px; margin-right: auto; text-align: left; }
.org-center { margin-left: auto; margin-right: auto; text-align: center; }
.underline { text-decoration: underline; }
#postamble p, #preamble p { font-size: 90%; margin: .2em; }
p.verse { margin-left: 3%; }
pre {
border: 1px solid #ccc;
box-shadow: 3px 3px 3px #eee;
padding: 8pt;
font-family: monospace;
overflow: auto;
margin: 1.2em;
}
pre.src {
position: relative;
overflow: visible;
padding-top: 1.2em;
}
pre.src:before {
display: none;
position: absolute;
background-color: white;
top: -10px;
right: 10px;
padding: 3px;
border: 1px solid black;
}
pre.src:hover:before { display: inline;}
pre.src-sh:before { content: 'sh'; }
pre.src-bash:before { content: 'sh'; }
pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
pre.src-R:before { content: 'R'; }
pre.src-perl:before { content: 'Perl'; }
pre.src-java:before { content: 'Java'; }
pre.src-sql:before { content: 'SQL'; }
table { border-collapse:collapse; }
caption.t-above { caption-side: top; }
caption.t-bottom { caption-side: bottom; }
td, th { vertical-align:top; }
th.org-right { text-align: center; }
th.org-left { text-align: center; }
th.org-center { text-align: center; }
td.org-right { text-align: right; }
td.org-left { text-align: left; }
td.org-center { text-align: center; }
dt { font-weight: bold; }
.footpara { display: inline; }
.footdef { margin-bottom: 1em; }
.figure { padding: 1em; }
.figure p { text-align: center; }
.inlinetask {
padding: 10px;
border: 2px solid gray;
margin: 10px;
background: #ffffcc;
}
#org-div-home-and-up
{ text-align: right; font-size: 70%; white-space: nowrap; }
textarea { overflow-x: auto; }
.linenr { font-size: smaller }
.code-highlighted { background-color: #ffff00; }
.org-info-js_info-navigation { border-style: none; }
#org-info-js_console-label
{ font-size: 10px; font-weight: bold; white-space: nowrap; }
.org-info-js_search-highlight
{ background-color: #ffff00; color: #000000; font-weight: bold; }
/*]]>*/-->
</style>
<script type="text/javascript">
/*
@licstart The following is the entire license notice for the
JavaScript code in this tag.
Copyright (C) 2012-2013 Free Software Foundation, Inc.
The JavaScript code in this tag is free software: you can
redistribute it and/or modify it under the terms of the GNU
General Public License (GNU GPL) as published by the Free Software
Foundation, either version 3 of the License, or (at your option)
any later version. The code is distributed WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
As additional permission under GNU GPL version 3 section 7, you
may distribute non-source (e.g., minimized or compacted) forms of
that code without the copy of the GNU GPL normally required by
section 4, provided you include this license notice and a URL
through which recipients can access the Corresponding Source.
@licend The above is the entire license notice
for the JavaScript code in this tag.
*/
<!--/*--><![CDATA[/*><!--*/
function CodeHighlightOn(elem, id)
{
var target = document.getElementById(id);
if(null != target) {
elem.cacheClassElem = elem.className;
elem.cacheClassTarget = target.className;
target.className = "code-highlighted";
elem.className = "code-highlighted";
}
}
function CodeHighlightOff(elem, id)
{
var target = document.getElementById(id);
if(elem.cacheClassElem)
elem.className = elem.cacheClassElem;
if(elem.cacheClassTarget)
target.className = elem.cacheClassTarget;
}
/*]]>*///-->
</script>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
displayAlign: "center",
displayIndent: "0em",
"HTML-CSS": { scale: 100,
linebreaks: { automatic: "false" },
webFont: "TeX"
},
SVG: {scale: 100,
linebreaks: { automatic: "false" },
font: "TeX"},
NativeMML: {scale: 100},
TeX: { equationNumbers: {autoNumber: "AMS"},
MultLineWidth: "85%",
TagSide: "right",
TagIndent: ".8em"
}
});
</script>
<script type="text/javascript" src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML"></script>
</head>
<body>
<div id="content">
<h1 class="title">淺談取樣定理</h1>
<div id="table-of-contents">
<h2>Table of Contents</h2>
<div id="text-table-of-contents">
<ul>
<li><a href="#orgheadline1">1. 來個取樣的思想實驗</a></li>
<li><a href="#orgheadline2">2. Nyquist Rate</a></li>
<li><a href="#orgheadline3">3. 取樣率與取樣頻寬</a></li>
<li><a href="#orgheadline4">4. 那我到底要多少取樣率呢?</a></li>
<li><a href="#orgheadline5">5. 說個 CD 取樣率 44.1 kHz 的小故事</a></li>
<li><a href="#orgheadline6">6. 結語</a></li>
</ul>
</div>
</div>
<div id="outline-container-orgheadline1" class="outline-2">
<h2 id="orgheadline1"><span class="section-number-2">1</span> 來個取樣的思想實驗</h2>
<div class="outline-text-2" id="text-1">
<p>
想像你的房子剛好有個窗子,能看到窗外有個摩天輪,這個摩天輪有 360 個座位,以逆時針方向依序編號,但不巧,你的視角只能看到一台車。如果你固定兩個小時的整點觀察一次該摩天輪,發現每次都是編號第 180 的車,請問該摩天輪的轉速是多少?還是該摩天輪根本就沒轉呢?
</p>
<p>
那麼如果你增加觀察的頻率,固定每個小時的整點都觀察一次該摩天輪,發現這次不一樣了,每個小時觀察到的車輛編號是 0, 180, 0, 180 交替出現,那這代表什麼呢?恭喜你,至少確定排除摩天輪不轉的可能性。那麼該摩天輪的轉速到底是多少呢?每兩個小時觀察到他會轉一整圈,那麼是每小時半圈嗎?答案是:不一定。
</p>
<p>
這次我們換個角度來想,已知摩天輪每兩個小時轉一整圈,那麼你最少要用多快的觀察頻率,才能知道摩天輪的正確轉速?
</p>
<p>
如果你用跟摩天輪轉速相同的頻率,也就是每兩個小時觀察一次,那你會跟第一段的觀察結果一樣,看到每次都一樣的車輛編號,導致你根本就不知道他到底是有轉還是沒轉。那如果你用每個小時觀察一次,也就是兩倍於摩天輪轉速的頻率來觀察,那你會看到跟第二段一樣的結果,也就是每個小時剛好是相反的位置被觀察到,換算成轉速是每小時 0.5 圈,那如果變成四倍,也就是每 30 分鐘就觀察一次呢?摩天輪每兩個小時轉一整圈,那每 30 分鐘就是轉 1/4 圈了,那你會看到 0, 90, 180, 270, 0, 90, 180, 270,換算也是每小時 0.5 圈,看來你已經可以正確觀察到摩天輪轉速了,更高的觀察頻率應該也可以觀察到正確的轉速,你心裡想。可是最少要多少頻率才能觀察到正確轉速呢?
</p>
<p>
這次我們每一個半小時觀察一次,上一段我們知道每 30 分鐘,摩天輪會轉 1/4 圈,所以每 90 分鐘觀察,摩天輪會轉 3/4 圈的角度,也就是 360 * 3/4 = 270 個車輛,從 0 開始的話,會依序觀察到 0, 270, 180, 90, 0, 270, 180, 90, 0, …….,如果這次是你第一次觀察到的結果,你可能會很興奮的下結論說這個摩天輪每 4*90=360 分鐘轉一圈,而且方向是與編號方向相反方向的。可是我們已經知道摩天輪每兩個小時轉一圈啊,這個結果跟已知不合啊。所以低於轉速兩倍的觀察頻率看來也是不行,有興趣的讀者可以嘗試其他低於兩倍的觀察頻率,看看結果是如何?
</p>
<p>
那現在同樣的摩天輪,但你搬家了,變成只能看到摩天輪的地面,剛好在編號 0 的車輛上,有一個雷射光束,永遠指著地面,而你能夠觀察到地面的雷射光束位置。
</p>
<p>
高中數學告訴我們,雷射光束的位置與編號 0 的車子被轉的角度有一個關係,那個關係叫做 \(cos \theta\), 這裡假設摩天輪的半徑是 1,那在地面雷射光束的位置就是 \(cos \theta\) 了,所以地面位置用 +1 到 -1 來表示。
</p>
<p>
回到摩天輪觀察頻率,如果我們用每兩個小時觀察一次的頻率,我們會看到雷射光束一直都指在同一個地方,為了方便描述,我們就說他一直都是在 +1.0 的位置上。畫成圖就會像圖 <a href="#orgparagraph1">1</a> 所示。
</p>
<div id="orgparagraph1" class="figure">
<p><img src="https://jjhuang314.github.io/Org/Sampling/SamplingRate_1.png" alt="SamplingRate_1.png" />
</p>
<p><span class="figure-number">Figure 1:</span> 取樣頻率等於訊號頻率</p>
</div>
<p>
那如果我們每個小時觀察一次,雷射光束指的位置又會有什麼變化呢?如果我們在相同位置觀察到 0, 180, 0, 180, ……, 那麼第 0 輛車的位置就會在 +1.0, -1.0, +1.0, -1.0, …… 變化了,畫成圖的話就變成:
</p>
<div class="figure">
<p><img src="https://jjhuang314.github.io/Org/Sampling/SamplingRate_2.png" alt="SamplingRate_2.png" />
</p>
<p><span class="figure-number">Figure 2:</span> 取樣頻率兩倍於訊號頻率</p>
</div>
<p>
在訊號處理的領域上,我們習慣將取樣到的點與 X 軸連接起來,來表示它是取樣資料,就像下圖這樣:
</p>
<div id="orgparagraph2" class="figure">
<p><img src="https://jjhuang314.github.io/Org/Sampling/SamplingRate_2_a.png" alt="SamplingRate_2_a.png" />
</p>
<p><span class="figure-number">Figure 3:</span> 週期為 2 hr,頻率 \(F = \frac{1}{2}\) cycles per hour 的正弦波,以 \(F_s = 1\) cycles per hour 來取樣(\(F_s = 2*F\))</p>
</div>
<p>
在圖 <a href="#orgparagraph2">3</a> 我們引入了週期以及頻率的觀念,這裡我們用的頻率單位是 cycles per hour,也就是每小時的轉速,轉換成每秒的轉速就變成 \(\frac{1}{3600}\) cycles per second,也就是 \(\frac{1}{3600}\) Hz(Hz 這個單位一直到 1960 年代為了紀念赫茲(Heinrich Hertz) 以後才被廣泛使用,在此之前都是以更直接的 cycles per second 這種一目了然的單位來表示),正弦波的一個週期,就是上述的摩天輪轉一圈回到原點,所以會用 cycles 喔!
</p>
<p>
那麼如果我們回頭看剛剛那個以 1.5 小時取樣率的結果,畫成圖來看呢?注意算一下圖上的訊號週期就是 6 小時(X 軸的單位就是小時),與我們剛剛計算的結果是一樣的,也就是 360 分鐘轉一圈。
</p>
<div id="orgparagraph3" class="figure">
<p><img src="https://jjhuang314.github.io/Org/Sampling/SamplingRate_1.5.png" alt="SamplingRate_1.5.png" />
</p>
<p><span class="figure-number">Figure 4:</span> F<sub>s</sub> = 1.3333 * F</p>
</div>
<p>
那我們如果取樣頻率更高一些呢?比方說四倍?我們來看一下結果:
</p>
<div id="orgparagraph4" class="figure">
<p><img src="https://jjhuang314.github.io/Org/Sampling/SamplingRate_4.png" alt="SamplingRate_4.png" />
</p>
<p><span class="figure-number">Figure 5:</span> F<sub>s</sub> = 4 * F</p>
</div>
<p>
圖 <a href="#orgparagraph4">5</a> 看起來就像是圖 <a href="#orgparagraph2">3</a> 的細緻版,只要每四點取一點,就會變成取樣率只有兩倍的那張圖。而這個「每 N 點取一點」也就是訊號處理 decimation 的基本觀念(不過當然不只有這樣,還需要做一些濾波的動作),但這就是基本的取樣率轉換的概念,在這篇文章裡面我們不詳談,有機會筆者再詳細說明。
</p>
<div id="orgparagraph5" class="figure">
<p><img src="https://jjhuang314.github.io/Org/Sampling/SamplingRate_2_b.png" alt="SamplingRate_2_b.png" />
</p>
<p><span class="figure-number">Figure 6:</span> 週期為 \(\frac{2}{3}\) hr 的正弦波,以 \(F_s = 1\) cycles per hr 取樣</p>
</div>
<p>
回到本文的第二段,為什麼看起來一樣的圖形,不一定代表一樣高的頻率訊號;圖 <a href="#orgparagraph5">6</a> 看起來跟圖 <a href="#orgparagraph2">3</a> 是完全一樣的圖形,但其實他的原始訊號頻率高三倍,不信我們將取樣率再高一些,變成 3 倍看看,如圖 <a href="#orgparagraph6">7</a> 所示。
</p>
<div id="orgparagraph6" class="figure">
<p><img src="https://jjhuang314.github.io/Org/Sampling/SamplingRate_2_c.png" alt="SamplingRate_2_c.png" />
</p>
<p><span class="figure-number">Figure 7:</span> 週期為 \(\frac{2}{3}\) hr 的正弦波,以 \(F_s = 3\) cycles per hr 取樣</p>
</div>
<p>
這是因為在數位訊號的領域上,不能表示真實的頻率,所有的頻率只剩下 [0, 1] 或是 \([0, 2\pi]\) ,前者稱為 normalized frequency, 單位是 cycles/sample,後者的單位則是 radian/sample,要轉換成真實的頻率,就需要把取樣率考量進來,變成 \([0, \frac{F_s}{2}]\) Hz,所以在數位訊號處理中,取樣率是個非常重要的參數喔!
</p>
<p>
而圖 <a href="#orgparagraph5">6</a> 取樣率是 1 cycles per hour,被取樣的訊號是 1.5 cycles per hour,最後得到的數位訊號是 1 cycles per hour,這個現象稱之為 alias,是我們一般要避免的,但有時候也會刻意採用這種取樣方式,筆者在下一篇文章會講相關的議題。
</p>
</div>
</div>
<div id="outline-container-orgheadline2" class="outline-2">
<h2 id="orgheadline2"><span class="section-number-2">2</span> Nyquist Rate</h2>
<div class="outline-text-2" id="text-2">
<p>
我們常常會聽到某訊號的 Nyquist rate 是多少?其實就是上一段直觀結論的數學版,一個 F 頻率的訊號,要用 \(F_s = 2*F\) 的取樣頻率來取樣,才能夠完整表示這個訊號,這個 \(F_s = 2*F\) 就是 Nyquist rate,有時候這又稱為取樣定理,或是 Shannon Sampling Theorem. 這裡的 Shannon 就是那個 Claude E. Shannon 啦。這起源於 19xx 年代,美國的電話公司開始數位化語音訊號,當時用的是 64kbps PCM(Pulse-Coded Modulation, 是一種用脈衝振幅來代表訊號大小的一個數位傳輸方式),為了節省頻寬,電話公司當然是要研究怎麼樣才能用最少的取樣頻率來傳遞語音訊號,Nyquist 採用的方式比較像是工程師直接量測與觀察得到的結論,而 Claude E. Shannon 則是後期利用取樣與 FFT 的關係,用數學式來描述,所以同樣內涵的取樣定理,有人稱之為 Nyquist Sampling Theorem,也有人稱之為 Shannon Sampling Theorem, 或是 Nyquist-Shannon Sampling Theorem,至於量測得到的結論,與數學式表示誰比較重要,我認為是兩者都重要,因為還沒有什麼理論是不需要實際驗證的,在理論能建構之前,大部分時候,也無法憑空想像出來,因為實驗就是了解上帝所創造的這個世界的方式。歸納永遠比演繹來得早,但歸納與演繹缺一不可;歸納能讓你了解系統現象,演繹則能讓你在腦海中從事思想實驗並大幅推廣。
</p>
</div>
</div>
<div id="outline-container-orgheadline3" class="outline-2">
<h2 id="orgheadline3"><span class="section-number-2">3</span> 取樣率與取樣頻寬</h2>
<div class="outline-text-2" id="text-3">
<p>
既然單一頻率的正弦波可以用他的 Nyquist Rate 來正確取樣,那麼所有頻率低於這個頻率的正弦波也可以用同樣的取樣率來取樣,所以我們一般會說 \(F_s \ge 2B\), \(F_s\) 是取樣率, B 是所需的訊號頻寬。
</p>
</div>
</div>
<div id="outline-container-orgheadline4" class="outline-2">
<h2 id="orgheadline4"><span class="section-number-2">4</span> 那我到底要多少取樣率呢?</h2>
<div class="outline-text-2" id="text-4">
<p>
是的,了解最低需要兩倍的取樣率之後,在訊號處理領域裡面,永遠都會再繼續問這個問題:到底要多少取樣率才夠呢?取樣率高有什麼好處與壞處?在市面上強調高取樣率的,最常見的就是音效卡,明明已經說了音樂到 20kHz 的頻寬就足夠,而 CD 取樣率也只有到 44.1kHz 而已,但你還是可以看到 96kHz 甚至 192kHz 取樣率的音效卡,那取樣率比 Nyquist rate 高這麼多有什麼用處呢?這有很多實作上的考量,先不談這個,你聽過錄製音樂的 CD 嗎?
</p>
</div>
</div>
<div id="outline-container-orgheadline5" class="outline-2">
<h2 id="orgheadline5"><span class="section-number-2">5</span> 說個 CD 取樣率 44.1 kHz 的小故事</h2>
<div class="outline-text-2" id="text-5">
<p>
一般會說人耳能夠聽到的範圍是 20 kHz,各位讀者現在也知道了只要兩倍的取樣率就足夠了,那為什麼 CD 的取樣率是 44.1 kHz 呢?那為什麼 DAT(錄音室比較常見的數位錄音帶)是 48 kHz 呢?根據維基百科,這要講到 1979 年 Sony 出了一台 PCM-1600 的裝置,可以在一般的卡帶上錄數位聲音,上面的取樣率就是 44100 Hz,因此 1980 年制定 CD 的標準的時候,就採用這個取樣率。那麼為什麼是 44100 Hz 而不是 40 kHz 呢?首先,要送進 ADC(Analog-to-Digigal Converter) 之前,要先經過一個低通濾波器,而真實世界的濾波器不會「嘎然而止」,而是會「漸漸停止」,這個「漸漸」就是 transition band,transition band 寬一點,濾波器比較容易設計,所以預留了 2.05kHz 的 transition band,那為什麼不是更多呢?當年電視是 PAL 與 NTSC 的時代,都是類比的,現在也幾乎看不到了,所以以當時的技術來說,44100 Hz 可以同時與 PAL 與 NTSC 相容,因為:
</p>
<p>
NTSC:
</p>
<ul class="org-ul">
<li>245 * 60 * 3 = 44100</li>
<li>245 active lines/field * 60 field/second * 3 samples/line = 44100 samples/second</li>
<li>每個 field 245 條垂直掃描線(整張畫面的主動掃描線是 490 條,但全部有 525 條,但 NTSC 時代每次只更新半張畫面)</li>
<li>每秒 60 field(所以每秒是 30 張)</li>
<li>主要使用在北美</li>
<li>北美交流電是 110V, 60Hz</li>
</ul>
<p>
PAL:
</p>
<ul class="org-ul">
<li>294 * 50 * 3 = 44100</li>
<li>294 active lines/field * 50 field/second * 3 samples/line = 44100 samples/second</li>
<li>每個 field 294 條垂直掃描線(整張畫面的主動掃描線是 588 條,但全部有 625 條,一樣也是每次只更新半張畫面)</li>
<li>每秒 50 fiels(所以每秒是 25 張)</li>
<li>主要使用在歐洲</li>
<li>歐洲的交流電是 110V, 50Hz</li>
</ul>
<p>
這個其實是相當好的工程範例,說明取捨(trade-off) 的藝術,也因此,當年 Sony 在標準會議上大獲全勝,於是 16 bits 44100 Hz 就 變成了 CD 的標準。1980 年代的日本在電子產業上真是強悍啊。
</p>
</div>
</div>
<div id="outline-container-orgheadline6" class="outline-2">
<h2 id="orgheadline6"><span class="section-number-2">6</span> 結語</h2>
<div class="outline-text-2" id="text-6">
<p>
對於數位訊號處理的初學者來說,取樣定理一直都是很難的一個題目,筆者一直都想寫個文章來談談取樣定理,也一直沒有太多心思來思考該如何淺顯的表達。本文的思想實驗是我認為很容易入門的方法,藉由這個思想實驗,讀者可以詳細了解取樣的動作,以及取樣會發生的效果,進而了解取樣定理所要描述的內容。取樣其實還有很多其他的題目可以探討,筆者希望這是一篇能夠讓讀者不至於懼怕取樣定理的一篇文章。
</p>
</div>
</div>
</div>
<div id="postamble" class="status">
<p class="author">Author: Albert Huang</p>
<p class="date">Created: 2016-05-25 Wed 23:33</p>
<p class="validation"><a href="http://validator.w3.org/check?uri=referer">Validate</a></p>
</div>
</body>
</html>Albert Huanghttp://www.blogger.com/profile/09910403631033610841noreply@blogger.com0tag:blogger.com,1999:blog-5393693761509999841.post-32902659280730114022015-06-30T22:33:00.002+08:002015-06-30T22:54:46.944+08:00如何為 Raspberry Pi 以及 STM32F429 Discovery Board 編譯 RTEMS<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>如何為 Raspberry Pi 以及 STM32F429 Discovery Board 編譯 RTEMS</title>
<!-- 2015-06-30 Tue 22:31 -->
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="generator" content="Org-mode" />
<meta name="author" content="Albert Huang" />
<style type="text/css">
<!--/*--><![CDATA[/*><!--*/
.title { text-align: center; }
.todo { font-family: monospace; color: red; }
.done { color: green; }
.tag { background-color: #eee; font-family: monospace;
padding: 2px; font-size: 80%; font-weight: normal; }
.timestamp { color: #bebebe; }
.timestamp-kwd { color: #5f9ea0; }
.right { margin-left: auto; margin-right: 0px; text-align: right; }
.left { margin-left: 0px; margin-right: auto; text-align: left; }
.center { margin-left: auto; margin-right: auto; text-align: center; }
.underline { text-decoration: underline; }
#postamble p, #preamble p { font-size: 90%; margin: .2em; }
p.verse { margin-left: 3%; }
pre {
border: 1px solid #ccc;
box-shadow: 3px 3px 3px #eee;
padding: 8pt;
font-family: monospace;
overflow: auto;
margin: 1.2em;
}
pre.src {
position: relative;
overflow: visible;
padding-top: 1.2em;
}
pre.src:before {
display: none;
position: absolute;
background-color: white;
top: -10px;
right: 10px;
padding: 3px;
border: 1px solid black;
}
pre.src:hover:before { display: inline;}
pre.src-sh:before { content: 'sh'; }
pre.src-bash:before { content: 'sh'; }
pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
pre.src-R:before { content: 'R'; }
pre.src-perl:before { content: 'Perl'; }
pre.src-java:before { content: 'Java'; }
pre.src-sql:before { content: 'SQL'; }
table { border-collapse:collapse; }
caption.t-above { caption-side: top; }
caption.t-bottom { caption-side: bottom; }
td, th { vertical-align:top; }
th.right { text-align: center; }
th.left { text-align: center; }
th.center { text-align: center; }
td.right { text-align: right; }
td.left { text-align: left; }
td.center { text-align: center; }
dt { font-weight: bold; }
.footpara:nth-child(2) { display: inline; }
.footpara { display: block; }
.footdef { margin-bottom: 1em; }
.figure { padding: 1em; }
.figure p { text-align: center; }
.inlinetask {
padding: 10px;
border: 2px solid gray;
margin: 10px;
background: #ffffcc;
}
#org-div-home-and-up
{ text-align: right; font-size: 70%; white-space: nowrap; }
textarea { overflow-x: auto; }
.linenr { font-size: smaller }
.code-highlighted { background-color: #ffff00; }
.org-info-js_info-navigation { border-style: none; }
#org-info-js_console-label
{ font-size: 10px; font-weight: bold; white-space: nowrap; }
.org-info-js_search-highlight
{ background-color: #ffff00; color: #000000; font-weight: bold; }
/*]]>*/-->
</style>
<script type="text/javascript">
/*
@licstart The following is the entire license notice for the
JavaScript code in this tag.
Copyright (C) 2012-2013 Free Software Foundation, Inc.
The JavaScript code in this tag is free software: you can
redistribute it and/or modify it under the terms of the GNU
General Public License (GNU GPL) as published by the Free Software
Foundation, either version 3 of the License, or (at your option)
any later version. The code is distributed WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
As additional permission under GNU GPL version 3 section 7, you
may distribute non-source (e.g., minimized or compacted) forms of
that code without the copy of the GNU GPL normally required by
section 4, provided you include this license notice and a URL
through which recipients can access the Corresponding Source.
@licend The above is the entire license notice
for the JavaScript code in this tag.
*/
<!--/*--><![CDATA[/*><!--*/
function CodeHighlightOn(elem, id)
{
var target = document.getElementById(id);
if(null != target) {
elem.cacheClassElem = elem.className;
elem.cacheClassTarget = target.className;
target.className = "code-highlighted";
elem.className = "code-highlighted";
}
}
function CodeHighlightOff(elem, id)
{
var target = document.getElementById(id);
if(elem.cacheClassElem)
elem.className = elem.cacheClassElem;
if(elem.cacheClassTarget)
target.className = elem.cacheClassTarget;
}
/*]]>*///-->
</script>
</head>
<body>
<div id="content">
<h1 class="title">如何為 Raspberry Pi 以及 STM32F429 Discovery Board 編譯 RTEMS</h1>
<div id="table-of-contents">
<h2>Table of Contents</h2>
<div id="text-table-of-contents">
<ul>
<li><a href="#sec-1">1. 前言</a></li>
<li><a href="#sec-2">2. 準備檔案</a></li>
<li><a href="#sec-3">3. Bootstrap</a></li>
<li><a href="#sec-4">4. configure</a></li>
<li><a href="#sec-5">5. 編譯</a></li>
<li><a href="#sec-6">6. 文件位置</a></li>
<li><a href="#sec-7">7. RTEMS BSP 介紹</a>
<ul>
<li><a href="#sec-7-1">7.1. Raspberry Pi</a></li>
<li><a href="#sec-7-2">7.2. STM32F4</a></li>
</ul>
</li>
<li><a href="#sec-8">8. 結語</a></li>
</ul>
</div>
</div>
<p>
-*- truncate-lines: nil -*-
</p>
<div id="outline-container-sec-1" class="outline-2">
<h2 id="sec-1"><span class="section-number-2">1</span> 前言</h2>
<div class="outline-text-2" id="text-1">
<p>
上一篇文章講到了<a href="http://alberthuang314.blogspot.tw/2015/06/macosx-rtems-toolchain.html">如何在 OS X 上編譯 RTEMS 的 toolchain</a>,隔了好一陣子,相信有些人應該已經研究完如何編譯 RTEMS 的 source code,
沒有研究的也沒關係,筆者今天就要來講述一下如何編譯 RTEMS source code 給 Raspberry Pi 或是 STM32F429 Discovery Board 使用。
</p>
</div>
</div>
<div id="outline-container-sec-2" class="outline-2">
<h2 id="sec-2"><span class="section-number-2">2</span> 準備檔案</h2>
<div class="outline-text-2" id="text-2">
<p>
先 checkout RTEMS 的 source code,嗯,git 的動詞是 clone,URL 是 <code>git://git.rtems.org/rtems.git</code>, 請在終端機中輸入以下命令:
</p>
<pre class="example">
$ cd ~/Projects/rtems
$ git clone git://git.rtems.org/rtems.git
Cloning into 'rtems'...
remote: Counting objects: 473959, done.
remote: Compressing objects: 100% (85745/85745), done.
remote: Total 473959 (delta 382898), reused 467269 (delta 377943)
Receiving objects: 100% (473959/473959), 65.15 MiB | 1.33 MiB/s, done.
Resolving deltas: 100% (382898/382898), done.
Checking connectivity... done.
</pre>
<p>
這樣會產生 <code>~/Projects/rtems/rtems</code> 的目錄
</p>
</div>
</div>
<div id="outline-container-sec-3" class="outline-2">
<h2 id="sec-3"><span class="section-number-2">3</span> Bootstrap</h2>
<div class="outline-text-2" id="text-3">
<p>
<code>bootstrap</code> script 是拿來產生 configure 檔案的,如果你要修改 BSP 的 configure.ac,就要在執行 bootstrap 之前,或是修改之後,重新執行一次 boostrap
</p>
<pre class="example">
$ cd ~/Projects/rtems/rtems
$ ./bootstrap
</pre>
<p>
這大概要花幾分鐘的時間
</p>
</div>
</div>
<div id="outline-container-sec-4" class="outline-2">
<h2 id="sec-4"><span class="section-number-2">4</span> configure</h2>
<div class="outline-text-2" id="text-4">
<p>
執行完上一節的 bootstrap 之後,=configure= scripts 就全部都產生完成,現在我們要建立一個編譯的目錄。
RTEMS 分成 build tree 跟 source tree,build tree 就是剛剛 git clone 出來的 <code>~/Projects/rtems/rtems</code>,
但實際編譯的時候要在另一個 build tree 的目錄,source tree 中各目錄的 preinstall.am 就是拿來產生 build tree 的。
不過現在還不用擔心這件事,先來編譯如下:
</p>
<pre class="example">
$ cd ~/Projects/rtems
$ mkdir build-raspberrypi
</pre>
<p>
或是
</p>
<pre class="example">
$ cd ~/Projects/rtems
$ mkdir build-stm32f4
</pre>
<p>
執行 configure script for Raspberry Pi:
</p>
<pre class="example">
$ cd build-raspberrypi
$ ../rtems/configure --enable-tests=samples \
--enable-cxx --enable-posix --enable-networking --enable-doc \
--target=arm-rtems4.11 --prefix=$HOME/Projects/rtems/bsps/4.11
--enable-rtemsbsp=raspberrypi
</pre>
<p>
執行 configure script for STM32F429:
</p>
<pre class="example">
$ cd build-stm32f4
$ ../rtems/configure --enable-tests=samples \
--enable-cxx --enable-posix --enable-networking --enable-doc \
--target=arm-rtems4.11 --prefix=$HOME/Projects/rtems/bsps/4.11
--enable-rtemsbsp=stm32f4
</pre>
<p>
最後你必須看到 available BSPs: raspberrypi 或是 stm32f4 才算是成功,不然無法正常編譯
</p>
<pre class="example">
configure: creating ./config.status
config.status: creating Makefile
target architecture: arm.
available BSPs: raspberrypi.
'make all' will build the following BSPs: raspberrypi.
other BSPs can be built with 'make RTEMS_BSP="bsp1 bsp2 ..."'
config.status: creating Makefile
</pre>
</div>
</div>
<div id="outline-container-sec-5" class="outline-2">
<h2 id="sec-5"><span class="section-number-2">5</span> 編譯</h2>
<div class="outline-text-2" id="text-5">
<pre class="example">
$ make all
</pre>
<p>
這在筆者的電腦上大約花費三分鐘即可
</p>
<pre class="example">
$ make install
</pre>
</div>
</div>
<div id="outline-container-sec-6" class="outline-2">
<h2 id="sec-6"><span class="section-number-2">6</span> 文件位置</h2>
<div class="outline-text-2" id="text-6">
<p>
因為 configure 的時候有帶入 <code>--enable-doc</code> 的參數,所以 doc 也會編譯成功(或失敗),RTEMS 的文件是用 texinfo 寫成,你需要有 texinfo 的環境才能產生 PDF 以及 info 檔,若這邊失敗的話,請重新 configure 並且把 <code>--enable-doc</code> 選項拿掉,再重新 make all 即可。
</p>
<p>
如果你文件編譯成功的話,info 檔會被安裝到 <code>~/Projects/rtems/bsps/4.11/share/info</code>, 可以把這個目錄加到你的 info 閱讀器(比如說 GNU Emacs)的目錄中。
</p>
<p>
至於其他的 dvi, pdf, html, ps 則會在 <code>~/Projects/rtems/bsps/4.11/share/rtems</code> 目錄下,基本上這些檔案跟 rtems.org 上的是一樣的,直接從 rtems.org 上取得也可以。如果想要發展應用程式,請先找 <i>RTEMS C User's Guide</i> (<code>c_user.pdf</code>),如果想發展 BSP 以及 device driver,則還要搭配 <i>BSP and Device Driver Development Guide</i> (<code>bsp_howto.pdf</code>)。
</p>
</div>
</div>
<div id="outline-container-sec-7" class="outline-2">
<h2 id="sec-7"><span class="section-number-2">7</span> RTEMS BSP 介紹</h2>
<div class="outline-text-2" id="text-7">
<p>
每一個 BSP 都在 RTEMS source tree 裡面的 <code>c/src/lib/libbsp/$CPU</code> 裡面,Raspberry Pi 以及 STM32F429 Discovery Board 都是 ARM 架構的,因此都會在 <code>c/src/lib/libbsp/arm</code> 裡面。
</p>
</div>
<div id="outline-container-sec-7-1" class="outline-3">
<h3 id="sec-7-1"><span class="section-number-3">7.1</span> Raspberry Pi</h3>
<div class="outline-text-3" id="text-7-1">
<p>
在 <code>c/src/lib/libbsp/arm/raspberrypi/make/custom</code> 目錄下,有好幾個檔案:
</p>
<pre class="example">
$ ls
raspberrypi.cfg raspberrypi.inc raspberrypi2.cfg
</pre>
<p>
這底下的命名規則就是 <code>$BSP.cfg</code>, 其中 raspberrypi.cfg 就是給 raspberrypi 這個 BSP 使用的, 而 raspberrypi2.cfg 就是給 Raspberry Pi 2 使用的了。這裡面的設定檔跟 compiler options 有關,舉 raspberrypi.cfg 的內容為例:
</p>
<pre class="example">
#
# Config file for RASPBERRYPI
#
include $(RTEMS_ROOT)/make/custom/raspberrypi.inc
CPU_CFLAGS = -mcpu=arm1176jzf-s
</pre>
<p>
而 raspberrypi.inc 內容則是:
</p>
<pre class="example">
#
# Config file for Raspberry Pi variants.
#
include $(RTEMS_ROOT)/make/custom/default.cfg
RTEMS_CPU = arm
CFLAGS_OPTIMIZE_V ?= -O2 -g
# This defines the operations performed on the linked executable.
# is currently required.
define bsp-post-link
$(OBJCOPY) -O binary --strip-all \
$(basename $@)$(EXEEXT) $(basename $@)$(DOWNEXT)
$(SIZE) $(basename $@)$(EXEEXT)
endef
</pre>
<p>
這些都是給 gcc 的參數,或是 bsp link 完成的時候會執行的動作(<code>bsp-post-link</code>),如果你不想要編譯器最佳化的話,可以從這個檔案修改。
</p>
</div>
</div>
<div id="outline-container-sec-7-2" class="outline-3">
<h3 id="sec-7-2"><span class="section-number-3">7.2</span> STM32F4</h3>
<div class="outline-text-3" id="text-7-2">
<p>
在 <code>c/src/lib/libbsp/arm/stm32f4/make/custom</code> 目錄下,有幾個檔案:
</p>
<pre class="example">
$ ls
stm32f105rc-testsuite.tcfg stm32f105rc.cfg stm32f4-testsuite.tcfg stm32f4.cfg
</pre>
<p>
按照剛剛的規則, stm32f4 自然是使用 stm32f4.cfg 了。
</p>
<p>
接下來我們來看 STM32F4 BSP 的 configure.ac:
</p>
<pre class="example">
RTEMS_BSPOPTS_SET([STM32F4_FAMILY_F10XXX],[stm32f1*],[1])
RTEMS_BSPOPTS_HELP([STM32F4_FAMILY_F10XXX],[Chip belongs to the STM32F10XXX family.])
RTEMS_BSPOPTS_SET([STM32F4_FAMILY_F4XXXX],[stm32f4*],[1])
RTEMS_BSPOPTS_HELP([STM32F4_FAMILY_F4XXXX],[Chip belongs to the STM32F4XXXX family.])
RTEMS_BSPOPTS_SET([STM32F4_HSE_OSCILLATOR],[*],[8000000])
RTEMS_BSPOPTS_HELP([STM32F4_HSE_OSCILLATOR],[HSE oscillator frequency in Hz])
RTEMS_BSPOPTS_SET([STM32F4_SYSCLK],[stm32f1*],[8000000])
RTEMS_BSPOPTS_SET([STM32F4_SYSCLK],[*],[16000000])
RTEMS_BSPOPTS_HELP([STM32F4_SYSCLK],[SYSCLK frequency in Hz])
</pre>
<p>
這邊可以看到 configure.ac 定義了兩種 BSP variant,分別是 stm32f1*,stm32f4*, 分別會產生不同的 configure 內容, 如果你的 configure 選項給的是 <code>--enable-rtemsbsp=stm32f105rc</code> 就會選擇 stm32f1* 的選項,產生在 <code>~/Projects/rtems/build-stm32f4/arm-rtems4.11/c/stm32f4/lib/libbsp/arm/stm32f4/include/bspopts.h</code> 裡面,這個之後可能會用到,在這篇文章預先介紹。如果你的版子有不同於預設的振盪器頻率,就需要修改 configure.ac,修改完之後,請重新執行 bootstrap=>configure=>make all=>make install 這個流程。
</p>
</div>
</div>
</div>
<div id="outline-container-sec-8" class="outline-2">
<h2 id="sec-8"><span class="section-number-2">8</span> 結語</h2>
<div class="outline-text-2" id="text-8">
<p>
在本文中,筆者介紹了如何下載以及針對 Raspberry Pi 以及 STM32F429 Discovery Board 編譯 RTEMS 的 source code,筆者在我的電腦上兩個都編譯成功,離執行還有點路,基本上筆者在工作場合用的不是這兩個 BSP,所以讀者就跟著我一直來探索吧,下一篇文章就會介紹如何下載 binary 在這兩張版子上並且執行 samples 的測試程式,到時候可能需要修改一些參數,筆者也會一一說明。
</p>
</div>
</div>
</div>
<div id="postamble" class="status">
<p class="author">Author: Albert Huang</p>
<p class="date">Created: 2015-06-30 Tue 22:31</p>
<p class="creator"><a href="http://www.gnu.org/software/emacs/">Emacs</a> 24.5.1 (<a href="http://orgmode.org">Org</a> mode 8.2.10)</p>
<p class="validation"><a href="http://validator.w3.org/check?uri=referer">Validate</a></p>
</div>
</body>
</html>
Albert Huanghttp://www.blogger.com/profile/09910403631033610841noreply@blogger.com0tag:blogger.com,1999:blog-5393693761509999841.post-76516332854635443792015-06-07T21:47:00.002+08:002015-06-30T21:02:20.496+08:00如何在 MacOSX 上安裝 RTEMS toolchain<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<!-- 2015-06-07 Sun 21:44 -->
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="generator" content="Org-mode" />
<meta name="author" content="Albert Huang" />
<style type="text/css">
<!--/*--><![CDATA[/*><!--*/
.title { text-align: center; }
.todo { font-family: monospace; color: red; }
.done { color: green; }
.tag { background-color: #eee; font-family: monospace;
padding: 2px; font-size: 80%; font-weight: normal; }
.timestamp { color: #bebebe; }
.timestamp-kwd { color: #5f9ea0; }
.right { margin-left: auto; margin-right: 0px; text-align: right; }
.left { margin-left: 0px; margin-right: auto; text-align: left; }
.center { margin-left: auto; margin-right: auto; text-align: center; }
.underline { text-decoration: underline; }
#postamble p, #preamble p { font-size: 90%; margin: .2em; }
p.verse { margin-left: 3%; }
pre {
border: 1px solid #ccc;
box-shadow: 3px 3px 3px #eee;
padding: 8pt;
font-family: monospace;
overflow: auto;
margin: 1.2em;
}
pre.src {
position: relative;
overflow: visible;
padding-top: 1.2em;
}
pre.src:before {
display: none;
position: absolute;
background-color: white;
top: -10px;
right: 10px;
padding: 3px;
border: 1px solid black;
}
pre.src:hover:before { display: inline;}
pre.src-sh:before { content: 'sh'; }
pre.src-bash:before { content: 'sh'; }
pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
pre.src-R:before { content: 'R'; }
pre.src-perl:before { content: 'Perl'; }
pre.src-java:before { content: 'Java'; }
pre.src-sql:before { content: 'SQL'; }
table { border-collapse:collapse; }
caption.t-above { caption-side: top; }
caption.t-bottom { caption-side: bottom; }
td, th { vertical-align:top; }
th.right { text-align: center; }
th.left { text-align: center; }
th.center { text-align: center; }
td.right { text-align: right; }
td.left { text-align: left; }
td.center { text-align: center; }
dt { font-weight: bold; }
.footpara:nth-child(2) { display: inline; }
.footpara { display: block; }
.footdef { margin-bottom: 1em; }
.figure { padding: 1em; }
.figure p { text-align: center; }
.inlinetask {
padding: 10px;
border: 2px solid gray;
margin: 10px;
background: #ffffcc;
}
#org-div-home-and-up
{ text-align: right; font-size: 70%; white-space: nowrap; }
textarea { overflow-x: auto; }
.linenr { font-size: smaller }
.code-highlighted { background-color: #ffff00; }
.org-info-js_info-navigation { border-style: none; }
#org-info-js_console-label
{ font-size: 10px; font-weight: bold; white-space: nowrap; }
.org-info-js_search-highlight
{ background-color: #ffff00; color: #000000; font-weight: bold; }
/*]]>*/-->
</style>
<script type="text/javascript">
/*
@licstart The following is the entire license notice for the
JavaScript code in this tag.
Copyright (C) 2012-2013 Free Software Foundation, Inc.
The JavaScript code in this tag is free software: you can
redistribute it and/or modify it under the terms of the GNU
General Public License (GNU GPL) as published by the Free Software
Foundation, either version 3 of the License, or (at your option)
any later version. The code is distributed WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
As additional permission under GNU GPL version 3 section 7, you
may distribute non-source (e.g., minimized or compacted) forms of
that code without the copy of the GNU GPL normally required by
section 4, provided you include this license notice and a URL
through which recipients can access the Corresponding Source.
@licend The above is the entire license notice
for the JavaScript code in this tag.
*/
<!--/*--><![CDATA[/*><!--*/
function CodeHighlightOn(elem, id)
{
var target = document.getElementById(id);
if(null != target) {
elem.cacheClassElem = elem.className;
elem.cacheClassTarget = target.className;
target.className = "code-highlighted";
elem.className = "code-highlighted";
}
}
function CodeHighlightOff(elem, id)
{
var target = document.getElementById(id);
if(elem.cacheClassElem)
elem.className = elem.cacheClassElem;
if(elem.cacheClassTarget)
target.className = elem.cacheClassTarget;
}
/*]]>*///-->
</script>
</head>
<body>
<div id="content">
<div id="table-of-contents">
<div id="text-table-of-contents">
<ul>
<li><a href="#sec-1">1. 簡介 RTEMS</a></li>
<li><a href="#sec-2">2. 環境</a></li>
<li><a href="#sec-3">3. 如果你已經安裝了 MacPorts,就順便裝這些套件吧</a>
<ul>
<li><a href="#sec-3-1">3.1. Xcode</a></li>
<li><a href="#sec-3-2">3.2. Python</a></li>
</ul>
</li>
<li><a href="#sec-4">4. 決定你的目錄</a></li>
<li><a href="#sec-5">5. 在 MacOSX 上安裝 toolchain</a>
<ul>
<li><a href="#sec-5-1">5.1. git clone rtems-source-builder</a></li>
<li><a href="#sec-5-2">5.2. 檢查編譯環境</a></li>
<li><a href="#sec-5-3">5.3. 編譯並安裝 ARM cross compiler</a></li>
<li><a href="#sec-5-4">5.4. 修改 gdb-7-1.cfg</a></li>
<li><a href="#sec-5-5">5.5. 檢查工具版本</a>
<ul>
<li><a href="#sec-5-5-1">5.5.1. gcc 4.9.2</a></li>
<li><a href="#sec-5-5-2">5.5.2. gdb 7.9</a></li>
<li><a href="#sec-5-5-3">5.5.3. 測試 gdb 的 python 功能:</a></li>
</ul>
</li>
<li><a href="#sec-5-6">5.6. 記得把 compiler 加入你的 $PATH</a></li>
</ul>
</li>
<li><a href="#sec-6">6. 結語</a></li>
</ul>
</div>
</div>
<div id="outline-container-sec-1" class="outline-2">
<h2 id="sec-1"><span class="section-number-2">1</span> 簡介 RTEMS</h2>
<div class="outline-text-2" id="text-1">
<p>
<a href="http://www.rtems.org">RTEMS</a>(Real-Time Executive for Multiprocessor Systems) 是一套 open source 的即時作業系統,由 OAR 公司維護,以 GPL license 發行。RTEMS 目前還使用在環繞火星的無線電設備上。
</p>
<p>
要編譯 RTEMS 必須使用 RTEMS compiler,不能使用 ARM bare metal GCC,所以就來先編譯這些工具吧。
</p>
</div>
</div>
<div id="outline-container-sec-2" class="outline-2">
<h2 id="sec-2"><span class="section-number-2">2</span> 環境</h2>
<div class="outline-text-2" id="text-2">
<p>
筆者的電腦上安裝了 MacPorts,因此這一篇文章是基於 MacPorts 的環境,若完全沒有安裝 MacPorts,環境會更單純一點,安裝過程會很順利,這是由於 RTEMS.org 的測試都預設使用者沒有 MacPorts/Homebrew。
</p>
</div>
</div>
<div id="outline-container-sec-3" class="outline-2">
<h2 id="sec-3"><span class="section-number-2">3</span> 如果你已經安裝了 MacPorts,就順便裝這些套件吧</h2>
<div class="outline-text-2" id="text-3">
</div><div id="outline-container-sec-3-1" class="outline-3">
<h3 id="sec-3-1"><span class="section-number-3">3.1</span> Xcode</h3>
<div class="outline-text-3" id="text-3-1">
<p>
這個 MacPorts 也需要
</p>
</div>
</div>
<div id="outline-container-sec-3-2" class="outline-3">
<h3 id="sec-3-2"><span class="section-number-3">3.2</span> Python</h3>
<div class="outline-text-3" id="text-3-2">
<p>
python27 或 python34 都可以
</p>
</div>
<div id="outline-container-sec-3-2" class="outline-3">
<h3 id="sec-3-2"><span class="section-number-3">3.2</span> MacPorts 其他套件</h3>
<div class="outline-text-3" id="text-3-2">
<p>
$ sudo port install xz cvs
</p>
</div>
</div>
</div>
</div>
<div id="outline-container-sec-4" class="outline-2">
<h2 id="sec-4"><span class="section-number-2">4</span> 決定你的目錄</h2>
<div class="outline-text-2" id="text-4">
<p>
先決定你的 RTEMS 根目錄,然後分別建立子目錄如下:
</p>
<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">
<colgroup>
<col class="left" />
<col class="left" />
</colgroup>
<thead>
<tr>
<th scope="col" class="left">目錄</th>
<th scope="col" class="left">描述</th>
</tr>
</thead>
<tbody>
<tr>
<td class="left">~/Projects/rtems</td>
<td class="left">所有 RTEMS 的根目錄</td>
</tr>
<tr>
<td class="left">~/Projects/rtems/compiler</td>
<td class="left">RTEMS 編譯器目錄</td>
</tr>
<tr>
<td class="left">~/Projects/rtems/rtems-source-builder</td>
<td class="left">RTEMS source builder tool</td>
</tr>
<tr>
<td class="left">~/Projects/rtems/rtems-git</td>
<td class="left">RTEMS git 源碼位置</td>
</tr>
<tr>
<td class="left">~/Projects/rtems/bsps</td>
<td class="left">RTEMS 的 BSP 放置目錄</td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="outline-container-sec-5" class="outline-2">
<h2 id="sec-5"><span class="section-number-2">5</span> 在 MacOSX 上安裝 toolchain</h2>
<div class="outline-text-2" id="text-5">
</div><div id="outline-container-sec-5-1" class="outline-3">
<h3 id="sec-5-1"><span class="section-number-3">5.1</span> git clone rtems-source-builder</h3>
<div class="outline-text-3" id="text-5-1">
<pre class="example">
$ cd $HOME/Projects/rtems
$ git clone git://git.rtems.org/rtems-source-builder.git
</pre>
</div>
</div>
<div id="outline-container-sec-5-2" class="outline-3">
<h3 id="sec-5-2"><span class="section-number-3">5.2</span> 檢查編譯環境</h3>
<div class="outline-text-3" id="text-5-2">
<p>
在命令列下以下的命令檢查環境:
</p>
<pre class="example">
$ rtems-source-builder/source-builder/sb-check
</pre>
<p>
應該會在終端機看到以下的反應:
</p>
<pre class="example">
RTEMS Source Builder - Check, v0.5.0
Environment is ok
</pre>
</div>
</div>
<div id="outline-container-sec-5-3" class="outline-3">
<h3 id="sec-5-3"><span class="section-number-3">5.3</span> 編譯並安裝 ARM cross compiler</h3>
<div class="outline-text-3" id="text-5-3">
<p>
rtems-source-builder 會自動抓取 source tarball,編譯,並且自動安裝到指定的 <code>--prefix</code> 目錄。
</p>
<pre class="example">
$ cd $HOME/Projects/rtems/rtems-source-builder/rtems
$ ../source-builder/sb-set-builder \
--log=build-log.txt \
--prefix=$HOME/Projects/rtems/compiler/4.11 \
4.11/rtems-arm
</pre>
<p>
每一組工具的編譯設定稱為 build-set,檔案結尾是 .bset,一般來說是不太會需要碰到這個檔案。4.11/rtems-arm 是指 <code>$HOME/Projects/rtems/rtems-source-builder/rtems/config/4.11/rtems-arm.bset</code> 這個 build-set。
</p>
<p>
安裝過程前面一小段訊息如下:
</p>
<pre class="example">
RTEMS Source Builder - Set Builder, v0.5.0
Build Set: 4.11/rtems-arm
Build Set: 4.11/rtems-autotools.bset
Build Set: 4.11/rtems-autotools-internal.bset
config: tools/rtems-autoconf-2.69-1.cfg
package: autoconf-2.69-x86_64-apple-darwin14.3.0-1
Creating source directory: sources
......
</pre>
<p>
然後如果你的編譯訊息在這裡結束,那麼你就要參考下一節修改檔案了。
</p>
<pre class="example">
building: arm-rtems4.11-gdb-7.9-x86_64-apple-darwin14.3.0-1
error: building arm-rtems4.11-gdb-7.9-x86_64-apple-darwin14.3.0-1
Build FAILED
See error report: rsb-report-arm-rtems4.11-gdb-7.9-x86_64-apple-darwin14.3.0-1.txt
error: building arm-rtems4.11-gdb-7.9-x86_64-apple-darwin14.3.0-1
Build Set: Time 0:35:38.935340
Build FAILED
</pre>
<p>
以下是編譯成功的訊息,如果你看到最後訊息是這樣,那恭喜你,ARM compiler for RTEMS 已經結束了。
</p>
<pre class="example">
cleaning: expat-2.1.0-x86_64-apple-darwin14.3.0-1
cleaning: arm-rtems4.11-binutils-2.24-x86_64-apple-darwin14.3.0-1
cleaning: arm-rtems4.11-gcc-4.9.2-newlib-2.2.0.20150423-x86_64-apple-darwin14.3.0-1
cleaning: arm-rtems4.11-gdb-7.9-x86_64-apple-darwin14.3.0-1
cleaning: rtems-tools-HEAD-1
Build Set: Time 0:34:53.361267
</pre>
</div>
</div>
<div id="outline-container-sec-5-4" class="outline-3">
<h3 id="sec-5-4"><span class="section-number-3">5.4</span> 修改 gdb-7-1.cfg</h3>
<div class="outline-text-3" id="text-5-4">
<p>
先看剛剛的 error report 說什麼
</p>
<pre class="example">
$ less $HOME/Projects/rtems/rtems-source-builder/rtems/rsb-report-arm-rtems4.11-gdb-7.9-x86_64-apple-darwin14.3.0-1.txt
</pre>
<p>
錯誤訊息如下:
</p>
<pre class="example">
checking whether to use python... yes
checking for python... /opt/local/bin/python
checking for python2.7... no
configure: error: python is missing or unusable
make[1]: *** [configure-gdb] Error 1
make: *** [all] Error 2
</pre>
<p>
那這是因為安裝 MacPorts 的 Python 而導致的錯誤,如果你打算繼續使用 MacPorts,那就要修改檔案。筆者是透過指定使用系統內建的 Python 而成功編譯,方法如下:
修改 <code>$HOME/Projects/rtems/rtems-source-builder/source-builder/config/gdb-7-1.cfg</code>
找到這一行:
</p>
<pre class="example">
%{!?without_python:--with-python} \
</pre>
<p>
修改成:
</p>
<pre class="example">
%{!?without_python:--with-python=/usr/bin/python} \
</pre>
<p>
你如果在最近這一陣子編譯,可以直接修改 gdb-7-1.cfg 之後再執行 sb-set-builder 開始編譯與安裝的動作,不過如果跟這篇文章的寫作相隔有一段時間,因為 RTEMS 的更新速度很快,筆者建議還是先照原來的方法編譯,若有錯誤訊息再找出解法。
</p>
</div>
</div>
<div id="outline-container-sec-5-5" class="outline-3">
<h3 id="sec-5-5"><span class="section-number-3">5.5</span> 檢查工具版本</h3>
<div class="outline-text-3" id="text-5-5">
</div><div id="outline-container-sec-5-5-1" class="outline-4">
<h4 id="sec-5-5-1"><span class="section-number-4">5.5.1</span> gcc 4.9.2</h4>
<div class="outline-text-4" id="text-5-5-1">
<pre class="example">
$ $HOME/Projects/rtems/compiler/4.11/bin/arm-rtems4.11-gcc --version
arm-rtems4.11-gcc (GCC) 4.9.2 20141030 (RTEMS 4.11, RSB 18cea20a12db4d2951e8e8a2dc17fc83c394c1fb-modified, Newlib 2.2.0.20150423)
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
</pre>
</div>
</div>
<div id="outline-container-sec-5-5-2" class="outline-4">
<h4 id="sec-5-5-2"><span class="section-number-4">5.5.2</span> gdb 7.9</h4>
<div class="outline-text-4" id="text-5-5-2">
<pre class="example">
$ $HOME/Projects/rtems/compiler/4.11/bin/arm-rtems4.11-gdb --version
GNU gdb (GDB) 7.9
Copyright (C) 2015 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-apple-darwin14.3.0 --target=arm-rtems4.11".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
</pre>
</div>
</div>
<div id="outline-container-sec-5-5-3" class="outline-4">
<h4 id="sec-5-5-3"><span class="section-number-4">5.5.3</span> 測試 gdb 的 python 功能:</h4>
<div class="outline-text-4" id="text-5-5-3">
<pre class="example">
$ arm-rtems4.11-gdb
GNU gdb (GDB) 7.9
Copyright (C) 2015 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-apple-darwin14.3.0 --target=arm-rtems4.11".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb) python
>print('test')
>test
(gdb)
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-5-6" class="outline-3">
<h3 id="sec-5-6"><span class="section-number-3">5.6</span> 記得把 compiler 加入你的 $PATH</h3>
<div class="outline-text-3" id="text-5-6">
<p>
如果你是使用 BASH,可以編輯 ~/.profile
</p>
<div class="org-src-container">
<pre class="src src-shell">export PATH="$HOME/Projects/rtems/compiler/4.11/bin:$PATH"
</pre>
</div>
<p>
做完之後記得更新 $PATH 並測試 $PATH 是否生效:
</p>
<div class="org-src-container">
<pre class="src src-shell">$ source ~/.profile
$ arm-rtems-gcc
arm-rtems4.11-gcc: fatal error: no input files
compilation terminated.
</pre>
</div>
</div>
</div>
</div>
<div id="outline-container-sec-6" class="outline-2">
<h2 id="sec-6"><span class="section-number-2">6</span> 結語</h2>
<div class="outline-text-2" id="text-6">
<p>
RTEMS 是一套很有趣的 open source 即時作業系統,光是應用在航太與武器系統上,就令人眼睛為之一亮了,支援的即時排程演算法也頗完整,有最普遍的 Rate Monotonic Scheduling(RMS), 以及 Earliest Deadline First(EDF) 等等。
</p>
<p>
本篇文章介紹了如何在 Mac 上編譯 RTEMS 的開發工具,尤其是 gdb,沒有了 Python,gdb 就沒這麼好用,因此筆者花了點時間搞定了 gdb with python 的編譯問題,在這篇文章跟大家分享經驗,接下來筆者將會開始介紹如何編譯 RTEMS source code,請有興趣的人拭目以待。
</p>
</div>
</div>
</div>
<div id="postamble" class="status">
<p class="author">Author: Albert Huang</p>
<p class="date">Created: 2015-06-07 Sun 21:44</p>
<p class="creator"><a href="http://www.gnu.org/software/emacs/">Emacs</a> 24.4.1 (<a href="http://orgmode.org">Org</a> mode 8.2.10)</p>
<p class="validation"><a href="http://validator.w3.org/check?uri=referer">Validate</a></p>
</div>
</body>
</html>Albert Huanghttp://www.blogger.com/profile/09910403631033610841noreply@blogger.com4tag:blogger.com,1999:blog-5393693761509999841.post-78000756882467535532014-12-03T11:33:00.000+08:002014-12-04T08:08:16.113+08:00原則導向與規則導向因為媒體人提到了柯 P 在新聞面對面專訪結束之後,問了「怎麼樣才能勝選但又不用讓馬英九下台」,所以昨夜花了點時間看了柯文哲與連勝文在新聞面對面的專訪,並且比較兩個人的特質。
<br><br>
我想點出來的是,連勝文是規則導向(rule-centered),而柯文哲是原則導向(principle-centered)。比如說講到廉潔,兩邊都有一個故事,連勝文這邊是說他在悠遊卡公司的時候,公司在敦化北路跟民生東路口附近,而他丈母娘的紅豆食府就在附近,但他只要是公司出錢的聚餐,為了避嫌都不會去紅豆食府,乍聽之下,似乎很清廉自持,但後面一點他說了,他悠遊卡董事長上任第一天,有人給了他一本廉政的手冊吧,上面就有提到一個小故事,是說類似的事情,說公司的聚餐不能去認識的人的餐廳裡面等等,也就是說他這個清廉自持的行為是因為有人寫了一個「規則」在哪裡,整場專訪,連勝文也相當強調「依法行事」這件事情,這就是 rule-centered 的行事風格。而柯文哲先生對於廉潔,也有個故事,但是他是講到他在台大人際關係不好的時候提到的,他是說台大醫院開會訂便當的時候,一向是打電話給廠商(比如說抗生素廠商等等)送便當進來,而柯文哲當了主管的第一天就要求屬下不得這樣做,開會一律自己買便當,所以才有 MG149 的私帳(因為這些都得自己出錢,但又需要管理,其實就是類似班費)。看得出來,柯文哲是在群體壓力下,堅守一個原則,而不是依照既有規則來行事。另外,講到說實話這件事,他非常堅持誠實這個原則,所以當他發現他講真話(失言風波),媒體很反彈,他說他回去苦惱了很多天,最後想說這跟道德也沒什麼關係,只是尊重聽這些話的人,所以他就做了修正。像這一類行事方法,就是原則導向,亦即心中有一些原則,是大方向,面對每天不同的事件發生的時候,依據這些心中的原則來行事,而且會有優先順序的。
<br><br>
規則導向的行事風格不會出什麼大錯,行事很安全,但有時候會不通情理,比方說有個丈夫因為妻子羊水破了,要趕緊到醫院生產,於是一路超速,警察把他攔下來發現他是因為妻子要生產才超速,規則導向的人這時候就會堅持說你犯了法,必須要開單,因為要依法行事,然後依法也沒規定警察必須要護送孕婦,於是就不理他。這就是規則導向的行事風格。原則導向的行事風格的警察,在攔下來發現超速的原因之後,會衡量各種原則,發現生命當然是優先的,於是罰單也不開,而且還護送這台車一路到醫院。事後來看,後面那個警察做的事情對嗎?的確有人超速而不開單,那麼他是不是包庇違法的事情發生呢?如果有人不問當時發生的狀況與當事人應對的方式,只挑出部份的違法證據來指控對方違法,就落入了規則導向的方式。
<br><br>
原則導向也是兩個當中,能夠開創新局的方式。如果面對一個全新的領域或全新的世界,既有的規則都不能應用,一個規則導向的行事風格就會陷入混亂當中,因為完全沒有規則可循,或是隨便引用相近的陳舊規則來應用在全新的事情上面,這是不是很熟悉?這就是近十幾年來,陳舊的法規面對全新的世界的時候的混亂。以原則導向來說,就會像美國憲法這樣,先條列出行事的原則,而當有任何新的事件發生,就回去檢視這些原則,仔細考量,最後選擇這個新事件要怎麼處理,如此才能夠面對瞬息萬變的世界,而通常這些原則就是一個團體、個人要堅守的價值。
<br><br>
原則導向有個很重要的人一定要提,那就是富蘭克林(Benjamin Franklin, 1706--1790)在他的自傳提過他隨身帶了一本小冊子,稱之為 "The Little Book",上面列了十三條原則,每週選定一個原則來強化,但每天晚上都會針對這十三條原則檢討自己當天的行事是否遵循了這些原則。沒有遵循的地方檢討原因是什麼,但不過分責備自己。注重長期來說,是否有進步。富蘭克林後來說了 "Tho’ I never arrived at the perfection I had been so ambitious of obtaining, but fell far short of it, yet I was, by the endeavour, a better and a happier man than I otherwise should have been if I had not attempted it. " 富蘭克林的這句話是說,他從未達到他原來所想要達到的完全,但是透過熱切的追尋,他變成一個比未追尋完全之前更好更快樂的人。只有這樣子才能夠進步。在 Stephen Covey 的書[3] 「與成功有約」裡面則是把富蘭克林的方法進一步加一些改變並且仔細的闡述,對原則導向有興趣的人可以參考一下。
<br><br>
規則導向我想到的代表人物是馬英九總統,看他的行事風格你就會知道什麼叫做規則導向,他最常把「依法行事」掛在嘴邊,對於一些大家都知道要為大原則放棄追小錯的時候,他只會專注在那個錯誤之上。所以規則導向就是在任何事情發生的時候,一定是檢討有沒有違反規則,並且對違反規則耿耿於懷。因為犯錯就是犯錯,沒有什麼逐漸改善讓犯錯率變少這件事。這是因為規則導向常常會有非常多的規則,而且是針對非常明確的事情做規範,比方說全勤獎金就是個很規則導向的事情,全勤的定義是你這個月每天都到,如果你有一天因為生病而沒到,就是沒有全勤獎金,不論你缺席的理由是什麼。但是原則導向就會去思考,全勤的意義是什麼?然後可能思考出全勤的意義在於你對於公司的貢獻,所以訂定了工作進度,只要你每個月達到工作進度就獎勵,而你中間是否因病缺席,就不在考量範圍內。
<br><br>
寫了這麼多,簡單總結一下,原則導向就是望向未來,而規則導向就是依循過去。 我不是在講哪一個個人怎麼樣,而是哪一種行事方法能夠帶領個人、公司、社會,甚至國家往未來瞬息萬變的挑戰,其實很清楚。
<br><br>
[1] 柯文哲專訪 <a href="https://www.youtube.com/watch?v=85hIr4ouAzA&index=13&list=WL">柯文哲專訪</a> <br>
[2] 連勝文專訪 <a href="https://www.youtube.com/watch?v=MJ5ErQUAaeE">連勝文專訪</a> <br>
[3] Stephen Covey, "The 7 Habits of Highly Effective People" (中文翻譯:與成功有約)Albert Huanghttp://www.blogger.com/profile/09910403631033610841noreply@blogger.com0tag:blogger.com,1999:blog-5393693761509999841.post-28710981609069638552014-08-07T01:40:00.001+08:002014-08-07T01:40:22.276+08:00LaTeX 字型安裝筆記: Adobe Garamond Pro 字型<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><br /><head><br /><title>LaTeX 字型安裝筆記: Adobe Garamond Pro 字型</title><br /><!-- 2014-08-07 Thu 01:39 --><br /><meta http-equiv="Content-Type" content="text/html;charset=utf-8" /><br /><meta name="generator" content="Org-mode" /><br /><meta name="author" content="Albert Huang" /><br /><style type="text/css"><br /> <!--/*--><![CDATA[/*><!--*/<br /> .title { text-align: center; }<br /> .todo { font-family: monospace; color: red; }<br /> .done { color: green; }<br /> .tag { background-color: #eee; font-family: monospace;<br /> padding: 2px; font-size: 80%; font-weight: normal; }<br /> .timestamp { color: #bebebe; }<br /> .timestamp-kwd { color: #5f9ea0; }<br /> .right { margin-left: auto; margin-right: 0px; text-align: right; }<br /> .left { margin-left: 0px; margin-right: auto; text-align: left; }<br /> .center { margin-left: auto; margin-right: auto; text-align: center; }<br /> .underline { text-decoration: underline; }<br /> #postamble p, #preamble p { font-size: 90%; margin: .2em; }<br /> p.verse { margin-left: 3%; }<br /> pre {<br /> border: 1px solid #ccc;<br /> box-shadow: 3px 3px 3px #eee;<br /> padding: 8pt;<br /> font-family: monospace;<br /> overflow: auto;<br /> margin: 1.2em;<br /> }<br /> pre.src {<br /> position: relative;<br /> overflow: visible;<br /> padding-top: 1.2em;<br /> }<br /> pre.src:before {<br /> display: none;<br /> position: absolute;<br /> background-color: white;<br /> top: -10px;<br /> right: 10px;<br /> padding: 3px;<br /> border: 1px solid black;<br /> }<br /> pre.src:hover:before { display: inline;}<br /> pre.src-sh:before { content: 'sh'; }<br /> pre.src-bash:before { content: 'sh'; }<br /> pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }<br /> pre.src-R:before { content: 'R'; }<br /> pre.src-perl:before { content: 'Perl'; }<br /> pre.src-java:before { content: 'Java'; }<br /> pre.src-sql:before { content: 'SQL'; }<br /><br /> table { border-collapse:collapse; }<br /> td, th { vertical-align:top; }<br /> th.right { text-align: center; }<br /> th.left { text-align: center; }<br /> th.center { text-align: center; }<br /> td.right { text-align: right; }<br /> td.left { text-align: left; }<br /> td.center { text-align: center; }<br /> dt { font-weight: bold; }<br /> .footpara:nth-child(2) { display: inline; }<br /> .footpara { display: block; }<br /> .footdef { margin-bottom: 1em; }<br /> .figure { padding: 1em; }<br /> .figure p { text-align: center; }<br /> .inlinetask {<br /> padding: 10px;<br /> border: 2px solid gray;<br /> margin: 10px;<br /> background: #ffffcc;<br /> }<br /> #org-div-home-and-up<br /> { text-align: right; font-size: 70%; white-space: nowrap; }<br /> textarea { overflow-x: auto; }<br /> .linenr { font-size: smaller }<br /> .code-highlighted { background-color: #ffff00; }<br /> .org-info-js_info-navigation { border-style: none; }<br /> #org-info-js_console-label<br /> { font-size: 10px; font-weight: bold; white-space: nowrap; }<br /> .org-info-js_search-highlight<br /> { background-color: #ffff00; color: #000000; font-weight: bold; }<br /> /*]]>*/--><br /></style><br /><script type="text/javascript"><br />/*<br />@licstart The following is the entire license notice for the<br />JavaScript code in this tag.<br /><br />Copyright (C) 2012 Free Software Foundation, Inc.<br /><br />The JavaScript code in this tag is free software: you can<br />redistribute it and/or modify it under the terms of the GNU<br />General Public License (GNU GPL) as published by the Free Software<br />Foundation, either version 3 of the License, or (at your option)<br />any later version. The code is distributed WITHOUT ANY WARRANTY;<br />without even the implied warranty of MERCHANTABILITY or FITNESS<br />FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.<br /><br />As additional permission under GNU GPL version 3 section 7, you<br />may distribute non-source (e.g., minimized or compacted) forms of<br />that code without the copy of the GNU GPL normally required by<br />section 4, provided you include this license notice and a URL<br />through which recipients can access the Corresponding Source.<br /><br /><br />@licend The above is the entire license notice<br />for the JavaScript code in this tag.<br />*/<br /><!--/*--><![CDATA[/*><!--*/<br /> function CodeHighlightOn(elem, id)<br /> {<br /> var target = document.getElementById(id);<br /> if(null != target) {<br /> elem.cacheClassElem = elem.className;<br /> elem.cacheClassTarget = target.className;<br /> target.className = "code-highlighted";<br /> elem.className = "code-highlighted";<br /> }<br /> }<br /> function CodeHighlightOff(elem, id)<br /> {<br /> var target = document.getElementById(id);<br /> if(elem.cacheClassElem)<br /> elem.className = elem.cacheClassElem;<br /> if(elem.cacheClassTarget)<br /> target.className = elem.cacheClassTarget;<br /> }<br />/*]]>*///--><br /></script><br /></head><br /><body><br /><div id="content"><br /><h1 class="title">LaTeX 字型安裝筆記: Adobe Garamond Pro 字型</h1><br /><p><br />上一篇文章筆者提到了 Garamond 字型有非常多個供應者, 其中一個就是 Adobe Garamond Pro 字型, 這是 Adobe 公司出品的商業字型, 在 LaTeX 上同樣也是由 <code>mathdesign</code> 這個套件來支援。<br /></p><br /><br /><p><br />筆者先假設你購買或從他處取得 Adobe Garamond Pro 的以下檔案:<br /></p><br /><ul class="org-ul"><br /><li>AGaramondPro-Regular.otf<br /></li><br /><li>AGaramondPro-Italic.otf<br /></li><br /><li>AGaramondPro-Semibold.otf<br /></li><br /><li>AGaramondPro-SemiboldItalic.otf<br /></li><br /></ul><br /><br /><p><br />請把以上這些檔案複製到 <code>$TEXMF/fonts/opentype/garamond/Adobe Garamond Pro</code> 的字型目錄裡面, 在筆者的 Mac 上我把他們複製到 <code>~/Library/texmf/fonts/opentype/garamond/Adobe Garamond Pro</code> 裡, 然後執行 <code>sudo texhash</code> 更新系統路徑。<br /></p><br /><br /><p><br />使用的方法是:<br /></p><br /><div class="org-src-container"><br /><br /><pre class="src src-latex"><span style="color: #00bfff;">\usepackage</span>[<span style="color: #ffd700;">adobe-garamond</span>]{<span style="color: #00ffff;">mathdesign</span>}<br /></pre><br /></div><br /><br /><p><br />然後你就可以在 LaTeX 裡面使用 Adobe Garamond Pro 這一套商業字型了, 有任何其他的使用細節, 可以在 CTAN 上搜尋 <a href="http://www.ctan.org/tex-archive/fonts/mathdesign">mathdesign 套件</a> 的說明檔案。<br /></p><br /><br /><p><br />P.S.: 這樣安裝的 Open Type 字型只可以使用在 PDFLaTeX 上, LaTeX->DVIPS 這個路徑需要其他的安裝方法。<br /></p><br /></div><br /><div id="postamble" class="status"><br /><p class="author">Author: Albert Huang</p><br /><p class="date">Created: 2014-08-07 Thu 01:39</p><br /><p class="creator"><a href="http://www.gnu.org/software/emacs/">Emacs</a> 24.3.1 (<a href="http://orgmode.org">Org</a> mode 8.2.1)</p><br /><p class="validation"><a href="http://validator.w3.org/check?uri=referer">Validate</a></p><br /></div><br /></body><br /></html><br />Albert Huanghttp://www.blogger.com/profile/09910403631033610841noreply@blogger.com0tag:blogger.com,1999:blog-5393693761509999841.post-52315848596772235702014-08-06T22:30:00.001+08:002014-08-06T23:00:50.519+08:00LaTeX 字型安裝筆記: URW Garamond 字型<html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml"><br /><head><br /><title>LaTeX 字型安裝筆記: URW Garamond 字型</title><br /><!-- 2014-08-06 Wed 22:29 --><br /><br /><br /><br /><style type="text/css"><br /> <!--/*--><![CDATA[/*><!--*/<br /> .title { text-align: center; }<br /> .todo { font-family: monospace; color: red; }<br /> .done { color: green; }<br /> .tag { background-color: #eee; font-family: monospace;<br /> padding: 2px; font-size: 80%; font-weight: normal; }<br /> .timestamp { color: #bebebe; }<br /> .timestamp-kwd { color: #5f9ea0; }<br /> .right { margin-left: auto; margin-right: 0px; text-align: right; }<br /> .left { margin-left: 0px; margin-right: auto; text-align: left; }<br /> .center { margin-left: auto; margin-right: auto; text-align: center; }<br /> .underline { text-decoration: underline; }<br /> #postamble p, #preamble p { font-size: 90%; margin: .2em; }<br /> p.verse { margin-left: 3%; }<br /> pre {<br /> border: 1px solid #ccc;<br /> box-shadow: 3px 3px 3px #eee;<br /> padding: 8pt;<br /> font-family: monospace;<br /> overflow: auto;<br /> margin: 1.2em;<br /> }<br /> pre.src {<br /> position: relative;<br /> overflow: visible;<br /> padding-top: 1.2em;<br /> }<br /> pre.src:before {<br /> display: none;<br /> position: absolute;<br /> background-color: white;<br /> top: -10px;<br /> right: 10px;<br /> padding: 3px;<br /> border: 1px solid black;<br /> }<br /> pre.src:hover:before { display: inline;}<br /> pre.src-sh:before { content: 'sh'; }<br /> pre.src-bash:before { content: 'sh'; }<br /> pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }<br /> pre.src-R:before { content: 'R'; }<br /> pre.src-perl:before { content: 'Perl'; }<br /> pre.src-java:before { content: 'Java'; }<br /> pre.src-sql:before { content: 'SQL'; }<br /><br /> table { border-collapse:collapse; }<br /> td, th { vertical-align:top; }<br /> th.right { text-align: center; }<br /> th.left { text-align: center; }<br /> th.center { text-align: center; }<br /> td.right { text-align: right; }<br /> td.left { text-align: left; }<br /> td.center { text-align: center; }<br /> dt { font-weight: bold; }<br /> .footpara:nth-child(2) { display: inline; }<br /> .footpara { display: block; }<br /> .footdef { margin-bottom: 1em; }<br /> .figure { padding: 1em; }<br /> .figure p { text-align: center; }<br /> .inlinetask {<br /> padding: 10px;<br /> border: 2px solid gray;<br /> margin: 10px;<br /> background: #ffffcc;<br /> }<br /> #org-div-home-and-up<br /> { text-align: right; font-size: 70%; white-space: nowrap; }<br /> textarea { overflow-x: auto; }<br /> .linenr { font-size: smaller }<br /> .code-highlighted { background-color: #ffff00; }<br /> .org-info-js_info-navigation { border-style: none; }<br /> #org-info-js_console-label<br /> { font-size: 10px; font-weight: bold; white-space: nowrap; }<br /> .org-info-js_search-highlight<br /> { background-color: #ffff00; color: #000000; font-weight: bold; }<br /> /*]]>*/--><br /></style><br /><script type="text/javascript"><br />/*<br />@licstart The following is the entire license notice for the<br />JavaScript code in this tag.<br /><br />Copyright (C) 2012 Free Software Foundation, Inc.<br /><br />The JavaScript code in this tag is free software: you can<br />redistribute it and/or modify it under the terms of the GNU<br />General Public License (GNU GPL) as published by the Free Software<br />Foundation, either version 3 of the License, or (at your option)<br />any later version. The code is distributed WITHOUT ANY WARRANTY;<br />without even the implied warranty of MERCHANTABILITY or FITNESS<br />FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.<br /><br />As additional permission under GNU GPL version 3 section 7, you<br />may distribute non-source (e.g., minimized or compacted) forms of<br />that code without the copy of the GNU GPL normally required by<br />section 4, provided you include this license notice and a URL<br />through which recipients can access the Corresponding Source.<br /><br /><br />@licend The above is the entire license notice<br />for the JavaScript code in this tag.<br />*/<br /><!--/*--><![CDATA[/*><!--*/<br /> function CodeHighlightOn(elem, id)<br /> {<br /> var target = document.getElementById(id);<br /> if(null != target) {<br /> elem.cacheClassElem = elem.className;<br /> elem.cacheClassTarget = target.className;<br /> target.className = "code-highlighted";<br /> elem.className = "code-highlighted";<br /> }<br /> }<br /> function CodeHighlightOff(elem, id)<br /> {<br /> var target = document.getElementById(id);<br /> if(elem.cacheClassElem)<br /> elem.className = elem.cacheClassElem;<br /> if(elem.cacheClassTarget)<br /> target.className = elem.cacheClassTarget;<br /> }<br />/*]]>*///--><br /></script></head><br /><body><br /><div id="content">
<br /><h1 class="title">
LaTeX 字型安裝筆記: URW Garamond 字型</h1>
<br /><br />Garamond 是一種描邊字型家族, 泛指由法國的鉛字鑄造師 Claude Garamond~(c. 1480–1561) 設計的字型或後人衍生的字型。許多與 Garamond 有關聯的字型則出自於另一位鉛字鑄造師 Jean Jannon。Garamond 同時也是印刷的時候, 最省墨水或碳粉的字型。<sup><a class="footref" href="https://www.blogger.com/blogger.g?blogID=5393693761509999841#fn.1" id="fnr.1" name="fnr.1">1</a></sup><br />
<br />Garamond 字型有非常多提供者, 有基於 Garamond 設計而衍生的: Adobe Garamond, Garamond Premier, Sabon, EB Garamond, URW++ Garamond No. 8 或是基於 Jannon 而衍生的: ITC Garamond, Garmond 3 等字型, 其中我們今天要講的是 URW++ 所製作的免費 Garamond 字型, 這個字型被內建在 Ghostscript 程式套件裡面, 並且被 TeX 社群引入到 LaTeX 字型中, 其格式是 PostScript Type1 格式。要使用這個字型, 你必須先安裝 <code>mathdesign</code> 這個套件。<br />
使用方法如下:<br />
<br /><div class="org-src-container">
<br /><br /><pre class="src src-latex"><span style="color: deepskyblue;">\usepackage</span>[<span style="color: gold;">urw-garamond</span>]{<span style="color: cyan;">mathdesign</span>}
<span style="color: deepskyblue;">\usepackage</span>[<span style="color: gold;">T1</span>]{<span style="color: cyan;">fontenc</span>}</pre>
</div>
<br />如果你無法使用, 別急, 很可能是你的 TeX 系統沒有附上這套字型, 雖然這套允許非商業用途免費使用, 但 TeX 不一定會附上, 你可以到 <a href="http://www.ctan.org/tex-archive/fonts/urw/garamond">CTAN Garamond 網頁</a> 下載所有的 afm 以及 pfb 檔, 並且放置在正確的路徑上, 筆者把 <code>*.afm</code> 放到 <code>~/Library/texmf/fonts/afm/urw/garamond</code> 裡, 並且把 <code>*.pfb</code> 放到 <code>~/Library/texmf/fonts/type1/urw/garamond</code> 裡面。筆者的電腦是 Mac, 其他系統請參考相關 TeX 系統的說明。放完之後要更新路徑, 讓 TeX 系統能夠使用這些字型, 只要在終端機輸入 <code>texhash</code> 即可。<br />
<br />URW++ Garamond 是一套附有數學符號的描邊字型, 除了有最省墨水或碳粉之外, 也被認為是可讀性很高的一個字型, 如果你已經厭倦 Times Roman 字型, 不妨可以來試試這一套字型。<br />
<br /><div id="footnotes">
<br /><h2 class="footnotes">
Footnotes: </h2>
<br /><div id="text-footnotes">
<br /><br /><div class="footdef">
<sup><a class="footnum" href="https://www.blogger.com/blogger.g?blogID=5393693761509999841#fnr.1" id="fn.1" name="fn.1">1</a></sup> <div class="footpara">
<br /><a href="http://www.bbc.com/news/blogs-magazine-monitor-26835560">http://www.bbc.com/news/blogs-magazine-monitor-26835560</a></div>
</div>
<br /><br /></div>
</div>
</div>
<br /><div class="status" id="postamble">
<br /><div class="author">
Author: Albert Huang</div>
<br /><div class="date">
Created: 2014-08-06 Wed 22:29</div>
<br /><div class="creator">
<a href="http://www.gnu.org/software/emacs/">Emacs</a> 24.3.1 (<a href="http://orgmode.org/">Org</a> mode 8.2.1)</div>
<br /><div class="validation">
<a href="http://validator.w3.org/check?uri=referer">Validate</a></div>
</div>
</body></html>Albert Huanghttp://www.blogger.com/profile/09910403631033610841noreply@blogger.com0tag:blogger.com,1999:blog-5393693761509999841.post-74984076459292609012014-08-01T23:58:00.001+08:002014-08-06T22:36:10.135+08:00在 LaTeX 使用內建在 Acrobat Reader 裡的 Minion Pro 與 Myriad Pro 字型以及 =\epsilon= (\epsilon) 與 =\ell= (\ell) 的問題解法<?xml version="1.0" encoding="utf-8"?><br /><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><br /><html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><br /><head><br /><title>在 LaTeX 使用內建在 Acrobat Reader 裡的 Minion Pro 與 Myriad Pro 字型以及 <code>\epsilon</code> (ε) 與 <code>\ell</code> (ℓ) 的問題解法</title><br /><!-- 2014-08-01 Fri 23:58 --><br /><meta http-equiv="Content-Type" content="text/html;charset=utf-8" /><br /><meta name="generator" content="Org-mode" /><br /><meta name="author" content="Albert Huang" /><br /><style type="text/css"><br /> <!--/*--><![CDATA[/*><!--*/<br /> .title { text-align: center; }<br /> .todo { font-family: monospace; color: red; }<br /> .done { color: green; }<br /> .tag { background-color: #eee; font-family: monospace;<br /> padding: 2px; font-size: 80%; font-weight: normal; }<br /> .timestamp { color: #bebebe; }<br /> .timestamp-kwd { color: #5f9ea0; }<br /> .right { margin-left: auto; margin-right: 0px; text-align: right; }<br /> .left { margin-left: 0px; margin-right: auto; text-align: left; }<br /> .center { margin-left: auto; margin-right: auto; text-align: center; }<br /> .underline { text-decoration: underline; }<br /> #postamble p, #preamble p { font-size: 90%; margin: .2em; }<br /> p.verse { margin-left: 3%; }<br /> pre {<br /> border: 1px solid #ccc;<br /> box-shadow: 3px 3px 3px #eee;<br /> padding: 8pt;<br /> font-family: monospace;<br /> overflow: auto;<br /> margin: 1.2em;<br /> }<br /> pre.src {<br /> position: relative;<br /> overflow: visible;<br /> padding-top: 1.2em;<br /> }<br /> pre.src:before {<br /> display: none;<br /> position: absolute;<br /> background-color: white;<br /> top: -10px;<br /> right: 10px;<br /> padding: 3px;<br /> border: 1px solid black;<br /> }<br /> pre.src:hover:before { display: inline;}<br /> pre.src-sh:before { content: 'sh'; }<br /> pre.src-bash:before { content: 'sh'; }<br /> pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }<br /> pre.src-R:before { content: 'R'; }<br /> pre.src-perl:before { content: 'Perl'; }<br /> pre.src-java:before { content: 'Java'; }<br /> pre.src-sql:before { content: 'SQL'; }<br /><br /> table { border-collapse:collapse; }<br /> td, th { vertical-align:top; }<br /> th.right { text-align: center; }<br /> th.left { text-align: center; }<br /> th.center { text-align: center; }<br /> td.right { text-align: right; }<br /> td.left { text-align: left; }<br /> td.center { text-align: center; }<br /> dt { font-weight: bold; }<br /> .footpara:nth-child(2) { display: inline; }<br /> .footpara { display: block; }<br /> .footdef { margin-bottom: 1em; }<br /> .figure { padding: 1em; }<br /> .figure p { text-align: center; }<br /> .inlinetask {<br /> padding: 10px;<br /> border: 2px solid gray;<br /> margin: 10px;<br /> background: #ffffcc;<br /> }<br /> #org-div-home-and-up<br /> { text-align: right; font-size: 70%; white-space: nowrap; }<br /> textarea { overflow-x: auto; }<br /> .linenr { font-size: smaller }<br /> .code-highlighted { background-color: #ffff00; }<br /> .org-info-js_info-navigation { border-style: none; }<br /> #org-info-js_console-label<br /> { font-size: 10px; font-weight: bold; white-space: nowrap; }<br /> .org-info-js_search-highlight<br /> { background-color: #ffff00; color: #000000; font-weight: bold; }<br /> /*]]>*/--><br /></style><br /><script type="text/javascript"><br />/*<br />@licstart The following is the entire license notice for the<br />JavaScript code in this tag.<br /><br />Copyright (C) 2012 Free Software Foundation, Inc.<br /><br />The JavaScript code in this tag is free software: you can<br />redistribute it and/or modify it under the terms of the GNU<br />General Public License (GNU GPL) as published by the Free Software<br />Foundation, either version 3 of the License, or (at your option)<br />any later version. The code is distributed WITHOUT ANY WARRANTY;<br />without even the implied warranty of MERCHANTABILITY or FITNESS<br />FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.<br /><br />As additional permission under GNU GPL version 3 section 7, you<br />may distribute non-source (e.g., minimized or compacted) forms of<br />that code without the copy of the GNU GPL normally required by<br />section 4, provided you include this license notice and a URL<br />through which recipients can access the Corresponding Source.<br /><br /><br />@licend The above is the entire license notice<br />for the JavaScript code in this tag.<br />*/<br /><!--/*--><![CDATA[/*><!--*/<br /> function CodeHighlightOn(elem, id)<br /> {<br /> var target = document.getElementById(id);<br /> if(null != target) {<br /> elem.cacheClassElem = elem.className;<br /> elem.cacheClassTarget = target.className;<br /> target.className = "code-highlighted";<br /> elem.className = "code-highlighted";<br /> }<br /> }<br /> function CodeHighlightOff(elem, id)<br /> {<br /> var target = document.getElementById(id);<br /> if(elem.cacheClassElem)<br /> elem.className = elem.cacheClassElem;<br /> if(elem.cacheClassTarget)<br /> target.className = elem.cacheClassTarget;<br /> }<br />/*]]>*///--><br /></script><br /></head><br /><body><br /><div id="content"><br /><h1 class="title">在 LaTeX 使用內建在 Acrobat Reader 裡的 Minion Pro 與 Myriad Pro 字型以及 <code>\epsilon</code> (ε) 與 <code>\ell</code> (ℓ) 的問題解法</h1><br /><div id="table-of-contents"><br /><h2>Table of Contents</h2><br /><div id="text-table-of-contents"><br /><ul><br /><li><a href="#sec-1">1. 前言</a></li><br /><li><a href="#sec-2">2. 準備檔案</a></li><br /><li><a href="#sec-3">3. 安裝</a></li><br /><li><a href="#sec-4">4. 使用</a></li><br /><li><a href="#sec-5">5. <code>\epsilon</code> 變成方塊的問題</a></li><br /><li><a href="#sec-6">6. <code>\ell</code></a></li><br /><li><a href="#sec-7">7. 結語</a></li><br /></ul><br /></div><br /></div><br /><br /><div id="outline-container-sec-1" class="outline-2"><br /><h2 id="sec-1"><span class="section-number-2">1</span> 前言</h2><br /><div class="outline-text-2" id="text-1"><br /><p><br />Minion Pro<sup><a id="fnr.1" name="fnr.1" class="footref" href="#fn.1">1</a></sup> 是一個 Adobe 出品的 Serif 字型, 內建在 Adobe Reader<sup><a id="fnr.2" name="fnr.2" class="footref" href="#fn.2">2</a></sup> 與 Adobe Acrobat 裡面, 是一套高品質且漂亮的字型, Myriad Pro<sup><a id="fnr.3" name="fnr.3" class="footref" href="#fn.3">3</a></sup> 則是同樣內建在軟體內的 Sans Serif 字型。有興趣的讀者可以先到 footnotes 上去找兩套字型的範例。兩套字型的格式都是 Open Type, 而且免費贈送, 如果我們想要在自己的 LaTeX 檔案裡面使用, 要怎麼安裝呢?以下這篇文章就會介紹安裝過程以及這兩套字型相關的問題與解法,所有範例都是以 MacOSX 為主, 其他系統請自行找尋相關資源。<br /></p><br /></div><br /></div><br /><br /><div id="outline-container-sec-2" class="outline-2"><br /><h2 id="sec-2"><span class="section-number-2">2</span> 準備檔案</h2><br /><div class="outline-text-2" id="text-2"><br /><ul class="org-ul"><br /><li>TeX 系統<br /></li><br /></ul><br /><p><br />你必須先安裝好 TeX/LaTeX 系統, Windows 的話一般是 <a href="http://miktex.org">MikTeX</a> 比較受歡迎, 而 Mac 則是 <a href="https://tug.org/mactex/">MacTeX</a>, 兩者都是基於 <a href="https://www.tug.org/texlive/">TeXLive</a> 衍生出來的, 如果是 Linux 使用者的話, 就直接安裝 TeXLive 即可。<br /></p><br /><br /><ul class="org-ul"><br /><li>MnSymbol 套件<br /></li><br /></ul><br /><p><br />安裝完 TeX/LaTeX 系統之後, 用系統附的套件管理員安裝 MnSymbol 這個套件。MnSymbol 是搭配 MinionPro 使用的數學符號字型, 相關的符號可以參考 <sup><a id="fnr.4" name="fnr.4" class="footref" href="#fn.4">4</a></sup> 裡面的說明檔。<br /></p><br /><br /><ul class="org-ul"><br /><li>LCDF typetools<br /></li><br /></ul><br /><br /><p><br />一般來說安裝完 TeX/LaTeX 系統後就會有 LCDF typetools 了, 你可以在終端機下命令檢查:<br /></p><br /><pre class="example"><br />Aquila:Font albert$ otfinfo --version<br />otfinfo (LCDF typetools) 2.100<br />Copyright (C) 2003-2013 Eddie Kohler<br />This is free software; see the source for copying conditions.<br />There is NO warranty, not even for merchantability or fitness for a<br />particular purpose.<br /></pre><br /><p><br />如果沒有的話, 請用套件管理員或請到 <a href="http://www.lcdf.org/type/">LCDF Type Software</a> 下載安裝。<br /></p><br /><br /><ul class="org-ul"><br /><li>CTAN 上的 MinionPro 套件<br /></li><br /></ul><br /><p><br />如果 TeX/LaTeX 套件管理員沒有列 MinionPro, 那麼就請你到 <a href="http://www.ctan.org/tex-archive/fonts/minionpro/">CTAN</a> 下載以下檔案:<br /></p><br /><ol class="org-ol"><br /><li><a href="http://mirrors.ctan.org/fonts/minionpro/enc-2.000.zip">http://mirrors.ctan.org/fonts/minionpro/enc-2.000.zip</a><br /></li><br /><li><a href="http://mirrors.ctan.org/fonts/minionpro/metrics-base.zip">http://mirrors.ctan.org/fonts/minionpro/metrics-base.zip</a><br /></li><br /><li><a href="http://mirrors.ctan.org/fonts/minionpro/metrics-full.zip">http://mirrors.ctan.org/fonts/minionpro/metrics-full.zip</a><br /></li><br /><li><a href="http://mirrors.ctan.org/fonts/minionpro/metrics-opticals.zip">http://mirrors.ctan.org/fonts/minionpro/metrics-opticals.zip</a><br /></li><br /><li><a href="http://mirrors.ctan.org/fonts/minionpro/scripts.zip">http://mirrors.ctan.org/fonts/minionpro/scripts.zip</a><br /></li><br /><br /><li>Minion Pro 與 Myriad Pro 字型檔<br /></li><br /></ol><br /><p><br />在你安裝完 Adobe Reader 或 Acrobat 之後, 你就會在 /Applications 有一個 "Adobe Reader.app" 而 Minion Pro 與 Myriad Pro 字型檔會放在 <code>/Applications/Adobe\ Reader.app/Contents/Resources/Resource/Font/</code> 裡面<br /></p><br /><pre class="example"><br />Aquila:~ albert$ cd /Applications/Adobe\ Reader.app/Contents/Resources/Resource/Font/<br />Aquila:Font albert$ ls<br />AdobePiStd.otf MinionPro-BoldIt.otf MyriadPro-Regular.otf ZY______.MMM<br />CourierStd-Bold.otf MinionPro-It.otf SY______.PFB ZY______.PFB<br />CourierStd-BoldOblique.otf MinionPro-Regular.otf SY______.PFM ZY______.PFM<br />CourierStd-Oblique.otf MyriadPro-Bold.otf ZX______.MMM<br />CourierStd.otf MyriadPro-BoldIt.otf ZX______.PFB<br />MinionPro-Bold.otf MyriadPro-It.otf ZX______.PFM<br /></pre><br /><br /><p><br />如果你安裝的是 Acrobat, 那麼把 /Applications 下的 Adobe Reader.app 取代成 Acrobat.app 即可。先把這個路徑記起來, 等一下會用到。<br /></p><br /></div><br /></div><br /><div id="outline-container-sec-3" class="outline-2"><br /><h2 id="sec-3"><span class="section-number-2">3</span> 安裝</h2><br /><div class="outline-text-2" id="text-3"><br /><p><br />檔案準備完之後, 就要開始安裝過程了, 筆者先認定你已經會操作終端機, 如果不知道的話, 請在網路上搜尋終端機的使用方式, 請先開啟終端機(or Terminal.app)。<br /></p><br /><br /><p><br />先切換使用者目錄到 scripts.zip 解壓縮的地方, 一般會在 ~/Downloads/scripts 裡面:<br /></p><br /><br /><pre class="example"><br />Aquila:~ albert$ cd ~/Downloads/scripts/<br />Aquila:scripts albert$ cp /Applications/Adobe\ Reader.app/Contents/Resources/Resource/Font/*.otf ./otf<br />Aquila:scripts albert$ ./convert.sh <br />Creating PostScript fonts ...<br />AdobePiStd: has no 'j' glyph to make dotless<br />cfftot1: glyph 'sterling.oldstyle': While processing otf/MinionPro-Bold.otf:<br />cfftot1: glyph 'sterling.oldstyle': warning: complex flex hint replaced with curves<br />cfftot1: (This Type 2 format font contains flex hints prohibited by Type 1.<br />cfftot1: I've safely replaced them with ordinary curves.)<br />MinionPro-Bold: already has a dotlessj glyph at 'uni0237'<br />MinionPro-BoldIt: already has a dotlessj glyph at 'uni0237'<br />cfftot1: glyph 'colonmonetary.oldstyle': While processing otf/MinionPro-It.otf:<br />cfftot1: glyph 'colonmonetary.oldstyle': warning: complex flex hint replaced with curves<br />cfftot1: (This Type 2 format font contains flex hints prohibited by Type 1.<br />cfftot1: I've safely replaced them with ordinary curves.)<br />MinionPro-It: already has a dotlessj glyph at 'uni0237'<br />MinionPro-Regular: already has a dotlessj glyph at 'uni0237'<br />Aquila:scripts albert$ mkdir -p ~/Library/texmf/fonts/type1/adobe/MinionPro<br />Aquila:scripts albert$ cp ./pfb/*.pfb ~/Library/texmf/fonts/type1/adobe/MinionPro<br /></pre><br /><br /><p><br />然後解壓縮字型相關檔案<br /></p><br /><pre class="example"><br />Aquila:scripts albert$ cd ~/Library/texmf<br />Aquila:scripts albert$ unzip enc-2.000.zip<br />Aquila:scripts albert$ unzip metrics-base.zip<br />Aquila:scripts albert$ unzip metrics-full.zip<br /></pre><br /><br /><p><br />更新字型地圖, <br /></p><br /><pre class="example"><br />Aquila:scripts albert$ updmap<br /></pre><br /><p><br />執行的結果應該會列出 ~/Librar/texmf/fonts/map/dvips/MinionPro/MinionPro.map 以及 ~/Librar/texmf/fonts/map/dvips/MyriadPro/MyriadPro.map<br /></p><br /><br /><p><br />找到之後, 預設是 disable 的, 你要下命令啟動他們:<br /></p><br /><pre class="example"><br />Aquila:scripts albert$ updmap --enable Map=MinionPro.map<br />Aquila:scripts albert$ updmap --enable Map=MyriadPro.map<br /></pre><br /><br /><p><br />到這邊如果安裝過程順利沒有什麼錯誤的話, 這兩套字型就算是安裝完成了。<br /></p><br /></div><br /></div><br /><div id="outline-container-sec-4" class="outline-2"><br /><h2 id="sec-4"><span class="section-number-2">4</span> 使用</h2><br /><div class="outline-text-2" id="text-4"><br /><p><br />想要在你的 LaTeX 檔案裡面使用 MinionPro 字型, 只要在 preamble 寫下:<br /></p><br /><div class="org-src-container"><br /><br /><pre class="src src-latex"><span style="color: #00bfff;">\usepackage</span>{<span style="color: #00ffff;">MinionPro</span>} <span style="color: #8fbc8f;">% 使用 Minion Pro 字型</span><br /><span style="color: #00bfff;">\usepackage</span>{<span style="color: #00ffff;">MnSymbol</span>} <span style="color: #8fbc8f;">% 使用搭配 MnSymbol 的數學字型</span><br /></pre><br /></div><br /><br /><p><br />另外, 預設的 text figure 一般人可能不太習慣, 可以選擇 lining figure 如下:<br /></p><br /><div class="org-src-container"><br /><br /><pre class="src src-latex"><span style="color: #00bfff;">\usepackage</span>[<span style="color: #ffd700;">lf</span>]{<span style="color: #00ffff;">MinionPro</span>} <span style="color: #8fbc8f;">% 使用 Minion Pro 字型, lining figure</span><br /></pre><br /></div><br /><br /><p><br />兩者的差異如圖所示:<br /></p><br /><br /><br /><div class="figure"><br /><p><img src="https://lh6.googleusercontent.com/-_kf6rZHOMDs/U9u0hfzdWwI/AAAAAAAAAQM/jJd6fqKRjCg/w1444-h424-no/MinionPro-figures.png" alt="MinionPro-figures.png" /><br /></p><br /></div><br /><br /><p><br />其他更詳細的使用方法, 請參考 CTAN 連結上面的 MinionPro.pdf 檔案。安裝過程就介紹到這裡了。<br /></p><br /></div><br /></div><br /><br /><div id="outline-container-sec-5" class="outline-2"><br /><h2 id="sec-5"><span class="section-number-2">5</span> <code>\epsilon</code> 變成方塊的問題</h2><br /><div class="outline-text-2" id="text-5"><br /><p><br />有數種解決方法, 不過最簡單的是用 <code>\varepsilon</code> 取代, 或是在 preamble 設定<br /></p><br /><div class="org-src-container"><br /><br /><pre class="src src-latex"><span style="color: #00bfff;">\renewcommand</span>{<span style="color: #00ffff;">\epsilon</span>}{<span style="color: #00ffff;">\varepsilon</span>}<br /></pre><br /></div><br /></div><br /></div><br /><div id="outline-container-sec-6" class="outline-2"><br /><h2 id="sec-6"><span class="section-number-2">6</span> <code>\ell</code></h2><br /><div class="outline-text-2" id="text-6"><br /><p><br />Adobe Reader 9 之後 <code>\ell</code> 被更改編碼位置, 但是 enc-2.0.0 未反映這個更新, 要修正這個問題, 就請修改 base-MinionPro-ab.enc 這個檔案, 他應該在 ~/Library/texmf/fonts/enc/dvips/MinionPro 裡面, 打開檔案後, 把 "afii61289" 取代成 "uni2113" 然後存檔即可。<br /></p><br /></div><br /></div><br /><div id="outline-container-sec-7" class="outline-2"><br /><h2 id="sec-7"><span class="section-number-2">7</span> 結語</h2><br /><div class="outline-text-2" id="text-7"><br /><p><br />TeX/LaTeX 是一個高品質的排版系統, 桌上型排版發展了這麼多年, 一直還沒有任何其他排版軟體能夠真正的取代它的地位, 雖然學習曲線比較陡峭, 但依然值得我們花精神學習它。LaTeX 的字型安裝一直是令人頭痛的問題, 這篇文章簡單的介紹如何安裝 Minion Pro 與 Myriad Pro 兩套字型, 讓使用者在 LaTeX 使用它們, 希望能夠減緩一些安裝字型時頭痛的程度, 讓各位更能享受 LaTeX 的排版品質。<br /></p><br /></div><br /></div><br /><div id="footnotes"><br /><h2 class="footnotes">Footnotes: </h2><br /><div id="text-footnotes"><br /><br /><div class="footdef"><sup><a id="fn.1" name="fn.1" class="footnum" href="#fnr.1">1</a></sup> <p class="footpara"><br /><a href="http://store1.adobe.com/cfusion/store/html/index.cfm?event=displayFontPackage&code=1719">http://store1.adobe.com/cfusion/store/html/index.cfm?event=displayFontPackage&code=1719</a><br /></p></div><br /><br /><div class="footdef"><sup><a id="fn.2" name="fn.2" class="footnum" href="#fnr.2">2</a></sup> <p class="footpara"><br /><a href="http://get.adobe.com/reader/">http://get.adobe.com/reader/</a><br /></p></div><br /><br /><div class="footdef"><sup><a id="fn.3" name="fn.3" class="footnum" href="#fnr.3">3</a></sup> <p class="footpara"><br /><a href="http://store1.adobe.com/cfusion/store/html/index.cfm?store=OLS-US&event=displayFontPackage&code=1706">http://store1.adobe.com/cfusion/store/html/index.cfm?store=OLS-US&event=displayFontPackage&code=1706</a><br /></p></div><br /><br /><div class="footdef"><sup><a id="fn.4" name="fn.4" class="footnum" href="#fnr.4">4</a></sup> <p class="footpara"><br /><a href="http://www.ctan.org/pkg/mnsymbol">http://www.ctan.org/pkg/mnsymbol</a><br /></p></div><br /><br /><br /></div><br /></div></div><br /><div id="postamble" class="status"><br /><p class="author">Author: Albert Huang</p><br /><p class="date">Created: 2014-08-01 Fri 23:58</p><br /><p class="creator"><a href="http://www.gnu.org/software/emacs/">Emacs</a> 24.3.1 (<a href="http://orgmode.org">Org</a> mode 8.2.1)</p><br /><p class="validation"><a href="http://validator.w3.org/check?uri=referer">Validate</a></p><br /></div><br /></body><br /></html><br />Albert Huanghttp://www.blogger.com/profile/09910403631033610841noreply@blogger.com2tag:blogger.com,1999:blog-5393693761509999841.post-16424902914975202352014-03-03T21:53:00.000+08:002014-03-03T22:03:26.548+08:00漫談分貝(dB) 這一堆玩意兒
<!-- 2014-03-03 Mon 21:47 -->
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="generator" content="Org-mode" />
<meta name="author" content="Albert Huang" />
<style type="text/css">
<!--/*--><![CDATA[/*><!--*/
.title { text-align: center; }
.todo { font-family: monospace; color: red; }
.done { color: green; }
.tag { background-color: #eee; font-family: monospace;
padding: 2px; font-size: 80%; font-weight: normal; }
.timestamp { color: #bebebe; }
.timestamp-kwd { color: #5f9ea0; }
.right { margin-left: auto; margin-right: 0px; text-align: right; }
.left { margin-left: 0px; margin-right: auto; text-align: left; }
.center { margin-left: auto; margin-right: auto; text-align: center; }
.underline { text-decoration: underline; }
#postamble p, #preamble p { font-size: 90%; margin: .2em; }
p.verse { margin-left: 3%; }
pre {
border: 1px solid #ccc;
box-shadow: 3px 3px 3px #eee;
padding: 8pt;
font-family: monospace;
overflow: auto;
margin: 1.2em;
}
pre.src {
position: relative;
overflow: visible;
padding-top: 1.2em;
}
pre.src:before {
display: none;
position: absolute;
background-color: white;
top: -10px;
right: 10px;
padding: 3px;
border: 1px solid black;
}
pre.src:hover:before { display: inline;}
pre.src-sh:before { content: 'sh'; }
pre.src-bash:before { content: 'sh'; }
pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
pre.src-R:before { content: 'R'; }
pre.src-perl:before { content: 'Perl'; }
pre.src-java:before { content: 'Java'; }
pre.src-sql:before { content: 'SQL'; }
table { border-collapse:collapse; }
td, th { vertical-align:top; }
th.right { text-align: center; }
th.left { text-align: center; }
th.center { text-align: center; }
td.right { text-align: right; }
td.left { text-align: left; }
td.center { text-align: center; }
dt { font-weight: bold; }
.footpara:nth-child(2) { display: inline; }
.footpara { display: block; }
.footdef { margin-bottom: 1em; }
.figure { padding: 1em; }
.figure p { text-align: center; }
.inlinetask {
padding: 10px;
border: 2px solid gray;
margin: 10px;
background: #ffffcc;
}
#org-div-home-and-up
{ text-align: right; font-size: 70%; white-space: nowrap; }
textarea { overflow-x: auto; }
.linenr { font-size: smaller }
.code-highlighted { background-color: #ffff00; }
.org-info-js_info-navigation { border-style: none; }
#org-info-js_console-label
{ font-size: 10px; font-weight: bold; white-space: nowrap; }
.org-info-js_search-highlight
{ background-color: #ffff00; color: #000000; font-weight: bold; }
/*]]>*/-->
</style>
<script type="text/javascript">
/*
@licstart The following is the entire license notice for the
JavaScript code in this tag.
Copyright (C) 2012 Free Software Foundation, Inc.
The JavaScript code in this tag is free software: you can
redistribute it and/or modify it under the terms of the GNU
General Public License (GNU GPL) as published by the Free Software
Foundation, either version 3 of the License, or (at your option)
any later version. The code is distributed WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
As additional permission under GNU GPL version 3 section 7, you
may distribute non-source (e.g., minimized or compacted) forms of
that code without the copy of the GNU GPL normally required by
section 4, provided you include this license notice and a URL
through which recipients can access the Corresponding Source.
@licend The above is the entire license notice
for the JavaScript code in this tag.
*/
<!--/*--><![CDATA[/*><!--*/
function CodeHighlightOn(elem, id)
{
var target = document.getElementById(id);
if(null != target) {
elem.cacheClassElem = elem.className;
elem.cacheClassTarget = target.className;
target.className = "code-highlighted";
elem.className = "code-highlighted";
}
}
function CodeHighlightOff(elem, id)
{
var target = document.getElementById(id);
if(elem.cacheClassElem)
elem.className = elem.cacheClassElem;
if(elem.cacheClassTarget)
target.className = elem.cacheClassTarget;
}
/*]]>*///-->
</script>
<script type="text/javascript" src="http://orgmode.org/mathjax/MathJax.js"></script>
<script type="text/javascript">
<!--/*--><![CDATA[/*><!--*/
MathJax.Hub.Config({
// Only one of the two following lines, depending on user settings
// First allows browser-native MathML display, second forces HTML/CSS
// config: ["MMLorHTML.js"], jax: ["input/TeX"],
jax: ["input/TeX", "output/HTML-CSS"],
extensions: ["tex2jax.js","TeX/AMSmath.js","TeX/AMSsymbols.js",
"TeX/noUndefined.js"],
tex2jax: {
inlineMath: [ ["\\(","\\)"] ],
displayMath: [ ['$$','$$'], ["\\[","\\]"], ["\\begin{displaymath}","\\end{displaymath}"] ],
skipTags: ["script","noscript","style","textarea","pre","code"],
ignoreClass: "tex2jax_ignore",
processEscapes: false,
processEnvironments: true,
preview: "TeX"
},
showProcessingMessages: true,
displayAlign: "center",
displayIndent: "2em",
"HTML-CSS": {
scale: 100,
availableFonts: ["STIX","TeX"],
preferredFont: "TeX",
webFont: "TeX",
imageFont: "TeX",
showMathMenu: true,
},
MMLorHTML: {
prefer: {
MSIE: "MML",
Firefox: "MML",
Opera: "HTML",
other: "HTML"
}
}
});
/*]]>*///-->
</script>
</head>
<div id="content">
<p>
今天是 3 月 3 日, 恰好是發明電話的貝爾的生日, 所以今天我們來談以貝爾的姓氏命名的單位, Bel 以及 decibel(分貝或 dB)。剛開始接觸數位訊號處理或是通訊領域, 最常令人困惑的就是 dB 這個玩意兒, 它既不是一個單位, 也不怎麼直覺, 接下來就讓我們來看看這玩意兒吧。
</p>
<p>
分貝(dB, or decibel) 當初是拿來描述量測的電話線訊號衰減量, 在 1928 年貝爾系統公司(貝爾電報電話公司的相關企業)把原本使用的 Transmission Unit(TU) 改名為 decibel, 並且增加 Bel(1 Bel = 10 decibel), 用來紀念發明電話的貝爾(Alexander Graham Bell, March 3, 1847 – August 2, 1922),<sup><a id="fnr.1" name="fnr.1" class="footref" href="#fn.1">1</a></sup> 文章發布的今天剛好是他的生日。
</p>
<p>
分貝是拿來描述衰減量的, 只是一個相對單位而已, 就像一般講的數量級一樣, 一個數量級代表的是十倍, 而 1 Bel 就是 10 dB, 是由以 10 為基底的對數函數產生:
</p>
\begin{equation}
L_{dB} = 10~\log_{10} \frac{P_1}{P_2}
\end{equation}
<p>
要先記住上述衰減量是拿來描述功率衰減的, 我們也可以用 dB 描述振幅的衰減量, 而初學者很容易搞混計算功率以及振幅衰減的分貝公式。
</p>
<p>
功率:
</p>
\begin{equation}
L_{dB} = 10~\log_{10} \frac{P_1}{P_2}
\end{equation}
<p>
振幅(如電壓、電流、聲壓):
</p>
\begin{equation}
L_{dB} = 20~\log_{10} \frac{A_1}{A_2}
\end{equation}
<p>
只要先記得分貝都是計算功率的公式, 再利用電路的基本公式: \(P=IV=\frac{V^2}{R}\), P 為功率, I 為電流, V 為電壓, R 為電阻, 那麼:
</p>
\begin{equation}
L_{dB} = 10~\log_{10} \frac{P_1}{P_2} = 10~\log_{10} \frac{V_1^2}{V_2^2} = 20~\log_{10} \frac{V_1}{V_2}
\end{equation}
<p>
而大部分功率都是振幅的平方倍, 所以都可以得到上述的式子, 因此振幅計算公式前面的常數是 20。
</p>
<p>
當倍數轉換成分貝讓乘法轉換成加法, 除法轉換成減法, 使得運算更為簡單, 其數值也不容易超過能夠表示的範圍。例如接收機的情況, 從發射機一路到接收機的各級增益, 按照順序列表:
</p>
<ul class="org-ul">
<li>發射機 \(P_{TX} = 1W = 10\log_{10} \frac{1W}{1mW} = 10\log_{10} 1000 = 30 dBm\)
</li>
<li>發射天線增益 \(G_{TXANT} = 10 dBi\), 或 10 倍
</li>
<li>空氣中衰減 \(ATT_{channel} = -60 dB\), 或 1/1000000 倍
</li>
<li>接收機天線增益 \(G_{RXANT} = 10 dBi\), 或 10 倍
</li>
<li>接收機 LNA 增益 \(G_{RX} = 20 dB\), 或 10 倍
</li>
</ul>
<p>
計算各級增益, 以 dB 來計算,只要算
</p>
\begin{equation}
RSSI_{dB} = P_{TX} + G_{TXANT} + ATT_{channel} + G_{RXANT} + G_{RX} = 30 + 10 - 60 + 10 + 20 = 10 dBm
\end{equation}
<p>
而用倍數來計算則會是這樣:
</p>
\begin{equation}
RSSI = 1 * 10 / 1000000 * 10 * 10 = 0.001
\end{equation}
<p>
可以看出用倍數算會出現動態範圍比較大的整數或小數, 而 dB 值只要加加減減就出來了, 這在浮點運算的時候看不出好處, 但在定點運算上可以看出來上述的例子, dB 的計算只要給有號整數部分 8 個位元即可表示, 而線性尺度(linear scale, 也就是上述所稱的倍數) 的計算則會做到超過 20 位元的除法。
</p>
<p>
除了運算上會變得動態範圍變小以外, dB 公式中的對數函數也有將比較小的數值變化放大並將比較大的數值變化縮小的功用。
</p>
<div class="figure">
<p><img src="https://lh3.googleusercontent.com/e4cGbRsrIRgZ10CfsEnihWvcxJJ1fr5aQ-68KtOFbj0=w482-h360-p-no" alt="Resp_linear.png" />
</p>
<p><span class="figure-number">Figure 1:</span> 線性尺度</p>
</div>
<div class="figure">
<p>
<img src="https://lh6.googleusercontent.com/SQzmwIDNJMEK65dIAeOqL8W4lMa-1FdwUo9RPgx_M8U=w482-h360-p-no" alt="Resp_dB.png" />
</p>
<p><span class="figure-number">Figure 2:</span> dB 尺度</p>
</div>
<p>
可以看得出來 320kHz 以下的變化原本在線性尺度看不太出來, 但在 dB 尺度看出來上下變化範圍有 10 dB 的大小, 這對訊號來說已經算是不小的影響。而線性尺度看起來差異很大(一半)的 400kHz 到 900kHz 的範圍, 在 dB 尺度上只有 4 dB 左右, 320kHz 變化 10 dB 在這個例子中, 因為那不是我們要的訊號, 所以影響不大, 但若發生在我們想要的頻譜上, 線性尺度可能就會看不太出來, 這個是 dB 尺度的優點。
</p>
<p>
以上就是對於 dB 簡單的介紹, 那麼我們常常看到 dB 後面還加上一些字母, 那是什麼意思呢?我們來看一些常用的 dB 家族。
</p>
<p>
分貝後面如果加上了其他的字母, 代表分母的參考量, 就會從相對值變成絕對值。
</p>
<ul class="org-ul">
<li>dBm 代表分母是 1mW, 所以 \(dBm = 10~\log_{10} \frac{P}{1mW}\)
</li>
<li>dBW 代表分母是 1W, 所以 \(dBW = 10~\log_{10} \frac{P}{1W}\)
</li>
</ul>
<p>
如果是分貝後面加上其他字母, 但是該字母被括號刮起來, 是代表訊號的種類。
</p>
<ul class="org-ul">
<li>dB(A) 代表聲壓, 是一個絕對單位, 參考訊號位準是 \(20~\mu~Pa\),<sup><a id="fnr.2" name="fnr.2" class="footref" href="#fn.2">2</a></sup> 是人耳所能聽到的下限, 又因為聲音是振幅, 所以計算公式為:
</li>
</ul>
\begin{equation}
L_p = 20~\log_{10}\frac{P_{rms}}{P_{ref}}, P_{ref} = 20~\mu~Pa
\end{equation}
<p>
聲音用 dB 來表示是因為耳朵對於壓力變化大小是對數級的, 至於頻率變化也有類似的關係, 因此對於噪音計算定義了 octave band filter, 每一個 octave band 的中心頻率是下一個 band 的 2 倍或 1/2。<sup><a id="fnr.3" name="fnr.3" class="footref" href="#fn.3">3</a></sup>
</p>
<p>
dBi 是用來描述天線增益, 定義是最大的波束相對於理想均勻球體輻射樣式(isotropic) 的增益。
</p>
<p>
dBm/Hz 則是拿來描述功率密度(power spectral density), 意思就是每 1 Hz 所含的功率, 如果你有功率密度 -30 dBm/Hz, 在 10 MHz 寬度上都是平坦的, 其他地方的數值都小到可以忽略, 那麼總發射功率就是 \(-30 + 10 \log_{10} {10 \times 10^6} = 40 dBm = 10W\)
</p>
<p>
我們描述 SNR(訊雜比) 的時候也常常用 dB 來描述, 大部分的接收機, 比如說 Wifi, Bluetooth, LTE, WCDMA 等等都會顯示 SNR<sub>dB</sub>, 而筆者常常看到有人引用這個 SNR 值的時候, 忘記加上 dB, 這樣會造成非常大的誤解與巨大的差異, 舉例來說, 如果 SNR 是 60 dB, 而引用的時候說 SNR 是 60, 那麼這個意思就是 \(\frac{P_{signal}}{P_{noise}} = 60\) 了, 而 \(60~dB = 10^{\frac{60}{10}} = 1000000\), 差距有 \(\frac{1000000}{60} = 16666.7\), 有上萬倍的差異啊!筆者知道分貝對初學者來說, 是個不容易搞懂的數量, 因此寫了這篇文章, 希望大家在接觸訊號與通訊領域的時候, 看到 dB<sup><a id="fnr.4" name="fnr.4" class="footref" href="#fn.4">4</a></sup> 能夠不再那麼陌生。
</p>
<div id="footnotes">
<h2 class="footnotes">Footnotes: </h2>
<div id="text-footnotes">
<div class="footdef"><sup><a id="fn.1" name="fn.1" class="footnum" href="#fnr.1">1</a></sup> <p class="footpara">
<a href="http://en.wikipedia.org/wiki/Alexander_Graham_Bell">http://en.wikipedia.org/wiki/Alexander_Graham_Bell</a>
</p></div>
<div class="footdef"><sup><a id="fn.2" name="fn.2" class="footnum" href="#fnr.2">2</a></sup> <p class="footpara">
<a href="http://en.wikipedia.org/wiki/Sound_pressure">http://en.wikipedia.org/wiki/Sound_pressure</a>
</p></div>
<div class="footdef"><sup><a id="fn.3" name="fn.3" class="footnum" href="#fnr.3">3</a></sup> <p class="footpara">
<a href="http://www.engineeringtoolbox.com/octave-bands-frequency-limits-d_1602.html">http://www.engineeringtoolbox.com/octave-bands-frequency-limits-d_1602.html</a>
</p></div>
<div class="footdef"><sup><a id="fn.4" name="fn.4" class="footnum" href="#fnr.4">4</a></sup> <p class="footpara">
<a href="http://en.wikipedia.org/wiki/Decibel">http://en.wikipedia.org/wiki/Decibel</a>
</p></div>
</div>
</div></div>
<div id="postamble" class="status">
<p class="author">Author: Albert Huang</p>
<p class="date">Created: 2014-03-03 Mon 21:47</p>
<p class="creator"><a href="http://www.gnu.org/software/emacs/">Emacs</a> 24.3.1 (<a href="http://orgmode.org">Org</a> mode 8.2.1)</p>
<p class="validation"><a href="http://validator.w3.org/check?uri=referer">Validate</a></p>
</div>Albert Huanghttp://www.blogger.com/profile/09910403631033610841noreply@blogger.com0tag:blogger.com,1999:blog-5393693761509999841.post-21845825233275299242014-02-18T22:17:00.000+08:002016-12-27T11:33:35.579+08:00談談 ARM Cortex-M4F 上的 DSP 功能
<!-- 2014-02-18 Tue 22:05 -->
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="generator" content="Org-mode" />
<meta name="author" content="Albert Huang" />
<style type="text/css">
<!--/*--><![CDATA[/*><!--*/
.title { text-align: center; }
.todo { font-family: monospace; color: red; }
.done { color: green; }
.tag { background-color: #eee; font-family: monospace;
padding: 2px; font-size: 80%; font-weight: normal; }
.timestamp { color: #bebebe; }
.timestamp-kwd { color: #5f9ea0; }
.right { margin-left: auto; margin-right: 0px; text-align: right; }
.left { margin-left: 0px; margin-right: auto; text-align: left; }
.center { margin-left: auto; margin-right: auto; text-align: center; }
.underline { text-decoration: underline; }
#postamble p, #preamble p { font-size: 90%; margin: .2em; }
p.verse { margin-left: 3%; }
pre {
border: 1px solid #ccc;
box-shadow: 3px 3px 3px #eee;
padding: 8pt;
font-family: monospace;
overflow: auto;
margin: 1.2em;
}
pre.src {
position: relative;
overflow: visible;
padding-top: 1.2em;
}
pre.src:before {
display: none;
position: absolute;
background-color: white;
top: -10px;
right: 10px;
padding: 3px;
border: 1px solid black;
}
pre.src:hover:before { display: inline;}
pre.src-sh:before { content: 'sh'; }
pre.src-bash:before { content: 'sh'; }
pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
pre.src-R:before { content: 'R'; }
pre.src-perl:before { content: 'Perl'; }
pre.src-java:before { content: 'Java'; }
pre.src-sql:before { content: 'SQL'; }
table { border-collapse:collapse; }
td, th { vertical-align:top; }
th.right { text-align: center; }
th.left { text-align: center; }
th.center { text-align: center; }
td.right { text-align: right; }
td.left { text-align: left; }
td.center { text-align: center; }
dt { font-weight: bold; }
.footpara:nth-child(2) { display: inline; }
.footpara { display: block; }
.footdef { margin-bottom: 1em; }
.figure { padding: 1em; }
.figure p { text-align: center; }
.inlinetask {
padding: 10px;
border: 2px solid gray;
margin: 10px;
background: #ffffcc;
}
#org-div-home-and-up
{ text-align: right; font-size: 70%; white-space: nowrap; }
textarea { overflow-x: auto; }
.linenr { font-size: smaller }
.code-highlighted { background-color: #ffff00; }
.org-info-js_info-navigation { border-style: none; }
#org-info-js_console-label
{ font-size: 10px; font-weight: bold; white-space: nowrap; }
.org-info-js_search-highlight
{ background-color: #ffff00; color: #000000; font-weight: bold; }
/*]]>*/-->
</style>
<script type="text/javascript">
/*
@licstart The following is the entire license notice for the
JavaScript code in this tag.
Copyright (C) 2012 Free Software Foundation, Inc.
The JavaScript code in this tag is free software: you can
redistribute it and/or modify it under the terms of the GNU
General Public License (GNU GPL) as published by the Free Software
Foundation, either version 3 of the License, or (at your option)
any later version. The code is distributed WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
As additional permission under GNU GPL version 3 section 7, you
may distribute non-source (e.g., minimized or compacted) forms of
that code without the copy of the GNU GPL normally required by
section 4, provided you include this license notice and a URL
through which recipients can access the Corresponding Source.
@licend The above is the entire license notice
for the JavaScript code in this tag.
*/
<!--/*--><![CDATA[/*><!--*/
function CodeHighlightOn(elem, id)
{
var target = document.getElementById(id);
if(null != target) {
elem.cacheClassElem = elem.className;
elem.cacheClassTarget = target.className;
target.className = "code-highlighted";
elem.className = "code-highlighted";
}
}
function CodeHighlightOff(elem, id)
{
var target = document.getElementById(id);
if(elem.cacheClassElem)
elem.className = elem.cacheClassElem;
if(elem.cacheClassTarget)
target.className = elem.cacheClassTarget;
}
/*]]>*///-->
</script>
<script type="text/javascript" src="http://orgmode.org/mathjax/MathJax.js"></script>
<script type="text/javascript">
<!--/*--><![CDATA[/*><!--*/
MathJax.Hub.Config({
// Only one of the two following lines, depending on user settings
// First allows browser-native MathML display, second forces HTML/CSS
// config: ["MMLorHTML.js"], jax: ["input/TeX"],
jax: ["input/TeX", "output/HTML-CSS"],
extensions: ["tex2jax.js","TeX/AMSmath.js","TeX/AMSsymbols.js",
"TeX/noUndefined.js"],
tex2jax: {
inlineMath: [ ["\\(","\\)"] ],
displayMath: [ ['$$','$$'], ["\\[","\\]"], ["\\begin{displaymath}","\\end{displaymath}"] ],
skipTags: ["script","noscript","style","textarea","pre","code"],
ignoreClass: "tex2jax_ignore",
processEscapes: false,
processEnvironments: true,
preview: "TeX"
},
showProcessingMessages: true,
displayAlign: "center",
displayIndent: "2em",
"HTML-CSS": {
scale: 100,
availableFonts: ["STIX","TeX"],
preferredFont: "TeX",
webFont: "TeX",
imageFont: "TeX",
showMathMenu: true,
},
MMLorHTML: {
prefer: {
MSIE: "MML",
Firefox: "MML",
Opera: "HTML",
other: "HTML"
}
}
});
/*]]>*///-->
</script>
</head>
<body>
<div id="content">
<div id="table-of-contents">
<h2>Table of Contents</h2>
<div id="text-table-of-contents">
<ul>
<li><a href="#sec-1">談談 ARM Cortex-M4F 上的 DSP 功能</a>
<ul>
<li><a href="#sec-1-1">1. 前言</a></li>
<li><a href="#sec-1-2">2. ARM Cortex-M4F 功能簡介</a></li>
<li><a href="#sec-1-3">3. DSP 運算的核心: 乘積累加(Multiply-and-Accumulate)</a></li>
<li><a href="#sec-1-4">4. 結語</a></li>
</ul>
</li>
</ul>
</div>
</div>
<div id="outline-container-sec-1" class="outline-2">
<h2 id="sec-1"><span class="section-number-2">1</span> 談談 ARM Cortex-M4F 上的 DSP 功能</h2>
<div class="outline-text-2" id="text-1">
</div><div id="outline-container-sec-1-1" class="outline-3">
<h3 id="sec-1-1"><span class="section-number-3">1</span> 前言</h3>
<div class="outline-text-3" id="text-1-1">
<p>
從 ARM2 在 1986 年問世以來, ARM 的處理器一向以省電性聞名, 之後到了智慧型手持裝置的時代, 省電性更是非常迫切的需求, 到了 2005 年, 有 98% 的手機上面至少有一顆 ARM 的處理器。<sup><a id="fnr.1" name="fnr.1" class="footref" href="#fn.1">1</a></sup> 專精於數位訊號處理的工程師, 除了傳統的數位訊號處理器以外, 勢必要了解一下這樣的趨勢, 以及如何在自己的專案中評估使用 ARM 處理器的可能性, 本文將會針對與中低階 DSP 較為類似的 ARM Cortex-M4F 上的 DSP 功能來討論。
</p>
</div>
</div>
<div id="outline-container-sec-1-2" class="outline-3">
<h3 id="sec-1-2"><span class="section-number-3">2</span> ARM Cortex-M4F 功能簡介</h3>
<div class="outline-text-3" id="text-1-2">
<p>
ARM Cortex-M4F 是 ARM Cortex-M 系列的處理器裡面功能最為強大的一個, 而 Cortex-M 系列的 M 是指 microcontroller, 下表列舉了部分的 Cortex-M 系列處理器的比較, 可以看出 Cortex-M4F 在指令集上有硬體乘法、硬體除法、飽和運算、數位訊號處理延伸指令以及浮點運算。
</p>
<p>
ARM Cortex-M 系列指令集支援<sup><a id="fnr.2" name="fnr.2" class="footref" href="#fn.2">2</a></sup>
</p>
<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">
<colgroup>
<col class="left" />
<col class="left" />
<col class="left" />
<col class="left" />
<col class="left" />
<col class="left" />
<col class="left" />
<col class="left" />
<col class="left" />
<col class="left" />
</colgroup>
<thead>
<tr>
<th scope="col" class="left">ARM Cortex-M</th>
<th scope="col" class="left">Thumb</th>
<th scope="col" class="left">Thumb-2</th>
<th scope="col" class="left">硬體乘法器</th>
<th scope="col" class="left">硬體除法器</th>
<th scope="col" class="left">飽和運算</th>
<th scope="col" class="left">DSP 延伸功能</th>
<th scope="col" class="left">浮點</th>
<th scope="col" class="left">ARM 架構</th>
<th scope="col" class="left">核心架構</th>
</tr>
</thead>
<tbody>
<tr>
<td class="left">Cortex-M3</td>
<td class="left">完整</td>
<td class="left">完整</td>
<td class="left">單一時脈</td>
<td class="left">有</td>
<td class="left">有</td>
<td class="left">無</td>
<td class="left">無</td>
<td class="left">ARMv7-M</td>
<td class="left">Harvard</td>
</tr>
<tr>
<td class="left">Cortex-M4</td>
<td class="left">完整</td>
<td class="left">完整</td>
<td class="left">單一時脈</td>
<td class="left">有</td>
<td class="left">有</td>
<td class="left">有</td>
<td class="left">選項</td>
<td class="left">ARMv7E-M</td>
<td class="left">Harvard</td>
</tr>
</tbody>
</table>
<p>
另外, Cortex-M4F 還有以下特點是數位訊號處理器程式設計師會注意的:
</p>
<ul class="org-ul">
<li>沒有快取記憶體
</li>
<li>沒有記憶體管理單元(MMU)
</li>
<li>記憶體保護單元(MPU) 是選項功能
</li>
<li>中斷處理延遲最長 12 個時脈
</li>
</ul>
<p>
在擁有 DSP 能力的處理器中, 有幾個分類:
</p>
<ol class="org-ol">
<li>數位訊號處理器(Digital Signal Processor)
</li>
<li>數位訊號控制器(Digital Signal Controller)
</li>
</ol>
<p>
第一種就是一般印象中的數位訊號處理器, 其特點就是架構完全針對數位訊號處理而優化, 是真正能夠持續的以單一時脈執行乘積累加運算, 亦即乘積累加所需的運算元會在下一個時脈就已經載入並執行運算, 而不用等待運算元從記憶體載入的時間, 發揮極致的運算能力, 但是設計複雜度比較高, 一般來說省電性不如微處理器或微控制器。這種有 TI TMS320C67x 定點與浮點 DSP 系列與很早期的 Motorola(現為 Freescale) DSP56300(這是 Steve Jobs 出走 Apple 時創立的 NeXT 公司在他們的工作站使用的 DSP56001 的下一代產品線, 是特殊的 24-bit DSP)。大部分的 DSP 只支援定點運算, 因為同樣的面積與功耗, 定點運算能夠提供更高的運算能力, 而且以訊號處理的應用而言, 不需要浮點數這麼高的動態範圍。當然, 浮點 DSP 還是有其優勢, 尤其是在一些必須縮短開發時間的應用上, 浮點數能力使得程式設計師不需要耗費太多精神與時間處理定點數運算。
</p>
<p>
第二種就是把微控制器整合數位訊號處理能力而成, 以傳統的微控制器為主, 擁有豐富的周邊支援與輸出入腳位。ARM Cortex-M4F 屬於這一個分類, 並且因為 ARM 架構被廣泛的支援, 使得 ARM Cortex-M4F 擁有豐富的工具可以應用。以 STMicroelectronics 公司的 STM32F 系列來說, 其 10ku 報價在 2 至 10 美元之間, 往下與 16-bit MCU 重疊, 往上與入門級 DSP 重疊。
</p>
</div>
</div>
<div id="outline-container-sec-1-3" class="outline-3">
<h3 id="sec-1-3"><span class="section-number-3">3</span> DSP 運算的核心: 乘積累加(Multiply-and-Accumulate)</h3>
<div class="outline-text-3" id="text-1-3">
<p>
我們常常看到支援數位訊號處理能力的處理器都會強調其乘積累加(MAC, or Multiply-and-ACcumulate) 的能力, 這是因為在數位訊號處理演算法上, 大量的使用 MAC 運算。
</p>
<p>
不管是有限響應濾波器:
</p>
\begin{equation}
y[n] = \sum_{k=0}^{N-1} h[k]x[n-k]
\end{equation}
<p>
或是無限響應濾波器:
</p>
\begin{equation}
y[n] = b_0 x[n] + b_1 x[n-1] + b_2 x[n-2] + a_1 y[n-1] + a_2 y[n-2]
\end{equation}
<p>
還是快速傅利葉轉換中很重要的 butterfly 運算:
</p>
\begin{eqnarray}
Y[k_1] & = & X[k_1] + X[k_2] \\
Y[k_2] & = & (X[k_1] - X[k_2])e^{-j\omega}
\end{eqnarray}
<p>
這些都非常仰賴乘積累加的運算。
</p>
<p>
ARM Cortex-M4F 與乘法或乘積累加有關的指令集如下表<sup><a id="fnr.2.100" name="fnr.2.100" class="footref" href="#fn.2">2</a></sup>:
</p>
<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">
<colgroup>
<col class="left" />
<col class="left" />
<col class="left" />
</colgroup>
<thead>
<tr>
<th scope="col" class="left">運算</th>
<th scope="col" class="left">指令意義</th>
<th scope="col" class="left">指令列表</th>
</tr>
</thead>
<tbody>
<tr>
<td class="left">16 * 16 = 32</td>
<td class="left">Signed Multiply (SMUL)</td>
<td class="left">SMULBB, SMULBT, SMULTB, SMULTT</td>
</tr>
<tr>
<td class="left">16 * 16 + 32 = 32</td>
<td class="left">Signed Multiply and Accumulate (SMLA)</td>
<td class="left">SMLABB, SMLABT, SMLATB, SMLATT</td>
</tr>
<tr>
<td class="left">16 * 16 + 64 = 64</td>
<td class="left">16-bit Signed Multiply with 64-bit Accumulate (SMLAL)</td>
<td class="left">SMLALBB, SMLALBT, SMLALTB, SLMALTT</td>
</tr>
<tr>
<td class="left">16 * 32 = 32</td>
<td class="left">16-bit by 32-bit signed multiply returning 32 MSB, i.e. word (SMULW)</td>
<td class="left">SMULWB, SMULWT</td>
</tr>
<tr>
<td class="left">(16*32) + 32 = 32</td>
<td class="left">Q setting 16-bit by 32-bit signed multiply with 32-bit accumulate (SMLAW)</td>
<td class="left">SMLAWB, SMLAWT</td>
</tr>
<tr>
<td class="left">(16*16) + (16*16) = 32</td>
<td class="left">Q setting sum of dual 16-bit signed multiply (SMU-AD)</td>
<td class="left">SMUAD, SMUADX</td>
</tr>
<tr>
<td class="left">(16*16) - (16*16) = 32</td>
<td class="left">Dual 16-bit signed multiply returning difference (SMU-SD)</td>
<td class="left">SMUSD, SMUSDX</td>
</tr>
<tr>
<td class="left">(16*16) + (16*16) + 32 = 32</td>
<td class="left">Q setting dual 16-bit signed multiply with single 32-bit accumulator (SMLAD)</td>
<td class="left">SMLAD, SMLADX</td>
</tr>
<tr>
<td class="left">(16*16) - (16*16) + 32 = 32</td>
<td class="left">Q setting dual 16-bit signed multiply subtract with 32-bit accumulate (SMLSD)</td>
<td class="left">SMLSD, SMLSDX</td>
</tr>
<tr>
<td class="left">(16*16) + (16*16) + 64 = 64</td>
<td class="left">Dual 16-bit signed multiply with single 64-bit accumulator (SMLALD)</td>
<td class="left">SMLALD, SMLALDX</td>
</tr>
<tr>
<td class="left">(16*16) - (16*16) + 64 = 64</td>
<td class="left">Q setting dual 16-bit signed multiply subtract with 64-bit accumulate (SMLSLD)</td>
<td class="left">SMLSLD, SMLSLDX</td>
</tr>
</tbody>
<tbody>
<tr>
<td class="left">32 * 32 = 32</td>
<td class="left">Multiply</td>
<td class="left">MUL</td>
</tr>
<tr>
<td class="left">32 + (32 * 32) = 32</td>
<td class="left">Multiply accumulate</td>
<td class="left">MLA</td>
</tr>
<tr>
<td class="left">32 - (32 * 32) = 32</td>
<td class="left">Multiply subtract</td>
<td class="left">MLS</td>
</tr>
<tr>
<td class="left">32 * 32 = 64</td>
<td class="left">Long signed/unsigned multiply</td>
<td class="left">SMULL, UMULL</td>
</tr>
<tr>
<td class="left">(32 * 32) + 64 = 64</td>
<td class="left">Long signed/unsgiend accumulate</td>
<td class="left">SMLAL, UMLAL</td>
</tr>
<tr>
<td class="left">(32 * 32) + 32 + 32 = 64</td>
<td class="left">32-bit unsigned multiply with double 32-bit accumulation yielding 64-bit result</td>
<td class="left">UMAAL</td>
</tr>
</tbody>
<tbody>
<tr>
<td class="left">32 + (32 * 32) = 32 MSB</td>
<td class="left">32-bit multiply with 32-most-significant-bit accumulate</td>
<td class="left">SMMLA, SMMLAR</td>
</tr>
<tr>
<td class="left">32 - (32 * 32) = 32 MSB</td>
<td class="left">32-bit multiply with 32-most-significant-bit subtract</td>
<td class="left">SMMLS, SMMLSR</td>
</tr>
<tr>
<td class="left">(32 * 32) = 32 MSB</td>
<td class="left">32-bit multiply returning 32-most-significant-bits</td>
<td class="left">SMMUL, SMMULR</td>
</tr>
</tbody>
</table>
<p>
以上都是定點運算<sup><a id="fnr.3" name="fnr.3" class="footref" href="#fn.3">3</a></sup>, 並且每一個指令都能夠在一個時脈執行完畢, 或許你會問:「我只想寫 C 語言, 而且已經有函式庫, 為什麼還需要了解指令集呢?」如果你不碰數位訊號處理應用, 或許可以不用了解這一顆處理器的指令集, 但就像作業系統的程式設計師必須要了解處理器關於作業系統的指令集一樣, 數位訊號處理工程師必須在了解所有 DSP 指令集後, 想盡辦法像國稅局一樣榨乾這顆處理器, 一滴都不能剩。尤其是函式庫提供的定點運算都只有 Q31 與 Q15 的選擇, 如果你有其他特殊的需求, 就得自己寫數位訊號處理程式碼。在 C 語言的優化過程中, 使用指令集的 intrisincs 是不可避免的。
</p>
<p>
ARM Cortex-M4F 也有符合 IEEE-754 規範的浮點運算單元, 而單精確浮點數在訊號處理演算法上扮演很重要的角色, 下表列舉了單精確浮點數的運算與時脈數:
</p>
<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">
<colgroup>
<col class="left" />
<col class="left" />
<col class="right" />
</colgroup>
<thead>
<tr>
<th scope="col" class="left">單精度浮點運算</th>
<th scope="col" class="left">指令</th>
<th scope="col" class="right">執行時脈</th>
</tr>
</thead>
<tbody>
<tr>
<td class="left">加/減</td>
<td class="left">VADD.F32, VSUB.F32</td>
<td class="right">1</td>
</tr>
<tr>
<td class="left">乘法</td>
<td class="left">VMUL.F32</td>
<td class="right">3</td>
</tr>
<tr>
<td class="left">乘積累加</td>
<td class="left">VMLA.F32, VMLS.F32, VNMLA.F32, VNMLS.F32</td>
<td class="right">3</td>
</tr>
<tr>
<td class="left">Fused MAC</td>
<td class="left">VFMA.F32, VFMS.F32, VFNMA.F32, VFNMS.F32</td>
<td class="right">3</td>
</tr>
<tr>
<td class="left">平方根</td>
<td class="left">VSQRT.F32</td>
<td class="right">14</td>
</tr>
<tr>
<td class="left">除法</td>
<td class="left">VDIV.F32</td>
<td class="right">14</td>
</tr>
</tbody>
</table>
<p>
可以看出浮點數的乘法比較花時間, ARM Cortex-M4F 有提供 fused MAC 指令以增加精確度。
</p>
<p>
接下來, 我們來看實際上拿 ARM Cortex-M4F 寫數位訊號處理程式的時候的效能, 以下是一般標準的 FIR 濾波器的程式碼:
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #20b2aa;">void</span> <span style="color: #00ffff;">fir</span>(<span style="color: #20b2aa;">q31_t</span> *<span style="color: #ffd700;">in</span>, <span style="color: #20b2aa;">q31_t</span> *<span style="color: #ffd700;">out</span>, <span style="color: #20b2aa;">q31_t</span> *<span style="color: #ffd700;">coeffs</span>,
<span style="color: #20b2aa;">int</span> *<span style="color: #ffd700;">state</span>, <span style="color: #20b2aa;">int</span> <span style="color: #ffd700;">numTaps</span>, <span style="color: #20b2aa;">int</span> <span style="color: #ffd700;">blkSize</span>)
{
<span style="color: #20b2aa;">int</span> <span style="color: #ffd700;">sample</span>;
<span style="color: #20b2aa;">int</span> <span style="color: #ffd700;">k</span>;
<span style="color: #20b2aa;">q63_t</span> <span style="color: #ffd700;">sum</span>; <span style="color: #8fbc8f;">/* </span><span style="color: #8fbc8f;">Q2.62 in 64-bit acccumulator </span><span style="color: #8fbc8f;">*/</span>
<span style="color: #20b2aa;">int</span> <span style="color: #ffd700;">idx</span> = *state;
<span style="color: #00bfff;">for</span> (sample=0; sample<blkSize; sample++)
{
state[idx++] = in[sample];
sum = 0;
<span style="color: #00bfff;">for</span> (k = 0; k < numTaps; k++)
{
sum += (<span style="color: #20b2aa;">q63_t</span>) coeffs[k] * state[idx]; <span style="color: #8fbc8f;">/* </span><span style="color: #8fbc8f;">1. Fetch coefficient and sample. 2. Perform MAC </span><span style="color: #8fbc8f;">*/</span>
idx--; <span style="color: #8fbc8f;">/* </span><span style="color: #8fbc8f;">Pointer update for circular addressing </span><span style="color: #8fbc8f;">*/</span>
<span style="color: #00bfff;">if</span> (idx < 0)
{
idx = numTaps - 1;
}
}
out[sample] = (<span style="color: #20b2aa;">q31_t</span>) (sum >> 31u); <span style="color: #8fbc8f;">// </span><span style="color: #8fbc8f;">Convert Q2.62 to Q1.31</span>
}
*state = idx;
}
</pre>
</div>
<p>
參考更早之前的 FIR 濾波器運算式:<sup><a id="fnr.4" name="fnr.4" class="footref" href="#fn.4">4</a></sup>
</p>
\begin{equation}
y[n] = \sum_{k=0}^{N-1} h[k]x[n-k]
\end{equation}
<p>
h[k] 就是 coeffs[k], x[n-k] 就是 state[idx], numTaps 就是 N, out[sample] 則是 y[n].
</p>
<p>
在最內側的迴圈中包含了:
</p>
<ul class="org-ul">
<li>載入係數與輸入取樣
</li>
<li>執行乘積累加運算
</li>
<li>循環定址的指標更新
</li>
</ul>
<p>
在現代 DSP<sup><a id="fnr.5" name="fnr.5" class="footref" href="#fn.5">5</a></sup> 中, 上述運算可以在一個或兩個時脈內執行完畢, 如:
</p>
<div class="org-src-container">
<pre class="src src-assembly"> do x0,FirLoop
mac x1,y1,a x:(r0)+,x1 y:(r4)+,y1
FirLoop
</pre>
</div>
<p>
這個迴圈指令是 zero overhead loop, 而且只需一個時脈指令就能完成上述三項最內側迴圈需要完成的事項。這是數位訊號處理器的能力, 而且也需要使用組合語言來優化, 那我們來看 ARM Cortex-M4F 用 C 語言能夠達到的速度:
</p>
<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">
<colgroup>
<col class="left" />
<col class="right" />
</colgroup>
<thead>
<tr>
<th scope="col" class="left">動作</th>
<th scope="col" class="right">時脈數</th>
</tr>
</thead>
<tbody>
<tr>
<td class="left">載入 coeffs[k]</td>
<td class="right">2</td>
</tr>
<tr>
<td class="left">載入 state[idx]</td>
<td class="right">1</td>
</tr>
<tr>
<td class="left">乘積累加</td>
<td class="right">1</td>
</tr>
<tr>
<td class="left">idx--</td>
<td class="right">1</td>
</tr>
<tr>
<td class="left">循環定址</td>
<td class="right">4</td>
</tr>
<tr>
<td class="left">迴圈 overhead</td>
<td class="right">3</td>
</tr>
</tbody>
<tbody>
<tr>
<td class="left">總共</td>
<td class="right">12</td>
</tr>
</tbody>
</table>
<p>
從上述表格中可以看出, 即便 ARM Cortex-M4F 這類數位訊號控制器擁有一個時脈就可以完成的乘積累加指令, 加上其他額外的執行成本, 就增加到 12 個時脈才能完成一個乘積累加。有一些 C 語言優化的方式:
</p>
<ul class="org-ul">
<li>Circular addressing alternatives
</li>
<li>Loop unrolling
</li>
<li>Caching of intermediate variables
</li>
<li>Extensive use of SIMD and intrinsincs(還是用上指令集)
</li>
</ul>
<p>
如果用上這些, 並且輸入以及係數是 16-bit 的情況下, 是可以達到平均每個乘積累加 1.625 個時脈的程度。<sup><a id="fnr.6" name="fnr.6" class="footref" href="#fn.6">6</a></sup>如果需要的精確度是 32-bit 的情況下, 可能會需要更多時脈, 但已經與數位訊號處理器差距不算遠了, 當然若與同樣擁有 SIMD 能力的數位訊號處理器並且優化相比, 還是差上一大截, 但是搭配 ARM 廣泛的周邊與軟體資源, 這樣的效能已經很吸引人。
</p>
<p>
在數位訊號處理程式上, ARM 提供了 CMSIS(Cortex Microcontroller Software Interface Standard) DSP 函式庫, 在實際開發時只需要呼叫這些函數即可, 但要善用這個函式庫, 還是需要對於數位訊號處理基本概念有認識才行。
</p>
<p>
另外, 在使用 ARM Cortex-M4F 的累加器的時候, 需要注意的是, 累加器不會自動作飽和動作, 因此做定點運算的時候, 必需自行預留累加的空間, 或是先將數值預先縮小以避免溢位。
</p>
</div>
</div>
<div id="outline-container-sec-1-4" class="outline-3">
<h3 id="sec-1-4"><span class="section-number-3">4</span> 結語</h3>
<div class="outline-text-3" id="text-1-4">
<p>
從 ARM7 問世開始, ARM 這間公司展現的企圖就是除了 32-bit microprocessor 以外, 還要開始蠶食 8-bit/16-bit MCU 的市場, 經過了一陣子的努力之後, 繼續推出了 ARM Cortex-M 系列展現強烈的企圖心, 如今採用的公司漸漸增多, 侵蝕了部分 16-bit MCU 的市場, MCU 程式設計師必須要看清這個趨勢, 學習 ARM 系列架構來接受這個潮流變化。Cortex-M 系列最高接的 Cortex-M4F 提供了數位訊號處理能力, 成為數位訊號控制器, 在省電性主導的地方, 與 16-bit DSP 相比互有優劣, 但 Cortex-M4F 提供了 32-bit 浮點運算, 讓開發時間能夠縮短, 千萬不可小看 ARM 在數位訊號控制器上的未來性。本文只討論了 ARM Cortex-M4F 的 DSP 能力以及在新的 DSP 專案中使用 ARM Cortex-M4F 的可能性, 筆者將在後續的文章中陸陸續續介紹如何使用 Cortex-M4F 來做實際的數位訊號處理應用。
</p>
</div>
</div>
</div>
<div id="footnotes">
<h2 class="footnotes">Footnotes: </h2>
<div id="text-footnotes">
<div class="footdef"><sup><a id="fn.1" name="fn.1" class="footnum" href="#fnr.1">1</a></sup> <p class="footpara">
Tom Krazit, <i>ARMed for the living room</i>, <a href="http://news.cnet.com/ARMed-for-the-living-room/2100-1006_3-6056729.html">http://news.cnet.com/ARMed-for-the-living-room/2100-1006_3-6056729.html</a>
</p></div>
<div class="footdef"><sup><a id="fn.2" name="fn.2" class="footnum" href="#fnr.2">2</a></sup> <p class="footpara">
<i>ARM® Cortex™-M4 Processor Technical Reference Manual Revision r0p1</i>, <a href="http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0439d/index.html">http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0439d/index.html</a>
</p></div>
<div class="footdef"><sup><a id="fn.3" name="fn.3" class="footnum" href="#fnr.3">3</a></sup> <p class="footpara">
有關於定點數 Q format 可以參考我之前寫的「定點數表示法」, <a href="http://alberthuang314.blogspot.tw/2012/08/blog-post.html">http://alberthuang314.blogspot.tw/2012/08/blog-post.html</a>
</p></div>
<div class="footdef"><sup><a id="fn.4" name="fn.4" class="footnum" href="#fnr.4">4</a></sup> <p class="footpara">
有關於 FIR 有限響應濾波器的概念可以參考我之前寫的「淺談動平均濾波器」, <a href="http://alberthuang314.blogspot.tw/2012/08/blog-post_24.html">http://alberthuang314.blogspot.tw/2012/08/blog-post_24.html</a>
</p></div>
<div class="footdef"><sup><a id="fn.5" name="fn.5" class="footnum" href="#fnr.5">5</a></sup> <p class="footpara">
這還是 Motorola DSP56300 的組合語言, 是將近二十年前的產品。
</p></div>
<div class="footdef"><sup><a id="fn.6" name="fn.6" class="footnum" href="#fnr.6">6</a></sup> <p class="footpara">
Kishore Dasari, <i>Designing with the Cortex-M4</i>, <a href="https://www.arm.com/files/pdf/DSPConceptsM4Presentation.pdf">https://www.arm.com/files/pdf/DSPConceptsM4Presentation.pdf</a>
</p></div>
</div>
</div></div>
<div id="postamble" class="status">
<p class="author">Author: Albert Huang</p>
<p class="date">Created: 2014-02-18 Tue 22:05</p>
<p class="creator"><a href="http://www.gnu.org/software/emacs/">Emacs</a> 24.3.1 (<a href="http://orgmode.org">Org</a> mode 8.2.1)</p>
<p class="validation"><a href="http://validator.w3.org/check?uri=referer">Validate</a></p>
</div>Albert Huanghttp://www.blogger.com/profile/09910403631033610841noreply@blogger.com1tag:blogger.com,1999:blog-5393693761509999841.post-75629044155805017592013-02-02T21:48:00.001+08:002013-02-02T21:56:41.794+08:00如何在 GNU Emacs 減少按鍵次數並提升工作效率<br />
GNU Emacs 是一個非常 powerful 的編輯器, 這個就不需要我多作介紹, 但是與 vim 相比, GNU Emacs 有一個比較大的缺點就是按鍵多。只要是採用 modeless 的方式編輯, 又要功能多, 按鍵數很難減少, 但是還是有一些方法, 可以讓我們整體的按鍵數量變少的, 可以減少手的傷害。至於那些買了青軸機械式鍵盤之後, 想辦法多打字讓別人聽按鍵聲音的, 就不在本文的討論範圍內。<br />
<br />GNU Emacs 有兩種方式減少打字數目, 筆者認為值得推薦, 一種是用巨集(macro), 另一種是用 skeleton 套件。當然還有第三種是編寫 Emacs Lisp, 寫點函數, 這個難度比較高, 不太適合初學者。今天筆者介紹的這兩個方式都很適合初學者使用。<br />
<div id="table-of-contents">
<h2>
Table of Contents</h2>
<div id="text-table-of-contents">
<ul><br />
<li><a href="http://www.blogger.com/blogger.g?blogID=5393693761509999841#sec-1">1 巨集</a></li>
<li><a href="http://www.blogger.com/blogger.g?blogID=5393693761509999841#sec-2">2 Skeleton</a></li>
<li><a href="http://www.blogger.com/blogger.g?blogID=5393693761509999841#sec-3">3 結語</a></li>
</ul>
</div>
</div>
<div class="outline-2" id="outline-container-1">
<br />
<h2 id="sec-1">
巨集</h2>
<div class="outline-text-2" id="text-1">
首先, 我們來看看巨集。要知道 EMACS 這個名字是由 Editing MACroS 來的, 巨集可是 Emacs 的核心價值啊!只要你發現你在做重複性的工作, 就可以把那些一連串的按鍵動作變成巨集。
<br />定義巨集很簡單, 在你的一連串按鍵動作開始之前, 先輸入 <code>C-x (</code>, 然後就開始按照平常的動作按按鍵, 按完所有按鍵之後, 鍵入 <code>C-x )</code> 就完成巨集的定義了。
<br />
要執行剛剛定義完的巨集, 就按 <code>C-x e</code>, 也可以配合 Emacs 的數字前置指令來執行多次的巨集。比如說你想要執行這個巨集四次, 就鍵入 <code>M-4 C-x e</code> 就會執行這個巨集四次。
<pre class="example">The quick brown fox jumps over the lazy dog</pre>
<br />比方說, 你想要把上面這個檔案改成一個英文單字一行, 可以用巨集來做, 方法如下:
<table border="2" cellpadding="6" cellspacing="0" frame="hsides" rules="groups"><colgroup><col class="left"></col><col class="left"></col></colgroup><thead>
<tr><th class="left" scope="col">按鍵</th><th class="left" scope="col">動作</th></tr>
</thead><tbody>
<tr><td class="left">C-x (</td><td class="left">開始錄製巨集</td></tr>
<tr><td class="left">M-f</td><td class="left">把游標往前移一個單字</td></tr>
<tr><td class="left">C-d</td><td class="left">刪除一個字元</td></tr>
<tr><td class="left">[ENTER]</td><td class="left">插入換行字元</td></tr>
<tr><td class="left">C-x )</td><td class="left">結束巨集的錄製</td></tr>
</tbody></table>
<br />
上述的巨集可以讓一個單字單獨存在於一行, 把剩下的文字換到下一行去, 如果要把所有英文單字都單獨存在於一行, 就需要重複作這個巨集。可以先用 <code>M-x count-words-region</code> 來計算這一行的單字數, 九個。所以要處理完所有的單字, 就輸入按鍵 <code>M-9 C-x e</code>, 不過通常我們錄製巨集的時候已經先做完一遍了, 那這時候你只需要執行 8 次就好。執行完結果就會如下所示:
<br />
<pre class="example">The
quick
brown
fox
jumps
over
the
lazy
dog</pre>
<br /></div>
<br /></div>
<div class="outline-2" id="outline-container-2">
<br />
<h2 id="sec-2">
Skeleton</h2>
<br />
<div class="outline-text-2" id="text-2">
<br />
<br />
如果你的重複性工作, 是經常性的使用到, 比方說寫函數時的註解, 常常需要寫函數名稱、作者、建立的時間等等資訊, 有些是每次都寫一樣的資訊(如作者), 有些則可以由函數執行結果得來(如日期), 有些需要打兩次一樣的字串(如函數名稱), 那麼 skeleton 就是一個不錯的工具, 讓你減少打字數目。<br />
<br />
<br />使用 skeleton 的方法如下:<br />
<br />
<pre class="src src-lisp">(<span style="color: deepskyblue;">define-skeleton</span> <span style="color: cyan;">your-skeleton-name</span>
<span style="color: darkorange;">"String to describe this skeleton."</span>
<span style="color: deeppink;">"String that will be inserted when you call your-skeleton"</span>)</pre>
<br />
<br />
<br />然後你就可以用 Emacs Lisp 函數一樣的呼叫方式來呼叫: <br /><code>M-x your-skeleton-name</code> 這函數就會自動從游標位置插入預先定義好的字串。<br />
高階一點的用法就會牽扯到<br />
<ul><br />
<li>使用者輸入字串<br /><ul><br />
<li>使用 (skeleton-read)</li>
</ul>
<br /></li>
<li>重複使用者輸入的字串<br /><ul><br />
<li>使用 v1, v2 變數</li>
</ul>
<br /></li>
<li>游標最後所處位置<br /><ul><br />
<li>使用 "_" 來標示</li>
</ul>
<br /></li>
<li>呼叫 Emacs Lisp 函數來插入字串<br /><ul><br />
<li>直接呼叫</li>
</ul>
<br /></li>
</ul>
<br />
筆者就用我自己用的一個例子來說明 skeleton:<br />
<pre class="src src-lisp"><span style="color: darkseagreen;">; </span><span style="color: darkseagreen;">Skeleton for assembly subroutine header</span>
(<span style="color: deepskyblue;">define-skeleton</span> <span style="color: cyan;">insert-asm-header</span>
<span style="color: darkorange;">"Prompt for subroutine name and insert assembly subroutine header"</span>
<span style="color: deeppink;">""</span> ?\n
<span style="color: deeppink;">";******************************************************************************"</span> ?\n
<span style="color: deeppink;">"; Name:\t\t"</span> (setq v1 (skeleton-read <span style="color: deeppink;">"Subroutine name: "</span>))?\n
<span style="color: deeppink;">"; Purpose:"</span> ?\n
<span style="color: deeppink;">"; "</span> (skeleton-read <span style="color: deeppink;">"Purpose: "</span>) ?\n
<span style="color: deeppink;">"; Method:\t"</span> ?\n
<span style="color: deeppink;">"; "</span> ?\n
<span style="color: deeppink;">"; Parameters:\t\t"</span> (skeleton-read <span style="color: deeppink;">"Parameters: "</span>) ?\n
<span style="color: deeppink;">"; Affected regs:\t"</span> ?\n
<span style="color: deeppink;">"; Author:\tAlbert Chun-Chieh Huang, "</span> (insert-current-date) ?\n
<span style="color: deeppink;">";******************************************************************************"</span> ?\n
v1 \n
<span style="color: deeppink;">""</span> _ \n
<span style="color: deeppink;">"rts"</span> \n
)</pre>
<br />
<br />
<br />定義完之後, 我們就可以用 <code>M-x insert-asm-header</code> 來呼叫這個 skeleton, 呼叫之後, 在 mode line 會出現<br />
<pre class="example">Subroutine name: </pre>
<br />
<br />
<br />要求使用者輸入副程式名稱, 除了馬上把這名稱字串放到 "Name:" 之後, 並且存在 v1 這個變數裡。 接下來會要求使用者輸入 <code>Purpose:</code> 說明這個副程式的用途, 並把副程式用途就插入 <code>(skeleton-read "Purpose: ")</code> 的位置上。接下來的 Parameters: 也一樣。到了 Author 的地方就呼叫 Emacs Lisp 函數 <code>(insert-current-date)</code> 把日期填上。<br />在倒數第四行的 v1 就是把剛剛存在 v1 這個變數的副程式名稱取代 v1 填上去。<br />倒數第三行的 "_" 就是指示 skeleton 插入完這些字串之後, 游標要回到這個位置來。<br />所有被雙引號包起來的都是字串, 不會有特殊意義。在雙引號以外的, 就是 Emacs Lisp 函數、變數、或是特殊字元。=\n= 是換行並且依照所處的 mode 縮排, 而 <code>?\n</code> 則只有單純的換行字元而已。<br />
<br />
<br />下面的例子就是執行完後的結果, 游標會停在倒數第二行, 與 rts 同樣的縮排位置上, 方便我打第一個 instruction. <br />
<pre class="example">;******************************************************************************
; Name: Test
; Purpose:
; Test
; Method:
;
; Parameters: a1
; Affected regs:
; Author: Albert Chun-Chieh Huang, 02 February 2013
;******************************************************************************
Test
rts</pre>
<br />
<br />如果對於 skeleton 想要有更深入的了解, 可以按 <code>C-h f skeleton-insert</code>, 裡面有關於 define-skeleton 的字串該怎麼寫的詳盡說明。<br />
<br /></div>
<br />
<br /></div>
<br />
<br />
<div class="outline-2" id="outline-container-3">
<br />
<h2 id="sec-3">
結語</h2>
<br />
<div class="outline-text-2" id="text-3">
<br />
<br />
要提升工作效率, 第一要件就是先找出重複的工作, 並且用快速有效率的方法執行這個工作。當你找出重複性的部份之後, 可以把重複不變的部份抽出來變成巨集, 如果有經常性的重複編輯工作, 就可以考慮用 skeleton 來定義, 如果有每一次呼叫變動的部份, 就考慮把這些變動用呼叫函數或是輸入參數的方式來引入, 如此就可以有效的減少按鍵次數, 並且提升工作效率。</div>
<br /></div>
<br />
<br />
-- <br />
Albert Huang <br />
Chun-Chieh Huang(黃俊傑) Albert Huanghttp://www.blogger.com/profile/09910403631033610841noreply@blogger.com0tag:blogger.com,1999:blog-5393693761509999841.post-74580898185205970462012-12-18T11:26:00.000+08:002012-12-18T13:09:26.760+08:00GNU Radio Talk: A Glimpse into Developing Software-Defined Radio by Python這是我十二月十七日在 PyHUG(一個新竹的 Python 社群, 由陳永昱(Yung-Yu Chen) 博士與我在 2011 年所組織發起的)講的講題, 內容簡介了軟體無線電的概念, 軟體無線電的硬體以及開源的專案 GNU Radio, 以及使用 GNU Radio 來開發軟體無線電的三種不同路徑的簡介。這是 GNU Radio 系列講題的第一個, 接下來的講題目前未定, 可能會從數位訊號處理的概念以及如何使用 GNU Radio 來作濾波器先切入, 然後再看聽眾反應決定接下來的主題。有任何建議都歡迎提出來!<br />
<br />
PyHUG 目前的聚會模式是每個月的第一與第三個星期一晚上, 通常都會有一個或一個以上的二十分鐘短講, 地點在交大計中一樓訓練教室, 所有訊息都是透過 meetup 這個網頁來公告, 你可以到<a href="http://www.meetup.com/pythonhug/">這裡</a>看相關訊息。<br />
<br />
The slides were given to PyHUG in December 17, 2012 in PyHUG, which is Python Hsinchu User Group initiated by Dr. Yung-Yu Chen and I in 2011. In this talk, I introduced the concept of software-defined radio, the free & open source software-defined radio project - GNU Radio, RF front-end hardware that can be used with GNU Radio provided by Ettus Research and Realtek, and illustrated three ways to develop software-defined radio by GNU Radio. This is the first of GNU Radio series talk, the topics for the subsequent talks are to be done, and I'll probably start from using filters in GNU Radio as well as concepts of digital signal processing. And then I'll try to decide topics depending upon feedback of attendees. Any idea or suggestions are welcome!<br />
<br />
Currently we have regular meetings on the first and the third Monday nights every month at the training classroom in the building of computer center in National Chaio-Tung University. Normally there will be one or two 20-minute talks. All messages related to PyHUG meetings or events are distributed via meetup website, and you can find information <a href="http://www.meetup.com/pythonhug/">here</a>.<br />
<br />
<a href="http://www.slideshare.net/AlbertHuang314/a-glimpse-into-developing-softwaredefined-radio-by-python">Download/view slides of "A Glimpse into Developing Software-Defined Radio by Python"</a>Albert Huanghttp://www.blogger.com/profile/09910403631033610841noreply@blogger.com0tag:blogger.com,1999:blog-5393693761509999841.post-18245202765658729312012-12-15T12:21:00.001+08:002014-08-25T01:01:22.148+08:00工程訓練與人文素養<br /><p>工程訓練與人文素養, 一個是左腦, 一個是右腦, 一個需要理性, 一個需要感性, 看似非常衝突的兩個面向, 但我覺得是一個工程師必須同時要具備的兩個面向。<br /></p><p><br />工程師, 尤其是電子電機工程師, 在現代的社會及媒體上, 有著許多不同的稱號, 比如說: 科技宅男、竹科新貴,中國大陸還有張江男之類的稱號, 其實都帶有些許戲謔的成分在。但回首過往, 被譽為中國鐵路之父的詹天佑(1861-1919), 不就是一名工程師嗎?他幼年就留學美國, 後來回近代中國修築了中國第一條鐵路, 並且修築了難度頗高的京張鐵路, 不僅帶給當代中國交通上的便利, 更因修築了外國人認為中國人不可能辦到的鐵路而激勵了當時的華人世界。更現代一些, 我們都在國中小學課本裡面讀過的作者, 陳之藩先生(1925-2012), 寫了不少膾炙人口的文章, 被收錄在「旅美小簡」、「在春風裡」、「劍河倒影」、「一星如月」等等, 我想在台灣應該是幾乎每一個人都讀過陳之藩先生的文章, 而他是學電機的, 也是工程師出身。<br /></p><p><br />工程訓練的目的是訓練一個人, 在既有的流程或基礎上, 運用自己所學的知識與理論, 事先籌劃改善的方法, 並預測改善後的成效, 然後著手實踐這個改善方法。因此, 大學的工程相關科系有著非常多的理論與實驗課程, 這些都在養成工程師基礎的知識, 與動手做的能力, 兩者缺一不可, 卻也相輔相成。沒有基礎知識, 不知道實驗結果的真正原因為何; 沒有動手做, 就不知道自己缺乏哪些知識與理論, 也不知道為什麼要學那些理論。<br /></p><p><br />人文素養對一名工程師來說, 乍看之下似乎沒有必要, 畢竟工程師不需要人文素養就能夠成為一名工程師。但是若從工程的本質來看的話, 人文素養又變成不可或缺的一部分。我來給工程下個定義, 把上一段的工程訓練目的稍微擴展一下, 「工程是為了改善人類的生活, 而在既有的基礎上, 運用自己所學的知識, 事先規劃改善方法, 預測改善後的成效, 並且著手實踐它。」既然是為了改善人類的生活, 人文素養能說不重要嗎?工程師做成的產品大部分時候是要給人使用的, 如果工程師在設計的時候, 脫離了「人」來思考, 設計出來的東西不是難以使用, 就是曲高和寡。工程師如果對於人性有所了解, 懂得人, 那麼就能夠很輕易的從日常生活中, 找到改善生活的方法, 讓人類的生活更便利。市面上有一種拖把, 有個桶子, 上面有個轉盤, 在洗好拖把之後可以用腳踩使轉盤轉動, 利用離心力的原理可以輕易的把水甩乾, 就不需要用手擰乾拖把而把手弄髒, 這個產品的問世帶給所有需要打掃的人, 包括家庭主婦與幫理家務的好男人, 非常便利的生活。這個就是因為發明人, 在幫忙老婆打掃家務的時候, 對於整個流程有敏銳與細膩的觀察, 從中找到改善的方法, 並且實踐這個改善的方法。我認為這就是帶有人文素養的工程思維表現。<br /></p><p><br />如果科學家的熱情是來自於研究宇宙的真理, 哲學家的熱情是來自於思考人類的問題, 那麼我覺得工程師的熱情就來自於改善人類的生活。我無法想像工程師只以賺錢為唯一的目的, 也不能是主要目的, 那會讓工程的樂趣整個消失不見, 只剩下金錢遊戲。你能想像廚師只愛賺錢, 而不以做好料理讓客人吃得愉快為熱情嗎?我並不是說賺錢不好, 相反的, 我覺得賺錢很好, 但是以賺錢為目的與熱情的, 有別的職業, 比方說學習巴菲特在股票證券市場上賺錢, 巴菲特就說過他對於賺錢有極大的熱情, 股票與金融市場的即時回報就是金錢, 你把這件事做得愈好, 賺的錢愈多, 如果你的熱情就來自於賺錢, 那麼在證券市場上的即時回報也會讓你的熱情不斷加增。而工程師的即時回報, 是把一個東西改善而變得更好, 而我們心裡知道這些小小的改善累積起來, 就會讓人類的生活變得更好更便利, 但是比較大筆的金錢也許是一年一次的回報, 如果工程師的熱情來自於金錢, 那麼在工程師生涯裡面, 你只有千分之二點七左右(1/365)的時間是有回報來增強你的熱情的, 絕大多數的時間, 你要做你不覺得有趣的事情, 我說這也太痛苦了吧!工程師生涯看似枯燥乏味, 但如果你的熱情來自於改善人類的生活, 那麼這些枯燥乏味的事情, 就會頓時變得很有趣!當你習慣於觀察周遭生活, 找出改善方法, 並且著手實踐它, 誰說下一個改善人類生活的發明家不會是你呢?<br /></p><br/>-- <br/>Albert Huang <br/>Chun-Chieh Huang(黃俊傑) <br/>Albert Huanghttp://www.blogger.com/profile/09910403631033610841noreply@blogger.com0tag:blogger.com,1999:blog-5393693761509999841.post-37225198209013978932012-12-12T20:51:00.003+08:002012-12-12T20:53:11.538+08:00寫實驗紀錄或工作日誌的重要性<br /><p>從退伍之後, 真的開始有寫程式起, 我就開始寫工作日誌, 一直保持習慣到如今。我從中獲得不少的好處, 今天利用這篇文章來跟大家分享一下。<br /></p><br /><p><br />先從我為什麼開始寫工作日誌講起好了。如同 Donald E. Knuth 在 "Coders at Work"<sup><a class="footref" name="fnr-.1" href="#fn-.1">1</a></sup> 裡面所講的, 寫程式是一個很耗腦力, 需要全神貫注的一件事。大家應該都還記得大學要交程式作業前, 常常一寫程式就沒日沒夜, 通宵達旦, 不寫到一個段落不善罷甘休, 但是程式設計的一個段落常常又是一兩天的功夫才會到。萬一還沒寫到一個段落就先休息, 等休息回來又忘記本來的思路了, 於是只好重新思考, 如此會花更多的時間寫程式! 正因為害怕這種事情發生, 於是, 熬夜寫程式就變成了交作業前的常態。大學時作業交完了, 可以好好休息一陣子, 不用每天想程式, 一旦開始工作, 平常的週間五天就要每天寫程式了, 遇到趕專案進度的時候, 可能要一週工作六天!<sup><a class="footref" name="fnr-.2" href="#fn-.2">2</a></sup> 因此如何保持每天都能夠有效率的寫程式就變成了一個挑戰與學習, 熬夜變成一個儘量避免的事情, 因為熬夜很容易讓第二天的工作效率大幅下降, 而且晚上最好還是要有自己的生活, 工作才能長長久久的。所以, 我開始寫工作日誌的動機, 就是不想熬夜, 因此, 每天在下班之前, 把當天的工作進度以及對還沒實現的部份的所有想法, 儘量的寫下來, 要足夠清楚明瞭到自己心裡覺得沒什麼好寫了, 而且第二天還能夠看懂。如此一來, 一旦闔上工作日誌, 就可以下班而不會一直擔心自己會忘記原本的想法, 下班後就可以好好放鬆。第二天來辦公室工作的時候, 一看昨天的工作日誌, 也可以很快知道昨天的進度在哪裡, 馬上可以接手繼續下去。<br /></p><br /><p><br />那麼工作日誌要如何撰寫呢?工作日誌的內容可以區分成幾類: 1) 設計 2) 當日該完成事項 3) 工作紀錄 4) 實驗紀錄。<br /></p><br /><p><br />在設計的部份, 筆者的建議是儘量用圖形表示, 因為詳細的文字可能會被紀錄在文件或是程式的註解中, 而圖形是一個描述概念非常有力量的工具, 在工作日誌中就儘量以圖形加上一些重點文字來紀錄你的設計, 這樣在實作過程中可以隨時翻閱設計圖, 可以很快的從程式設計的細節中, 再度回到一個高度來鳥瞰整個叢林, 這樣才不會迷失在樹林中(實作細節)。<br /></p><br /><p><br />當日該完成事項是每天一開始的時候, 告訴自己還有哪些工作還沒完成, 每個工作的優先順序是如何, 這樣在寫任何程式之前, 可以在心中先建立一個清單, 工作效率會大幅提升。如果你有使用萬用手冊的習慣, 那麼這部份就不用太著墨, 只要在執行那個工作的時候, 把工作紀錄寫下來即可。<br /></p><br /><p><br />工作紀錄只要把重點記錄下來即可, 不必把每一個動作記錄下來, 但是要把 know-how 記錄下來, 才不會「知其然而不知其所以然。」<br /></p><br /><p><br />在追蹤某個問題的發生點時, 我們常常做的是如同建立樹狀圖一般, 從 root(issue) 一路往下追蹤到真正發生的原因(root cause), 而常常在分支點時, 都有很多個不同的追蹤方向, 有的時候, 我們會懷疑數個分支都有可能發生問題, 或是我們也許會判斷錯誤導致追蹤錯分支, 甚至有的時候, 一個 issue 是由多個錯誤累積產生的, 就有可能有數個 root cause, 所以數個分支都是問題。這時候有實驗紀錄的話, 就有非常大的幫助。實驗紀錄應該儘量詳盡的紀錄日後可能有幫助的細節, 比如說實驗的設定、過程與結果, 這些都要詳盡紀錄。如果是在追某個或某些 bug, 在分支點時, 應該把所有可能的方向、往這個分支追蹤的判斷理由、每個分支需要花費的成本估計記錄下來, 萬一日後發現不是那麼一回事, 還可以回頭往另一個方向追。或是當某個分支解決之後, 回頭來看該分支所屬的 parent, 看看那個 parent 是不是已經也被解決, 如果沒有, 就表示還有其他原因造成那個錯誤, 就要繼續追蹤其他分支。另外, 很多時候我們可以從統計上來了解我們是否解決完所有的問題, 比方說掉封包的機率(packet dropping probability), 在解網路 driver 或 physical layer 那一層相關問題的時候, 是一個頗適合的測量指標, 我們可以從掉封包的機率的改變看出我們解的問題佔的比例有多大, 是否已經解決大部分的問題。當然, 當掉封包的機率很小的時候, 也不代表我們把問題解決完了, 這時候可以用亂數的方式產生封包來找出我們可能沒發現的問題。這些猜測, 以及某個 root cause 解決完之後的掉封包機率的改變都要寫下來。以掉封包機率而言, 某個 bug 解完之後, 如果沒有一個數量級(10 倍)以上的改變, 那這個 bug 可能跟你的 issue 沒有太大相關。再來, 如果你做實驗之後發現傳送 1000 個封包之後, 掉了 1 個封包, 這時候也至少要把測試數量提升一個數量級以上, 也就是至少傳送 10<sup>4</sup> 個封包來測試掉封包機率。<br /></p><br /><p><br />在每天工作要結束前, 重頭再把工作日誌翻閱一遍, 看看今日的工作還有哪些沒有完成, 然後要紀錄腦袋裡對於今日的工作還有什麼想法, 未來該追蹤的方向是什麼, 總之把心中覺得未完成的東西紀錄在紙上, 這樣心中就不會有牽掛, 之後也不會因為忘記某些非常好的想法而扼腕。<br /></p><br /><p><br />手寫的工作日誌最好有索引, 把每天的主題用一句話統一寫到那本工作日誌的開頭或結尾的地方, 以便日後快速翻閱。每個月或每一季再花一點時間把工作日誌重點整理一次, 以供日後學習之用, 如此就可以累積寶貴的經驗。<br /></p><br /><p><br />工作日誌以內頁的記號, 可以分成方格、直線、網點與空白。每個人都有不同的選擇, 方格與網點適合繪圖或實驗紀錄, 直線適合文字比較多的紀錄, 空白是比較少使用的格式, 但是限制也最少。我個人覺得方格頗適合繪圖, 會很鼓勵使用的人用圖形來表示, 比較適合創意多的設計。而直線則比較中規中矩, 會鼓勵使用的人用文字來呈現, 比較適合不需要圖形表現的紀錄。<br /></p><br /><p><br />在今天的文章裡, 我分享了過去十幾年我寫工作日誌的經驗與方法, 我從紀錄工作日誌的習慣, 以及整理工作日誌的重點, 學習到非常多自己在業界的經驗, 這些經驗都非常寶貴。各位在看完之後, 也許能夠從中獲得一些靈感, 也開始寫工作日誌, 並且享受到下班就把一切放下的愜意!有句話說:「經驗是你最好的老師」,在用工作日誌的形式來紀錄與整理你的經驗之後, 經驗絕對會變成你很好的老師!<br /></p><br /><div id="footnotes"><br /><h2 class="footnotes">Footnotes: </h2><br /><div id="text-footnotes"><br /><p class="footnote"><sup><a class="footnum" name="fn-.1" href="#fnr-.1">1</a></sup> Peter Seibel 著、蔡學鏞 譯, 「編程的頂尖對話-閱讀 15 位軟體大師的核心思維」, 碁峰, 民 100 年。<br /></p><br /><br /><p class="footnote"><sup><a class="footnum" name="fn-.2" href="#fnr-.2">2</a></sup> 筆者建議星期天還是好好休息, 以筆者過去的經驗, 如果每週工作七天沒有休息, 兩週之後每一天的工作效率大概就只剩下 50% 不到吧, 終究是要還回去的, 所以還是以每週工作六天為最大限度。<br /></p><br /></div><br /></div><br /><br/>-- <br/>Albert Huang <br/>Chun-Chieh Huang(黃俊傑) <br/>Albert Huanghttp://www.blogger.com/profile/09910403631033610841noreply@blogger.com0tag:blogger.com,1999:blog-5393693761509999841.post-23337633598782662952012-12-04T18:29:00.001+08:002012-12-04T18:29:31.668+08:00平均同步訊號的意義 - 如何處理雜訊<br /><p>這個世界上的事情基本上是不可預測的, 在訊號處理上, 我們把不能夠預測的部份都當作是雜訊來看待, 然後用統計的觀點來看我們想要的訊號。<br /></p><br /><p><br />在這篇文章裡, 筆者會介紹對待雜訊最基本的工具: 平均, 以及在平均這個運算上, 我們能夠得到什麼樣的好處, 也就是能夠得到多少增益(gain), 這樣我們就知道需要花多少次的平均能夠得到我們想要的結果。為了比較容易說明平均, 在這篇文章裡, 筆者只先專注在同步訊號的平均, 而這也是示波器的基本原理之一。<br /></p><br /><br /><div id="table-of-contents"><br /><h2>Table of Contents</h2><br /><div id="text-table-of-contents"><br /><ul><br /><li><a href="#sec-1">1 同步平均 (Coherent Averaging)</a></li><br /><li><a href="#sec-2">2 增益</a></li><br /><li><a href="#sec-3">3 結語</a></li><br /><li><a href="#sec-4">4 參考書目</a></li><br /></ul><br /></div><br /></div><br /><br /><div id="outline-container-1" class="outline-2"><br /><h2 id="sec-1">同步平均 (Coherent Averaging)</h2><br /><div class="outline-text-2" id="text-1"><br /><br /><p>訊號有分非週期性與週期性序號, 要能夠同步, 必須是週期訊號, 所以像語音訊號這種非週期訊號, 我們就先不討論。週期訊號裡面, 又以正弦波在頻域上最單純, 所以我們先來看一段正弦波。這是週期為 20 的正弦波, 圖上總共兩個週期:<br /><table style="width:auto;"><tr><td><a href="https://picasaweb.google.com/lh/photo/opQQK3WBfNx-nRIKvk1YhdMTjNZETYmyPJy0liipFm0?feat=embedwebsite"><img src="https://lh6.googleusercontent.com/-M4m0HCsurp8/UL3MPKPIu_I/AAAAAAAABwY/fxYjst_0RAA/s800/SignalAveragingNoNoise.jpg" height="400" width="600" /></a></td></tr><tr><td style="font-family:arial,sans-serif; font-size:11px; text-align:right">From <a href="https://picasaweb.google.com/108267210070859251792/SignalAveraging?authuser=0&feat=embedwebsite">SignalAveraging</a></td></tr></table><br /><br />我們把上述的數位訊號表列如下:<br /></p><table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides"><br /><colgroup><col class="left" /><col class="left" /><col class="left" /><col class="left" /><col class="left" /><col class="left" /><col class="left" /><col class="left" /><col class="left" /><col class="left" /><br /></colgroup><br /><thead><br /><tr><th scope="col" class="left">X(0)</th><th scope="col" class="left">X(1)</th><th scope="col" class="left">X(2)</th><th scope="col" class="left">X(3)</th><th scope="col" class="left">X(4)</th><th scope="col" class="left">X(5)</th><th scope="col" class="left">X(6)</th><th scope="col" class="left">X(7)</th><th scope="col" class="left">X(8)</th><th scope="col" class="left">X(9)</th></tr><br /><tr><th scope="col" class="left">0.0000</th><th scope="col" class="left">0.3090</th><th scope="col" class="left">0.5878</th><th scope="col" class="left">0.8090</th><th scope="col" class="left">0.9511</th><th scope="col" class="left">1.0000</th><th scope="col" class="left">0.9511</th><th scope="col" class="left">0.8090</th><th scope="col" class="left">0.5878</th><th scope="col" class="left">0.3090</th></tr><br /></thead><br /><tbody><br /><tr><td class="left">X(10)</td><td class="left">X(11)</td><td class="left">X(12)</td><td class="left">X(13)</td><td class="left">X(14)</td><td class="left">X(15)</td><td class="left">X(16)</td><td class="left">X(17)</td><td class="left">X(18)</td><td class="left">X(19)</td></tr><br /><tr><td class="left">0.0000</td><td class="left">-0.3090</td><td class="left">-0.5878</td><td class="left">-0.8090</td><td class="left">-0.9511</td><td class="left">-1.0000</td><td class="left">-0.9511</td><td class="left">-0.8090</td><td class="left">-0.5878</td><td class="left">-0.3090</td></tr><br /></tbody><br /><tbody><br /><tr><td class="left">X(20)</td><td class="left">X(21)</td><td class="left">X(22)</td><td class="left">X(23)</td><td class="left">X(24)</td><td class="left">X(25)</td><td class="left">X(26)</td><td class="left">X(27)</td><td class="left">X(28)</td><td class="left">X(29)</td></tr><br /><tr><td class="left">-0.0000</td><td class="left">0.3090</td><td class="left">0.5878</td><td class="left">0.8090</td><td class="left">0.9511</td><td class="left">1.0000</td><td class="left">0.9511</td><td class="left">0.8090</td><td class="left">0.5878</td><td class="left">0.3090</td></tr><br /></tbody><br /><tbody><br /><tr><td class="left">X(30)</td><td class="left">X(31)</td><td class="left">X(32)</td><td class="left">X(33)</td><td class="left">X(34)</td><td class="left">X(35)</td><td class="left">X(36)</td><td class="left">X(37)</td><td class="left">X(38)</td><td class="left">X(39)</td></tr><br /><tr><td class="left">0.0000</td><td class="left">-0.3090</td><td class="left">-0.5878</td><td class="left">-0.8090</td><td class="left">-0.9511</td><td class="left">-1.0000</td><td class="left">-0.9511</td><td class="left">-0.8090</td><td class="left">-0.5878</td><td class="left">-0.3090</td></tr><br /></tbody><br /></table><br /><br /><br /><p><br />那麼平均這兩個週期的正弦波(週期為 20) 的動作就是:<br /></p><br /><p><br />X<sub>avg</sub>(0) = X(0)+X(20)<br /></p><br /><p><br />X<sub>avg</sub>(1) = X(1)+X(21)<br /></p><br /><p><br />…<br /></p><br /><p><br />X<sub>avg</sub>(19) = X(19)+X(19+20)<br /></p><br /><p><br />最後 X<sub>avg</sub>(0:19) 就會是平均後的正弦波, 如果以 N 來代表取平均的週期數, 而週期以 T 來帶進去, 那麼我們的運算式子會變成:<br /></p><br /><p><br />X<sub>avg</sub>(i) = ( X(i) + X(i+T) + X(i+2*T) + … + X(i+(N-1)*T) ) / N, i = 0..T-1<br /></p><br /><p><br />上述的訊號還是相當的純淨沒有雜質, 看不出平均的意義, 接下來我們來看加入雜訊之後的樣子, 我們假設雜訊是 WGN(White Gaussian Noise), 意思是這些雜訊的振幅符合 Gaussian 分布, 而雜訊彼此之間沒有關聯, 白色表示頻譜一致分布在頻域上。<br /></p><br /><p><br />我們讓訊雜比是 0 dB, 意思是雜訊跟訊號的功率是一樣的, 訊號加雜訊會如下圖所示, 圖中的 N 代表平均的週期數:<br /><table style="width:auto;"><tr><td><a href="https://picasaweb.google.com/lh/photo/Sg1kGLJy-dueTQfk5T4OP9MTjNZETYmyPJy0liipFm0?feat=embedwebsite"><img src="https://lh3.googleusercontent.com/-mDH1a2f5eK8/UL3MMlyTqQI/AAAAAAAABwA/RIWAnVD52oI/s800/SignalAveragingN_1.jpg" height="400" width="600" /></a></td></tr><tr><td style="font-family:arial,sans-serif; font-size:11px; text-align:right">From <a href="https://picasaweb.google.com/108267210070859251792/SignalAveraging?authuser=0&feat=embedwebsite">SignalAveraging</a></td></tr></table><br /><br />如果我們平均 2 個週期, 看起來還是跟 N=1 時差不多:<br /><table style="width:auto;"><tr><td><a href="https://picasaweb.google.com/lh/photo/TtocOYJ6isxG0nW6jjhcpNMTjNZETYmyPJy0liipFm0?feat=embedwebsite"><img src="https://lh5.googleusercontent.com/-7rzF77P4zO4/UL3MNm5N-oI/AAAAAAAABwM/Gy00-Z_TBdo/s800/SignalAveragingN_2.jpg" height="400" width="600" /></a></td></tr><tr><td style="font-family:arial,sans-serif; font-size:11px; text-align:right">From <a href="https://picasaweb.google.com/108267210070859251792/SignalAveraging?authuser=0&feat=embedwebsite">SignalAveraging</a></td></tr></table><br /><br />如果我們平均 16 個週期, 稍微好一點點了:<br /><table style="width:auto;"><tr><td><a href="https://picasaweb.google.com/lh/photo/8QcO-l0baiBBWKo2jhiH3dMTjNZETYmyPJy0liipFm0?feat=embedwebsite"><img src="https://lh5.googleusercontent.com/-c-nTUaPbjtk/UL3MOkURE4I/AAAAAAAABwU/5Np-5tDghY8/s800/SignalAveragingN_16.jpg" height="400" width="600" /></a></td></tr><tr><td style="font-family:arial,sans-serif; font-size:11px; text-align:right">From <a href="https://picasaweb.google.com/108267210070859251792/SignalAveraging?authuser=0&feat=embedwebsite">SignalAveraging</a></td></tr></table><br /><br />如果我們平均 1024 個週期, 喔, 已經開始有蠻漂亮的訊號形狀了:<br /><table style="width:auto;"><tr><td><a href="https://picasaweb.google.com/lh/photo/aG5XwKjF9nehrFQ-x0noM9MTjNZETYmyPJy0liipFm0?feat=embedwebsite"><img src="https://lh6.googleusercontent.com/-dF81sk_jw4k/UL3MP2XBajI/AAAAAAAABwg/4qC__0i9cts/s800/SignalAveragingN_1024.jpg" height="400" width="600" /></a></td></tr><tr><td style="font-family:arial,sans-serif; font-size:11px; text-align:right">From <a href="https://picasaweb.google.com/108267210070859251792/SignalAveraging?authuser=0&feat=embedwebsite">SignalAveraging</a></td></tr></table><br /><br />如果我們平均 4096 個週期, 哇, 訊號又更明顯了:<br /><table style="width:auto;"><tr><td><a href="https://picasaweb.google.com/lh/photo/hMXcyl3cUfvw8tfUmtxTOtMTjNZETYmyPJy0liipFm0?feat=embedwebsite"><img src="https://lh4.googleusercontent.com/-zngqTzyVvsU/UL3MQ54_aLI/AAAAAAAABwo/seyUCejDzrU/s800/SignalAveragingN_4096.jpg" height="400" width="600" /></a></td></tr><tr><td style="font-family:arial,sans-serif; font-size:11px; text-align:right">From <a href="https://picasaweb.google.com/108267210070859251792/SignalAveraging?authuser=0&feat=embedwebsite">SignalAveraging</a></td></tr></table><br /><br />如果我們平均 65536 個週期, 這個已經幾乎就跟沒有雜訊一樣了, 我們很少有機會能平均這麼多次, 放在這裡是要讓讀者明白平均的威力:<br /><table style="width:auto;"><tr><td><a href="https://picasaweb.google.com/lh/photo/veBqXrfbrp3gmrsd4j6nuNMTjNZETYmyPJy0liipFm0?feat=embedwebsite"><img src="https://lh6.googleusercontent.com/-8SjYVpjlnQM/UL3MSnDapMI/AAAAAAAABw0/SR8VXWUXDqc/s800/SignalAveragingN_65536.jpg" height="400" width="600" /></a></td></tr><tr><td style="font-family:arial,sans-serif; font-size:11px; text-align:right">From <a href="https://picasaweb.google.com/108267210070859251792/SignalAveraging?authuser=0&feat=embedwebsite">SignalAveraging</a></td></tr></table><br /><br />我們把原來的純淨訊號與 N=65536 平均後的訊號放在一起看:<br /><table style="width:auto;"><tr><td><a href="https://picasaweb.google.com/lh/photo/opQQK3WBfNx-nRIKvk1YhdMTjNZETYmyPJy0liipFm0?feat=embedwebsite"><img src="https://lh6.googleusercontent.com/-M4m0HCsurp8/UL3MPKPIu_I/AAAAAAAABwY/fxYjst_0RAA/s800/SignalAveragingNoNoise.jpg" height="400" width="600" /></a></td></tr><tr><td style="font-family:arial,sans-serif; font-size:11px; text-align:right">From <a href="https://picasaweb.google.com/108267210070859251792/SignalAveraging?authuser=0&feat=embedwebsite">SignalAveraging</a></td></tr></table><br /><table style="width:auto;"><tr><td><a href="https://picasaweb.google.com/lh/photo/0JbEk4vHfXD38R7z76WAetMTjNZETYmyPJy0liipFm0?feat=embedwebsite"><img src="https://lh5.googleusercontent.com/-I4R9t2tN9fc/UL3MTQ2udeI/AAAAAAAABw4/wOshtAhEom4/s800/SignalAveragingN_65536_large.jpg" height="400" width="600" /></a></td></tr><tr><td style="font-family:arial,sans-serif; font-size:11px; text-align:right">From <a href="https://picasaweb.google.com/108267210070859251792/SignalAveraging?authuser=0&feat=embedwebsite">SignalAveraging</a></td></tr></table><br /><br />所以從上述幾張圖一路看下來, 很明顯的平均同步訊號能夠讓訊號浮現而雜訊變小, 用訊號處理的術語就是有增益(gain), 那麼我們從平均能夠得到的增益是多少呢?接下來我們來仔細算一下。<br /></p><br /></div><br /><br /></div><br /><br /><div id="outline-container-2" class="outline-2"><br /><h2 id="sec-2">增益</h2><br /><div class="outline-text-2" id="text-2"><br /><br /><p>假設我們想要得到的常數訊號振幅是 A, 而雜訊是 N(n) 那麼我們接收到的訊號 r(n) = A + N(n), 在統計上, 我們可以把 A 當作是這個 distribution 的平均值。雜訊的振幅, 亦即 r(n) 的標準差是 sigma<sub>in。</sub> <br /></p><br /><p><br />在雜訊本身的 distribution 不變的情況下, 取 N 個取樣做平均之後, 其標準差會變成:<br /></p><br /><p><br />sigma<sub>avg</sub> = sigma<sub>in</sub> / sqrt(N), 亦即平均 N 次之後的標準差為原來的標準差除以根號 N。<br /></p><br /><p><br />原來的訊雜比 SNR<sub>in</sub> = A / sigma<sub>in</sub><br /></p><br /><p><br />平均後的訊雜比 SNR<sub>avg</sub> = A / sigma<sub>avg</sub><br /></p><br /><p><br />Gain = SNR<sub>avg</sub> / SNR<sub>in</sub> = sigma<sub>in</sub> / sigma<sub>avg</sub> = sqrt(N)<br /></p><br /><p><br />把增益用分貝表示: Gain = 20*log10(sqrt(N)) = 10*log10(N) dB, 第一個 log10 乘以 20 是因為這是振幅。<br /></p><br /><p><br />把之前的平均次數能夠得到的增益做成表格, 如下所示:<br /></p><table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides"><br /><colgroup><col class="right" /><col class="right" /><br /></colgroup><br /><thead><br /><tr><th scope="col" class="right">N</th><th scope="col" class="right">Gain(dB)</th></tr><br /></thead><br /><tbody><br /><tr><td class="right">1</td><td class="right">0</td></tr><br /><tr><td class="right">2</td><td class="right">3.01</td></tr><br /><tr><td class="right">16</td><td class="right">12.04</td></tr><br /><tr><td class="right">1024</td><td class="right">30.10</td></tr><br /><tr><td class="right">4096</td><td class="right">36.12</td></tr><br /><tr><td class="right">65536</td><td class="right">48.16</td></tr><br /></tbody><br /></table><br /><br /><br /><br /><br /></div><br /><br /></div><br /><br /><div id="outline-container-3" class="outline-2"><br /><h2 id="sec-3">結語</h2><br /><div class="outline-text-2" id="text-3"><br /><br /><p>只要在現實生活中處理訊號, 免不了的就是要處理雜訊, 這是痛苦的地方, 也是這個世界迷人有趣的地方。如何與雜訊共存, 或是把雜訊對我們的影響變小, 是我們每一個要處理訊號的工程師必須要面對的問題。在這篇文章中, 我們了解到了在訊號同步的情況之下, 如何透過同步平均(coherent averaging) 來改善訊雜比, 使我們要得到的訊號「浮出水面」, 以及要作多少次平均可以得到多少增益, 將來各位如果遇到需要處理訊號的時候, 有最基本但也非常有用的工具可以把雜訊消除。<br /></p><br /></div><br /><br /></div><br /><br /><div id="outline-container-4" class="outline-2"><br /><h2 id="sec-4">參考書目</h2><br /><div class="outline-text-2" id="text-4"><br /><br /><p>Sheldon Ross, "A First Course in Probability," 6/e, Prentice-Hall, 2002.<br /></p><br /><p><br />Richard G. Lyons, "Understandding Digital Signal Processing," 3/e, Prentice-Hall, 2011.<br /></p></div><br /></div><br /><br/>-- <br/>Albert Huang <br/>Chun-Chieh Huang(黃俊傑) <br/>Albert Huanghttp://www.blogger.com/profile/09910403631033610841noreply@blogger.com0tag:blogger.com,1999:blog-5393693761509999841.post-40980198477161333992012-12-01T20:51:00.001+08:002012-12-03T13:21:51.648+08:00在 MacOSX 10.8.2 上安裝 GNU Radio 3.6.2 與台幣九百元的軟體無線電硬體rtl-sdr<br />
GNU Radio<sup><a class="footref" href="http://www.blogger.com/blogger.g?blogID=5393693761509999841#fn-.1" name="fnr-.1">1</a></sup> 是一個軟體無線電的自由軟體, 是以 Python 寫成, 在需要執行速度快的元件則改用 C++ 來撰寫。我們可以把 GNU Radio 視為 Python 的訊號處理函式庫。<br />
<br />
軟體無線電不論如何, 還是需要一個硬體來接收訊號, 你可以使用音效輸入接收來自於無線電接收機的音效輸出, 或是直接用一個無線電接收前端設備來接收來自於天線的訊號。Realtek RTL2832U 原本是 Realtek 這家晶片設計公司設計的 DVB(數位電視廣播) 接收機晶片, 他的設計就是前端接收機把類比訊號轉成數位訊號後, 就透過 USB 2.0 的介面傳送進電腦作後續的數位電視廣播解調工作, 可以說是軟體無線電的應用, 經過 hacker 們的努力以及 Realtek 還算友善的服務之後, 於是我們就可以把 Realtek RTL2832U 晶片的數位電視棒<sup><a class="footref" href="http://www.blogger.com/blogger.g?blogID=5393693761509999841#fn-.2" name="fnr-.2">2</a></sup>用在 GNU Radio 的軟體上, 也就是 rtl-sdr<sup><a class="footref" href="http://www.blogger.com/blogger.g?blogID=5393693761509999841#fn-.3" name="fnr-.3">3</a></sup> 這個軟體套件。<br />
<br />
原本在 MacOSX 上面要 build GNU Radio 是困難重重啊, 但是經過 Michael Dickens 的努力之後, 現在在 MacPorts 2.1.2 上面可以非常容易的安裝 GNU Radio, 不過要安裝 rtl-sdr 還是有一點小小的技巧, 筆者就利用這篇文章來紀錄安裝過程並分享給有需要的人。<br />
<br />
<div id="table-of-contents">
<br />
<h2>
Table of Contents</h2>
<br />
<div id="text-table-of-contents">
<br />
<ul><br />
<li><a href="http://www.blogger.com/blogger.g?blogID=5393693761509999841#sec-1">1 要先安裝的 MacPorts 2.1.2 套件</a></li>
<br />
<li><a href="http://www.blogger.com/blogger.g?blogID=5393693761509999841#sec-2">2 Install GNU Radio 3.6.2</a></li>
<br />
<li><a href="http://www.blogger.com/blogger.g?blogID=5393693761509999841#sec-3">3 Install rtl-sdr library</a></li>
</ul>
<br /></div>
<br /></div>
<br />
<div class="outline-2" id="outline-container-1">
<br />
<h2 id="sec-1">
要先安裝的 MacPorts 2.1.2 套件</h2>
<br />
<div class="outline-text-2" id="text-1">
這些套件是要編譯 GNU Radio 所需要先安裝的 MacPorts 2.1.2 的套件, <br />如果你利用 MacPorts 2.1.2 來安裝 gnuradio 的話,<br />這些相依套件會自動被安裝, 筆者把這些套件列出來當作參考:<br />
<br />
<ul><br />
<li>python27</li>
<br />
<li>py27-cheetah</li>
<br />
<li>cmake</li>
<br />
<li>mercurial</li>
<br />
<li>boost</li>
<br />
<li>sdcc</li>
<br />
<li>doxygen</li>
<br />
<li>sphinx</li>
<br />
<li>py27-sphinx</li>
<br />
<li>cppunit</li>
<br />
<li>fftw-3-single</li>
<br />
<li>swig</li>
<br />
<li>gsl-devel</li>
<br />
<li>guile</li>
<br />
<li>ccache</li>
<br />
<li>libusb<br /> libusb-devel is obsoleted by libusb</li>
<br />
<li>py27-numpy</li>
<br />
<li>py27-gtk</li>
<br />
<li>py27-scipy</li>
<br />
<li>py27-lxml</li>
<br />
<li>py27-matplotlib</li>
</ul>
<br />
<br />
<br /></div>
<br />
<br /></div>
<br />
<br />
<div class="outline-2" id="outline-container-2">
<br />
<h2 id="sec-2">
Install GNU Radio 3.6.2</h2>
<br />
<div class="outline-text-2" id="text-2">
<br />
感謝 Michael Dickens <mlk@alum.mit.edu> 的努力, 現在 MacPorts 2.1.2 可以直接安裝 GNU Radio 3.6.2, 也可以直接安裝 GNU Radio 最新的 next branch, 安裝 gnuradio 有一些選項可以選:<br />
<pre class="example">$ port info gnuradio
gnuradio @3.6.2 (science)
Sub-ports: gnuradio-devel, gnuradio-next
Variants: debug, docs, full, grc, jack, orc, portaudio, python26,
python27, qtgui, sdl, swig, uhd, universal, wavelet, wxgui
Description: GNU Radio Software Defined Radio: This port is kept up
with the GNU Radio release, which is typically updated
every few months.
Homepage: http://gnuradio.org/
Build Dependencies: cmake
Library Dependencies: boost, cppunit, fftw-3-single, pkgconfig
Conflicts with: gnuradio-next, gnuradio-devel
Platforms: darwin, macosx
License: GPL-3
Maintainers: michaelld@macports.org, openmaintainer@macports.org</pre>
<br />我安裝的時候下的命令是:<br />
<pre class="example">$ sudo port install gnuradio +docs +grc +orc +python27 +qtgui +sdl +swig +uhd +wxgui</pre>
<br />
<br />安裝成功後, 可以用以下命令檢查:<br />
<pre class="example">$ port installed gnuradio
The following ports are currently installed:
gnuradio @3.6.2_0+docs+grc+orc+python27+qtgui+sdl+swig+uhd+wxgui (active)</pre>
<br />
<br /></div>
<br />
<br /></div>
<div class="outline-2" id="outline-container-3">
<br />
<h2 id="sec-3">
Install rtl-sdr library</h2>
<br />
<div class="outline-text-2" id="text-3">
<br />
<br />Check out rtl-sdr library:<br />
<pre class="example">$ git clone git://git.osmocom.org/rtl-sdr.git</pre>
<br />
<br />Building with cmake:<br />
<pre class="example">$ cd rtl-sdr/
$ mkdir build
$ cd build
$ cmake ../ -DINSTALL_UDEV_RULES=ON
$ make
$ sudo make install</pre>
<br />
<br />Check out gr-osmosdr<br />
<pre class="example">$ git clone git://git.osmocom.org/gr-osmosdr
$ cd gr-osmosdr/
$ mkdir build
$ cd build/
$ cmake -DPYTHON_EXECUTABLE=/opt/local/bin/python -DPYTHON_INCLUDE_DIR=/opt/local/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -DPYTHON_LIBRARY=/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/libpython2.7.dylib -DCMAKE_INSTALL_PREFIX:PATH=/opt/local ../
$ make
$ sudo make install</pre>
<br />
<br />Mac 系統會把 osmosdr 這個 python 的 module 裝到 /opt/local/lib/python2.7/site-packages 裡面, 這會造成執行 gnuradio 的錯誤, 請執行以下的命令把 osmosdr 目錄搬移到 /opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages 裡面:<br />
<pre class="example">$ sudo mv /opt/local/lib/python2.7/site-packages/osmosdr /opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages</pre>
<br />
<br />安裝完後, 大家就可以開始使用 rtl-sdr 來接收無線電訊號了, 理論上 RTL2832U 能夠達到最大的取樣率是 3.2Msps(mega sample per second), 不過每台機器都不一樣, 先來測試一下, 在你的機器上可以達到最大的取樣率是多少:<br />
<pre class="example">$ ./rtl_test -s 2.4e6
Found 1 device(s):
0: Compro Videomate U650F
Using device 0: Compro Videomate U650F
Found Elonics E4000 tuner
Supported gain values (14): -1.0 1.5 4.0 6.5 9.0 11.5 14.0 16.5 19.0 21.5 24.0 29.0 34.0 42.0
Reading samples in async mode...</pre>
<br />
<br />
<br />上面是筆者的 MacBook Pro core i7 能夠達到最大的取樣率 2.4Msps, 測試的方法就是從 3.2e6 不斷的往下調, 直到沒有 lost bytes 為止, 那就是在你的機器上能夠達到的最大取樣率。<br />
<br />
<br />另外, 每一個 RTL2832U 的 DVB dongle 都有不一樣的 tuner, 可以用以下的命令來看你能夠調整頻率的範圍:<br />
<pre class="example">$ ./rtl_test -t</pre>
<br />
<br />
<br />筆者的機器上的結果是:<br />
<pre class="example">$ rtl_test -t
Found 1 device(s):
0: Compro Videomate U650F
Using device 0: Compro Videomate U650F
Found Elonics E4000 tuner
Supported gain values (14): -1.0 1.5 4.0 6.5 9.0 11.5 14.0 16.5 19.0 21.5 24.0 29.0 34.0 42.0
Benchmarking E4000 PLL...
[E4K] PLL not locked for 52000000 Hz!
[E4K] PLL not locked for 2203000000 Hz!
[E4K] PLL not locked for 1102000000 Hz!
[E4K] PLL not locked for 1248000000 Hz!
E4K range: 53 to 2202 MHz
E4K L-band gap: 1102 to 1248 MHz</pre>
<br />
<br />
<br />
<br />接下來就可以利用這個來接收訊號了, 可以把取樣到的訊號存在檔案, 或是利用 GNU Radio 來接收, 這個例子可以把中心頻率調到 392 MHz, 並以取樣率 1.8 Msps 抓取訊號並存在 /tmp/capture.bin 這個檔案中。<br />
<pre class="example">$ ./rtl_sdr /tmp/capture.bin -s 1.8e6 -f 392e6</pre>
<br />
<br />如果要利用存下來的檔案, 可以用<a href="http://thread.gmane.org/gmane.linux.drivers.video-input-infrastructure/44461/focus=44525"> 這篇文章</a> 提到的 FM 解調器(rtl2832-fm.grc) 來解開來。當然, 你要先能夠把中心頻率調到正確的位置上, 還要有清晰的 FM 訊號。<br />
<br />
<br />至此, 如果你的設備跟筆者的一樣, 就擁有了只花台幣九百元的軟體無線電, 可以調整的頻率範圍是 53 到 2202 MHz (1102 到 1248 MHz 不可用), 最大取樣率是 2.4 Msps 的 I/Q 訊號, 所以可處理的頻寬是 2.4 MHz, 接下來, 要怎麼做, 要接收什麼, 那就是個人的功夫啦, 在此祝各位玩軟體無線電愉快!<br />
<br />
<div id="footnotes">
<br />
<h2 class="footnotes">
Footnotes: </h2>
<br />
<div id="text-footnotes">
<br />
<div class="footnote">
<sup><a class="footnum" href="http://www.blogger.com/blogger.g?blogID=5393693761509999841#fnr-.1" name="fn-.1">1</a></sup> GNU Radio 網站(英文): <a href="http://gnuradio.org/redmine/projects/gnuradio/wiki">http://gnuradio.org/redmine/projects/gnuradio/wiki</a></div>
<br />
<br />
<div class="footnote">
<sup><a class="footnum" href="http://www.blogger.com/blogger.g?blogID=5393693761509999841#fnr-.2" name="fn-.2">2</a></sup> 筆者購買的數位電視棒是康博啟示錄 Compro U650, 在 rtl-sdr 網站所描述的 Compro Videomate U650F 與 U650 應是同一產品。</div>
<br />
<br />
<div class="footnote">
<sup><a class="footnum" href="http://www.blogger.com/blogger.g?blogID=5393693761509999841#fnr-.3" name="fn-.3">3</a></sup> rtl-sdr 完整安裝過程與文件(英文): <a href="http://sdr.osmocom.org/trac/wiki/rtl-sdr">http://sdr.osmocom.org/trac/wiki/rtl-sdr</a></div>
</div>
<br /></div>
<br />
<br /></div>
<br /></div>
<br />
<br />
-- <br />
Albert Huang <br />
Chun-Chieh Huang(黃俊傑) Albert Huanghttp://www.blogger.com/profile/09910403631033610841noreply@blogger.com1tag:blogger.com,1999:blog-5393693761509999841.post-10450788066047083302012-11-06T19:57:00.000+08:002012-11-21T12:44:45.653+08:00如何用星座圖偵錯數位通訊系統<p>人類天生就是視覺與聽覺的動物, 而抽象思考能力是比較晚才發展起來的, 因此不同工程的偵錯技巧都類似, 最好使用視覺或聽覺來輔助, 才能做最有效率的偵錯。上次講「<a href="http://alberthuang314.blogspot.tw/2012/11/soc-debug.html">在 SoC debug 的藝術</a>」時筆者並沒有提到這個非常重要的偵錯技巧: <b>視覺化</b>! 通訊系統偵錯如果用視覺化來輔助, 可以大幅提升工作效率, 我們今天就來談談通訊系統視覺化偵錯技巧。<sup><a class="footref" name="fnr.1" href="#fn.1">1</a></sup></p><p>首先來看什麼是星座圖。天文學上的星座圖是一組一組的星星合起來看的, 在通訊系統裡面, 星座圖就是在頻域上看解調出來的 symbol 值, 繪製在一個平面上, 將所有出現的 symbol 值同時繪製在上面的時候, 看起來就像是天文學上的星座圖, 所以就有了這個名字。不過我們並沒有把一個點稱之為星星。:-)</p><a name='more'></a><p>為什麼我們能夠把真實傳輸的訊號看作是星座圖上的一點?這牽涉到 signal space 的證明, 在這裡我們就不詳細證明了, 有興趣的可以翻閱數位通訊系統的書, 有兩本數位通訊對於 signal space 有比較詳細的證明。<sup><a class="footref" name="fnr.2" href="#fn.2">2</a></sup></p><p>筆者打從一開始從事通訊產業就開始使用星座圖來偵錯通訊系統, 深深的為這樣的偵錯技巧著迷, 最近看到一本書<sup><a class="footref" name="fnr.3" href="#fn.3">3</a></sup>有詳盡的介紹這個偵錯技巧, 接下來我們就來看在星座圖上能夠看到通訊系統什麼樣的問題。全部的圖例都是以 16 QAM 為例子。</p><div id="outline-container-1" class="outline-2"><h1 id="sec-1">Carrier Recovery Loop Phase Offset </h1><div class="outline-text-2" id="text-1"><p><table style="width:auto;"><tr><td><a href="https://picasaweb.google.com/lh/photo/J-jhvw-RH9NRyclwzCsGadMTjNZETYmyPJy0liipFm0?feat=embedwebsite"><img src="https://lh3.googleusercontent.com/-LKsSXpqkZ78/UJjjv-AfNRI/AAAAAAAABsw/DvGgenRnrKg/s640/PhaseErr.jpg" height="360" width="480" /></a></td></tr><tr><td style="font-family:arial,sans-serif; font-size:11px; text-align:right">From <a href="https://picasaweb.google.com/108267210070859251792/Constellations?authuser=0&feat=embedwebsite">Constellations</a></td></tr></table>上圖可以看到 16 QAM 的星座點以原點為圓心, 逆時針旋轉了 8 度, 是由於 carrier recovery loop 裡面殘留的相位差所致。</p></div></div><div id="outline-container-2" class="outline-2"><h1 id="sec-2">Carrier Recovery Loop Unlocked </h1><div class="outline-text-2" id="text-2"><table style="width:auto;"><tr><td><a href="https://picasaweb.google.com/lh/photo/Kbh73Y7d3ZWZYpxDGICHPNMTjNZETYmyPJy0liipFm0?feat=embedwebsite"><img src="https://lh6.googleusercontent.com/-I84DSeYGNPw/UJjjxpY_DGI/AAAAAAAABs8/xd6ack7oDo0/s640/Unlock.jpg" height="360" width="480" /></a></td></tr><tr><td style="font-family:arial,sans-serif; font-size:11px; text-align:right">From <a href="https://picasaweb.google.com/108267210070859251792/Constellations?authuser=0&feat=embedwebsite">Constellations</a></td></tr></table><p>上圖可以看到 16 QAM 的星座點隨著時間旋轉, 這是由於 carrier recovery loop 完全沒有鎖到對方發射器的相位。通常脫鎖的話, 旋轉方向是一樣的, 也就是說你的鎖相迴路頻率比對方發射機快或是慢, 如果是一下往順時針, 然後很快就往逆時針(或是相反情況), 而且一去不回頭, 那也是脫鎖, 這有可能是一開始雙方頻率差異過大, 超過鎖相迴路能夠處理的頻寬。</p></div></div><div id="outline-container-3" class="outline-2"><h1 id="sec-3">Poor Phase Noise </h1><div class="outline-text-2" id="text-3"><p><table style="width:auto;"><tr><td><a href="https://picasaweb.google.com/lh/photo/jxY6VoWBhJlPthIAl5R0KdMTjNZETYmyPJy0liipFm0?feat=embedwebsite"><img src="https://lh6.googleusercontent.com/-BeFQ2-JMZxA/UJjjzaTcgkI/AAAAAAAABtI/0WsAaHIczgQ/s640/PhaseNoise.jpg" height="360" width="480" /></a></td></tr><tr><td style="font-family:arial,sans-serif; font-size:11px; text-align:right">From <a href="https://picasaweb.google.com/108267210070859251792/Constellations?authuser=0&feat=embedwebsite">Constellations</a></td></tr></table>上圖可以看到星座點以原點為圓心, 以正負平均 3 度的差異旋轉, 這是由於鎖相迴路的相位雜訊過大而來。正負平均(rms) 三度就可以在星座點造成這樣明顯的軌跡了。</p></div></div><div id="outline-container-4" class="outline-2"><h1 id="sec-4">Coherent Carrier Interference(同步載波干擾) </h1><div class="outline-text-2" id="text-4"><p><table style="width:auto;"><tr><td><a href="https://picasaweb.google.com/lh/photo/rXdlCmrZRdQs8LJBJ5Xr-dMTjNZETYmyPJy0liipFm0?feat=embedwebsite"><img src="https://lh5.googleusercontent.com/-QqBFnH2uKZs/UJjjynAusXI/AAAAAAAABtA/b0Hskq8jtIo/s640/CoherentCarrierInterference.jpg" height="360" width="480" /></a></td></tr><tr><td style="font-family:arial,sans-serif; font-size:11px; text-align:right">From <a href="https://picasaweb.google.com/108267210070859251792/Constellations?authuser=0&feat=embedwebsite">Constellations</a></td></tr></table>上圖是 16 QAM 的星座點受到跟接收機同步的另一個載波干擾所產生的, 受到干擾的點圍繞著理想的星座點旋轉。同步載波干擾會導致錯誤率的增加, 因為相鄰兩個星座點的距離被縮小了。</p></div></div><div id="outline-container-5" class="outline-2"><h1 id="sec-5">Multipath </h1><div class="outline-text-2" id="text-5"><p><table style="width:auto;"><tr><td><a href="https://picasaweb.google.com/lh/photo/R2_h9av7sPkjI-2tiE2B1NMTjNZETYmyPJy0liipFm0?feat=embedwebsite"><img src="https://lh3.googleusercontent.com/-D92ILTtojoI/UJjj11D7b7I/AAAAAAAABtY/Z_9F3K6COdc/s640/Multipath.jpg" height="360" width="480" /></a></td></tr><tr><td style="font-family:arial,sans-serif; font-size:11px; text-align:right">From <a href="https://picasaweb.google.com/108267210070859251792/Constellations?authuser=0&feat=embedwebsite">Constellations</a></td></tr></table>上圖可以看到在多重路徑干擾下的 16 QAM 星座點。多重路徑干擾是由於對方發射機的訊號被衰減並延遲, 而接收機收到兩組或兩組以上的訊號所致。解調器會收到並且鎖住比較大的訊號, 但是在星座點上會顯示另一組衰減的星座點。在每一個理想的星座點上都可以看到完整的縮小版 16 QAM 星座點, 由於延遲的關係旋轉某一個角度。上圖的多重路徑訊號是原來訊號傳輸功率的十分之一。</p></div></div><div id="outline-container-6" class="outline-2"><h1 id="sec-6">IQ Phase Imbalance(IQ 相位不平衡) </h1><div class="outline-text-2" id="text-6"><p><table style="width:auto;"><tr><td><a href="https://picasaweb.google.com/lh/photo/Eptwz2pN6puRWyBcXon0SdMTjNZETYmyPJy0liipFm0?feat=embedwebsite"><img src="https://lh5.googleusercontent.com/-hdUbzaedq0o/UJjj0QGXebI/AAAAAAAABtQ/B_I8yge6S9U/s640/IQPhaseImbalance.jpg" height="360" width="480" /></a></td></tr><tr><td style="font-family:arial,sans-serif; font-size:11px; text-align:right">From <a href="https://picasaweb.google.com/108267210070859251792/Constellations?authuser=0&feat=embedwebsite">Constellations</a></td></tr></table>IQ 相位不平衡(IQ Phase Imbalance) 是由於調變器或解調器的功能出問題, 當訊號區分 I 跟 Q 頻道的時候, 兩組線路的相位差異不是正好 90 度。上圖的 IQ 頻道相位差為 10 度。</p></div></div><div id="outline-container-7" class="outline-2"><h1 id="sec-7">IQ Amplitude Imbalance(IQ 振幅不平衡) </h1><div class="outline-text-2" id="text-7"><p><table style="width:auto;"><tr><td><a href="https://picasaweb.google.com/lh/photo/CQyAUNCzowBrX4nE_hbVStMTjNZETYmyPJy0liipFm0?feat=embedwebsite"><img src="https://lh5.googleusercontent.com/-CxaLy0dOy5E/UJjj3EeES6I/AAAAAAAABtg/Rm0XptYZOZ4/s640/IQAmpImbalance.jpg" height="360" width="480" /></a></td></tr><tr><td style="font-family:arial,sans-serif; font-size:11px; text-align:right">From <a href="https://picasaweb.google.com/108267210070859251792/Constellations?authuser=0&feat=embedwebsite">Constellations</a></td></tr></table>IQ 振幅不平衡(IQ Amplitude Imbalance) 也是調變器或解調器線路問題, 當訊號區分 I 與 Q 頻道後, 兩者的增益不一樣, 就會導致 IQ 振幅不平衡。</p></div></div><div id="outline-container-8" class="outline-2"><h1 id="sec-8">Gain Compression(增益壓縮) </h1><div class="outline-text-2" id="text-8"><p><table style="width:auto;"><tr><td><a href="https://picasaweb.google.com/lh/photo/DgnTIotNvGId0jHKdFlyhdMTjNZETYmyPJy0liipFm0?feat=embedwebsite"><img src="https://lh5.googleusercontent.com/-TcwQwauyKPI/UJjj4HSM0cI/AAAAAAAABto/oY_pOHfT_po/s640/GainCompression.jpg" height="360" width="480" /></a></td></tr><tr><td style="font-family:arial,sans-serif; font-size:11px; text-align:right">From <a href="https://picasaweb.google.com/108267210070859251792/Constellations?authuser=0&feat=embedwebsite">Constellations</a></td></tr></table>外圈星座點相對於內圈有比較高的瞬時功率, 如果系統上有增益壓縮的問題, 外圈的星座點會被拉往內圈, 而內圈的星座點會被稍稍從理想星座點位置拉離圓心。</p><p>這個問題也會導致解調的錯誤率增加, 因為星座點之間的距離縮短了。</p></div></div><div id="outline-container-9" class="outline-2"><h1 id="sec-9">Improper Amounts of Gain </h1><div class="outline-text-2" id="text-9"><p><table style="width:auto;"><tr><td><a href="https://picasaweb.google.com/lh/photo/M2eKzGmOlNTI1up-x25ZStMTjNZETYmyPJy0liipFm0?feat=embedwebsite"><img src="https://lh3.googleusercontent.com/-2M5TGUEht-U/UJjj5BrWitI/AAAAAAAABt0/K3NpCdxV5x8/s640/GainTooHigh.jpg" height="360" width="480" /></a></td></tr><tr><td style="font-family:arial,sans-serif; font-size:11px; text-align:right">From <a href="https://picasaweb.google.com/108267210070859251792/Constellations?authuser=0&feat=embedwebsite">Constellations</a></td></tr></table>上圖所顯示的是增益太大, 使得 16 QAM 星座點往外長。</p><p><table style="width:auto;"><tr><td><a href="https://picasaweb.google.com/lh/photo/p0swwUkFXlEzDIdL6IUT89MTjNZETYmyPJy0liipFm0?feat=embedwebsite"><img src="https://lh4.googleusercontent.com/-sagXBmsF0iQ/UJjj7OK_oXI/AAAAAAAABuA/-NU5JmcmRzE/s640/GainTooLow.jpg" height="360" width="480" /></a></td></tr><tr><td style="font-family:arial,sans-serif; font-size:11px; text-align:right">From <a href="https://picasaweb.google.com/108267210070859251792/Constellations?authuser=0&feat=embedwebsite">Constellations</a></td></tr></table>上圖所顯示的是增益太小, 使得 16 QAM 星座點往內縮。</p></div></div><div id="outline-container-10" class="outline-2"><h1 id="sec-10">Amplitude Variation beyond Automatic Gain Control Bandwidth </h1><div class="outline-text-2" id="text-10"><p><table style="width:auto;"><tr><td><a href="https://picasaweb.google.com/lh/photo/AFbikB6Y8_FnUnssz7QTitMTjNZETYmyPJy0liipFm0?feat=embedwebsite"><img src="https://lh5.googleusercontent.com/-XZ7nvmIAc_Y/UJjj6MPo4VI/AAAAAAAABt8/tkeqmmP1asE/s640/AmpVar.jpg" height="360" width="480" /></a></td></tr><tr><td style="font-family:arial,sans-serif; font-size:11px; text-align:right">From <a href="https://picasaweb.google.com/108267210070859251792/Constellations?authuser=0&feat=embedwebsite">Constellations</a></td></tr></table>上圖可以看出來, 每一個星座點都有振幅變化, 這是由於接收機的自動增益控制趕不上訊號的振幅變化, 無法將振幅變化消除。上圖的星座點都是沿著圓心作直線變化, 表示接收機的鎖相迴路鎖得很精準。</p></div></div><div id="outline-container-11" class="outline-2"><h1 id="sec-11">結語 </h1><div class="outline-text-2" id="text-11"><p>今天介紹了如何用視覺化的方式, 透過對星座點的觀察, 偵錯數位通訊系統, 這是筆者一直以來覺得非常有效率與威力的偵錯方式。在這篇文章中介紹了通訊系統會在星座點出現的現象, 但平面的文章沒辦法表現的是人類對於視覺的快速反應, 在面對 symbol rate 很快的系統, 仍然能夠很快速的反應, 讓我們很容易能夠抓出也許只有一兩個 symbol 的瞬間錯誤。在很多數位通訊儀器上面, 也都內建這種偵錯的方式, 可以好好利用。</p></div></div><div id="footnotes"><h2 class="footnotes">Footnotes: </h2><div id="text-footnotes"><p class="footnote"><sup><a class="footnum" name="fn.1" href="#fnr.1">1</a></sup> 除了視覺化偵錯之外, 如果許可的話也可以利用聽覺, 比如說在偵錯語音頻帶數據機、業餘無線電數據機的時候, 因為頻寬在聲音頻寬內(小於 20 kHz), 所以很適合用聲音來偵錯。這樣你就知道為什麼以前的電話撥接數據機在剛開始連線的時候會開啟喇叭讓你聽到一連串的高低音了吧。</p><p class="footnote"><sup><a class="footnum" name="fn.2" href="#fnr.2">2</a></sup> Wozencraft, John M., and Jacobs, Irwin Mark, "Principles of Communication Engineering," John Wiley & Sons, 1965.<br />
<br />
Gallager, Robert G., "Principles of Digital Communication," Cambridge University Press, 2008. 可以由 <a href="http://goo.gl/glkdQ">http://goo.gl/glkdQ</a> 下載。</p><p class="footnote"><sup><a class="footnum" name="fn.3" href="#fnr.3">3</a></sup> McClaning, Kevin, "Wireless Receiver Design for Digital Communications, " 2/ed, SciTech Publishing Inc., 2012.</p></div></div><br />
-- <br />
Albert Huanghttp://www.blogger.com/profile/15756607906352002721noreply@blogger.com0tag:blogger.com,1999:blog-5393693761509999841.post-88046849065853974412012-11-06T12:44:00.000+08:002012-11-21T12:44:03.075+08:00阿姆斯壯之死
<p>第一個登陸月球的那個阿姆斯壯(全名是 Neil Armstrong) 逝世於 2012 年 8 月 25 日。他的身軀是死了, 但是他的精神(spirit) 卻永遠與我們同在, 我們永遠會記得他登陸月球時講過的話:「這是一個人的一小步,卻是全人類的一大步」。而另一個阿姆斯壯, Lance Armstrong, 在單車環法賽奪得了七次冠軍的那個阿姆斯壯, 他還活著。
</p>
<p>
一個單車選手要能夠奪得單車環法賽冠軍就已經很不容易了, 而 Lance Armstrong 不但奪得七次單車環法賽冠軍, 而且還是在他罹患癌症並且痊癒之後奪得, 這樣的故事可以激勵多少人心, 鼓勵多少人向上, 也因此, 他出了一本書, 書名是 "It's Not About The Bike: My Journey Back To Life" 多年前我開始騎單車的時候, 買了一本。
</p>
<p>
運動選手之所以常常是被人們所崇敬的對象, 正是因為他們秉持運動家精神, 即便目標是多麼艱難, 從不輕言放棄, 也不用不公平的方式贏得比賽。筆者還記得有一年環法賽, Lance Armstrong 長年的冠軍競爭對手, 來自德國的 Jan Ulrich 被撞倒在地上, Lance Armstrong 並沒有利用這個機會趕緊大幅超前, 而是在 Ulrich 的附近等待他再度上路之後, 才一起出發。這一幕被多少媒體與網路文章傳頌, 至今仍讓人津津樂道。這正是運動家精神表現的極致: 堅持與對手公平競爭。
</p>
<p>
Lance Armstrong 曾經罹患癌症, 但他並未放棄他熱愛的單車運動, 反而在痊癒後, 不放棄自己的訓練計畫, 也不管癌症治療後身體是多麼的虛弱, 他還是堅持奮戰不懈, 積極的訓練, 終能在 2005 年獲得第七次環法賽冠軍, 並且宣布退休。這也是運動家永遠不放棄的精神。
</p>
<p>
因為上述兩項運動家精神極致的表現, Lance Armstrong 是現任的 Apple 執行長 Tim Cook 常常掛在嘴邊的效法對象, 如果時光就停留在 2005 年的話, 一切看起來是那麼的完美: Lance Armstrong, 一個罹患癌症之後仍然奮戰不懈的鬥士, 一個贏得七次單車環法賽冠軍的英雄, 一個堅持與對手公平競爭的謙謙君子, 他的運動家精神放眼當今這個世界, 沒有幾個人能夠與他匹敵。
</p>
<p>
今年七月美國反禁藥協會(United States Anti-Doping Agency, or USADA) 以 2009 至 2010 年的血液樣本以及 Lance Armstrong 在美國郵政車隊的前隊友的證詞, 指控 Lance Armstrong 使用禁藥以提升運動表現, 並要求撤銷其七次單車環法賽的冠軍頭銜。而 Lance Armstrong 在八月底正式放棄任何上訴, 也意味著他默認了他使用禁藥的指控。
</p>
<p>
此刻, Lance Armstrong 的書很諷刺的躺在我的書架上, 還沒有機會被我閱讀, 就已經充滿了汙穢。登陸月球的阿姆斯壯, 身軀是死了, 精神卻與我們同在; 而單車英雄阿姆斯壯, 還非常健康, 精神卻已經死了。
</p>
<br/>-- <br/>Albert Huanghttp://www.blogger.com/profile/15756607906352002721noreply@blogger.com0tag:blogger.com,1999:blog-5393693761509999841.post-58822176159417255802012-11-04T21:49:00.001+08:002012-11-21T12:45:05.604+08:00台鐵老舊車廂警報器
<p>週日要從新竹到台北, 一時興起改搭台鐵莒光號, 當天旅客人數不少, 座位坐滿之餘走道仍有一些旅客站立。車行至楊梅一帶, 突然第七車廂廁所有人誤觸警報器, 一時間鈴聲大作, 許久都沒有人來關掉警報器, 至少十分鐘之後, 車廂有一名旅客及筆者在互相不知道的情況下先後依照警報器旁邊的告示指示, 走去第一車的車長室通知車長來處理, 在旅客人數不少的情況下, 筆者從七車走到三車時便遇到迎面而來已經被通知的列車長。列車長表示由於是老舊車廂, 警報器沒有辦法連線到車長室, 只能由旅客主動通知列車長來處理。這要是真有緊急事件, 這麼一來一回, 恐怕會失掉處理機會吧?再者, 只要車廂門關起來, 相鄰的車廂是聽不到警報器聲音的, 真的發生事情而該車廂又剛好沒有其他人, 那麼恐怕會產生莫大的遺憾。
</p>
<p>
台鐵目前積極購置全新車組淘汰舊有車廂, 但是以目前淘汰的速度來看, 舊有車廂恐怕要再用上好幾年, 在這些老舊車廂淘汰之前, 難道就只能放任這種規劃不良的警報系統繼續使用嗎? 筆者在接下來的旅程便發揮了工程師愛解決問題的毛病, 開始思考這個問題。筆者認為其實可以用低廉的價格便可以將這些警報器全部升級成為可以通報車長室的現代化連線警報器。
</p>
<p>
空話不多說, 來發想解決方案吧。
</p>
<p>
首先就是如何連線? 根據列車長所言, 看來是牽電纜有窒礙難行之處, 那麼想當然爾, 就來用無線的方式吧!但是無線的方式如何是成本最低廉的呢?台鐵列車之間的無線電通訊早已進入全面數位化的時代, 使用的是 TETRA 的數位中繼無線電系統, 原有的類比式(應該是 FM 調頻式無線電)的機器以及頻率都沒有在使用。筆者想到的其實就是使用這些頻率, 用 AFSK 1200bps<sup><a class="footref" name="fnr.1" href="#fn.1">1</a></sup> 的傳輸方式, 每一節車廂廁所警報器都配上一台 modem, 或是我們一般稱之為 TNC(Terminal Node Controller) 的無線電數據機, 每一節車廂都配上一台。當警報器響的時候, 就開始每隔一段時間傳送一個封包, 裡面包含了列車號碼、車廂號碼與警報器的型態(也許將來要擴充傳送其他訊息)等資訊, 業餘無線電裡有一個通訊協定是 AX.25, 這個通訊協定會把 TNC 收到的封包, 再廣播出去, 當然會用某種機制避免封包氾濫。如此, 每一個車廂的數據機都會幫上一個車廂的數據機的封包傳送出去, 讓下一個車廂的數據機收到, 如此層層轉送, 很快就可以送到列車長室。這樣的系統成本非常低廉, 甚至有可能利用原有以淘汰的無線電對講設備來使用, 在這些車廂淘汰之前, 至少讓旅客覺得台鐵有可靠且安全的服務。
</p>
<div id="footnotes">
<h2 class="footnotes">Footnotes: </h2>
<div id="text-footnotes">
<p class="footnote"><sup><a class="footnum" name="fn.1" href="#fnr.1">1</a></sup> AFSK 是一種用兩種頻率的聲音來代表 0 與 1 的調變方式, 只要用接上對講機使用聲音發射即可, 構造簡單成本極低, 在 VHF/UHF 可以達到 1200 bps 以上的速度。
</p>
</div>
</div>
<br/>-- <br/>Albert Huanghttp://www.blogger.com/profile/15756607906352002721noreply@blogger.com0tag:blogger.com,1999:blog-5393693761509999841.post-74840345294759089342012-11-02T15:15:00.000+08:002012-11-21T12:45:39.984+08:00在 SoC debug 的藝術
<p>今天要談一下, 在 SoC(System-on-Chip) debug 的藝術, 首先我先界定一下何謂 SoC, Wikipedia 對於 "System on a chip" 的解釋是 "A system on a chip or system on chip (SoC or SOC) is an integrated circuit (IC) that integrates all components of a computer or other electronic system into a single chip." 對於在 SoC 上面寫程式與 debug, 我認為最大的特點是:
</p><ul>
<li>
任何地方都有可能會錯
</li>
</ul>
<p>
讀者可能會想, 我在任何地方寫程式的特性也是這樣啊, 但是 SoC 還有一個很致命的缺點, 即便是處理器已經驗證過, 都仍然有可能會發生指令集的錯誤, 尤其是組合語言程式設計師每個人的寫法都不一樣, 很有可能會踩到之前沒有驗證過的指令集組合而發生錯誤!
</p>
<p>
是的, 在 SoC 上寫程式, 驗證工具不管做得再好, 都只是減少錯誤發生的機率而已, 實際上遇到的問題, 還是要有這樣的心態來面對會比較正確。因為在一般的情況下, 我們會把 CPU/DSP 當做已經驗證沒有問題來寫程式, 但是在 SoC 上面, CPU/DSP 非常有可能會因為在新的設計上, 某個或某些組合的 CPU/DSP instruction 在某一級 pipeline 發生問題, 而導致錯誤的結果。即便是大廠如 AMD, 經過了很多的驗證程序之後, 還是有可能出現問題, 如: <a href="http://it.slashdot.org/story/12/03/06/0136243/amd-confirms-cpu-bug-found-by-dragonfly-bsds-matt-dillon">AMD processor incorrectly updates the stack pointer</a>
</p>
<p>
在這樣的 SoC 上面寫程式與 debug, 需要有一些藝術與技巧, 筆者就來分享一下我的經驗。筆者分享的是筆者在通訊 SoC 晶片上發展的經驗, 但我想很多部分都可以類推到其他系統晶片上。一般說來, 在這樣的 SoC 上面會出現的錯誤來源有幾個:
</p><ul>
<li>
自己的程式
</li>
<li>
CPU/DSP instruction 的邏輯錯誤
</li>
<li>
CPU/DSP instruction 的時序錯誤
</li>
<li>
IC 硬體區塊的錯誤
</li>
<li>
IC 內部 Bus 傳輸錯誤
</li>
<li>
IC 與 IC 之間外部 Bus 傳輸錯誤
</li>
<li>
別家晶片上對於通訊訊號或協定上的錯誤
</li>
</ul>
<p>
由於通訊基頻系統大部分都含有一顆或多顆 DSP 負責基頻訊號處理, 所以 DSP programmer 常常身負驗證各個 functional block 的責任, 或是在使用的過程中由奇特的現象來發現驗證團隊之前沒有發現到的錯誤。不管錯誤來源有多少, 解錯誤的首要, 就是先把整個系統以及演算法的原理搞清楚, 清楚之後, 就要依據錯誤出現的現象, 猜測問題出現的點, 然後設計實驗來確認錯誤發生的地方。猜測問題發生的點, 依靠的是對於這個系統的直覺, 而這個直覺是透過你對系統的了解與經驗累積而來的。另外, 就是需要重建錯誤發生時所發生的事情。如果有 simulator 可以使用, 那麼常常在 simulator 上就可以觀察到錯誤的前後發生的事情, 但是像是通訊訊號或協定上的錯誤, 則常常需要有時序上的事件紀錄來重建錯誤發生當時的原貌, 或是有時候沒有現成的分析工具, 就要自己寫一些程式來記錄與觀察變數的變化與事件的流程; 而選擇觀察的物件, 也反映了你對於系統的了解程度。
</p>
<p>
第一個就是要確定自己的程式沒有問題, 程式可能出錯的來源有兩種: 一種是程式設計師自己寫錯, 另一個是 CPU/DSP instructions 出錯導致程式有錯。前者有很多的程式設計相關書籍都有提到如何避免, 以筆者的經驗, 在寫任何 DSP 程式, 特別是組合語言之前, 一定要先想好怎麼測試自己所寫的程式, 以及怎麼樣算是測試成功及失敗。這部分的觀念, 筆者後來發現軟體業界早已經講了很多, 讀者有興趣的話可以參考 TDD(Test Driven Development) 的觀念。TDD 的導入也能夠幫助我們找到第二、三個 CPU/DSP 指令集上的錯誤。
</p>
<p>
程式出錯另一個來源就是 CPU/DSP 指令集上的錯誤, 可以略分成兩種: 一種是指令集邏輯上的錯誤, 另一種是指令集時序上的錯誤。一般來說如果 CPU/DSP 有 test pattern 的話, 前者邏輯上的錯誤應該都已經抓完, 剩下的時序上的錯誤, 也就是指令前後組合的問題, 由於樣本數太大, 一般都只能隨機測試, 所以後者時序上的錯誤是 DSP programmer 比較容易遇到的地雷。如果 DSP programmer 是用組合語言撰寫程式, 而不是 C 語言, 那麼踩到地雷的機會更大。如果有編譯器的話, 通常編譯器就可以當作是一個測試的程式, 可以抓到某些編譯器 codegen 愛用的組合語言時序組合的 bug, 但是組合語言程式設計師每個人愛用的組合語言寫法都不同, 就很容易在某個人的寫法上就踩到地雷。而時序上的錯誤其實也是比較難抓的問題, 通常只能依靠 DSP programmer 在使用上的時候, 發現某些奇特的現象, 把搜尋範圍縮小之後才能夠找到。上一節講的 TDD 就能夠幫助 programmer 找到那些奇特的現象在哪裡。另外, 一般來說, 通訊 SoC 的計畫時程短則三年, 長則五年以上, 要求把整本 DSP 架構讀得滾瓜爛熟不也是很合理的嗎? 對於 CPU/DSP 架構的熟悉程度, 也會幫助你可以很快的找到指令時序上的錯誤。
</p>
<p>
前三項都確定沒問題之後, 接下來要排除的錯誤才是困難的開始, 在此, 筆者建議大家一定要維持寫實驗記錄或是工作記錄的習慣, 筆者常常遇到一解就是一兩週的 bug, 常常解到後來需要與一兩週之前的結果一起比較才能判斷錯誤在哪裡, 因此工作記錄非常重要, 而且有了工作記錄之後, 每天回家才不會心裡一直掛念這件事。要排除這邊的錯誤, 通常是已經有一個錯誤發生了, 這個錯誤也許要做很多次才能重複, 但是一定要確定如何能夠重複這個錯誤, 這點很重要, 因為接下來你會需要一直讓這個錯誤發生才能夠 debug. 讓錯誤發生是一個「點」, 要找出錯誤發生真正的原因(root cause), 常常需要其他的「點」, 讓你連成數條線才能夠把搜尋範圍變小找到真正發生的原因。
</p>
<p>
找 root cause 的過程, 我個人覺得就像是 binary search 一樣, 不斷的找一個點做判斷, 決定要往左跑, 還是往右跑。當然, 有的時候還是會判斷錯誤, 跑錯方向, 所以就要回溯到當初的切割點, 知道當時的實驗資料是什麼, 為什麼做這樣的判斷, 才能對整個問題有更全面性的了解。這時候仰賴的還是當初的實驗記錄, 所以實驗記錄很重要吧!
</p>
<p>
除了解單一錯誤以外, 有的時候會需要解多重錯誤。筆者碰觸到的大部分是通訊或訊號處理的問題, 穩定度很重要, 多重錯誤常常會表現在穩定度上, 所以我們常常要記錄錯誤率, 才能知道自己是否已經解完所有的錯誤, 或是剛剛解掉的那個錯誤是否佔的比例最大。另外, 我覺得在這樣的系統上 debug, 還要「大膽的假設,小心的求證」, 有的時候, 我們需要處理的是通訊 physical layer 或是 protocol layer 的問題, 需要猜測對方怎麼做, 這時候就需要大膽的假設, 然後小心的求證。有的時候, 錯誤的可能是另一家公司的晶片, 因此「大膽的假設,小心的求證」是必要的。在這個情況下, 考驗的就是你對整個通訊系統以及原理的掌握程度了。另外, 晶片內部的錯誤, 也是需要「大膽的假設,小心的求證」, 因為這時候, 能夠觀察的工具變少了, 有時候需要猜測。還有, 對已知事物的掌握程度, 也會影響到猜測的精準度, 比如說各個硬體的規格, 使用到的演算法的原理, 通訊 physical layer or protocl layer 的原理, 通訊系統的規格, CPU/DSP instruction set, 等等, 都能夠提昇猜測的效率。對已知事物掌握程度高, 才能夠專心的面對未知的事物。
</p>
<p>
在此, 筆者試圖將我的經驗整理成幾點原則:
</p><ul>
<li>
先想清楚 test plan
</li>
<li>
熟悉 CPU/DSP 架構
</li>
<li>
熟悉待測物的功能、規格、演算法
</li>
<li>
確保知道如何重複產生 bug
</li>
<li>
知道 bug 發生點之後, 嘗試往前一級測試問題
</li>
<li>
紀錄所有測試數據以及判斷的依據, 以便回頭仔細檢視
</li>
</ul>
<p>
身為一個使用組合語言的通訊 DSP 程式設計師, 除了通訊演算法以外, debug 大概就佔掉絕大多數的時間, 真正寫 code 反而是這些工作裡面佔比例最少的。因此, debug 的效率與正確性, 對於程式甚至是晶片的品質, 有著決定性的影響。每個人都有每個人的方法, 筆者在這一篇文章裡, 試圖分享我個人的方法與經驗, 希望能對即將跨入或剛剛跨入這一個領域的工程師有點幫助, 而在這個領域很有經驗的工程師也歡迎大家一起交流心得。
</p>
<br/>-- <br/>
Albert Huanghttp://www.blogger.com/profile/15756607906352002721noreply@blogger.com0tag:blogger.com,1999:blog-5393693761509999841.post-11403279602919094522012-10-28T00:40:00.001+08:002012-11-21T12:46:00.240+08:00Emacs Wiki 簡易使用指南這是我之前發表在 Newzilla 線上雜誌上的文章,不確定能否直接轉錄回我的 blog,先用連結吧。<br />
<br />
<a href="http://skm.zoomquiet.org/data/20050206151303/" target="_blank">點進去看吧</a><br />
<br />Albert Huanghttp://www.blogger.com/profile/15756607906352002721noreply@blogger.com0tag:blogger.com,1999:blog-5393693761509999841.post-21063796471283206092012-10-28T00:16:00.002+08:002012-11-21T12:46:16.764+08:00Emacs Wiki 後一章 -- 專案、遠端連線與註腳模式<br />
原文撰寫於 2005 年 3 月 2 日,本來是接受某線上雜誌邀稿,該雜誌因故停刊,故未刊出,這其實只是草稿而已,我也懶得改寫了。<br />
<br />
黃俊傑 jjhuang <u>AT</u> cm-nctu-edu-tw<br />
<h2>
<span style="font-size: x-large;">
前言</span></h2>
在<a href="http://alberthuang314.blogspot.tw/2012/10/emacs-wiki_28.html" target="_blank">上一期</a>中, 我們學習了如何用 Emacs Wiki 來快速產生網頁, 本期我們將會介紹 Emacs Wiki 相關的工具; 使用 Emacs Wiki 的專案功能來管理不同的網頁, 將網頁傳到遠端的網頁伺服器上, 以及使用 Emacs 內建的註腳次要模式(footnote-mode) 來幫助我們輸入註腳。<br />
<h2>
<span style="font-size: x-large;">
Emacs Wiki 專案</span></h2>
如果你像筆者這樣有好幾個獨立的 Wiki 要編輯, 那麼你很可能需要使用到 Emacs Wiki 專案來管理這些檔案。 新增專案的方法如下,首先你要先進入 Emacs 的 customization<br />
<pre class="example" style="margin-left: 48px;">M-x customize-group <ret> emacs-wiki <ret>
</ret></ret></pre>
<span style="background-color: white;">然後再進入 Emacs Wiki Project 這個目錄, 進入之後把 Emacs Wiki Projects 這個變數打開來。 一開始 Emacs Wiki 是沒有任何專案的, 只有 default 這個專案, 而這個專案是沒有列在這個變數中。 若要新增一個專案, 首先要按 INS 這個按鈕, 然後輸入專案名稱於 Project name: 一欄, 接下來在 Project name: 的下方中間也有一個 INS 按鈕, 請按下這個按鈕, 然後輸入開啟這個專案時要改變的變數。 筆者所知道需要改變的變數至少有下列幾個:</span>
<br />
<dl>
<dt>emacs-wiki-publishing-directory</dt>
<dd>這個專案的網頁放置目錄</dd>
<dt>emacs-wiki-directories</dt>
<dd>這個專案的 Wiki 檔案放置目錄</dd></dl>
記得 emacs-wiki-directories 是複數名詞, 代表這是一個 list, 所以在 Value 那一欄必需將你的目錄用括號刮起來, 如:<br />
<pre class="example" style="margin-left: 48px;">("~/Documents/MyWebPage")
</pre>
增加完成之後, 記得按 State 這個按鈕把這次改變的專案設定儲存起來。 以後要使用專案, 可以直接開啟該專案的檔案, 或是在 Emacs Wiki Mode 中下 C-c C-v 改變專案。<br />
<h2>
<span style="font-size: x-large;">
傳送網頁至遠端伺服器</span></h2>
目前 Emacs Wiki 要編輯遠端的網頁, 可以放在本地端, 然後再用 rsync 等同步程式來做同步, 或是把專案放置在遠端的機器上。 要把專案放置載遠端的機器上, 可以把 emacs-wiki-directory 放在本地端, 把 emacs-wiki-publishing-directory 填上<br />
<pre class="example" style="margin-left: 48px;">"/user@host:/path/to/your/web/page"
</pre>
<span style="background-color: white;">如此, 當你下 C-c C-p (emacs-wiki-publish) 時, Emacs 就會透過 tramp 程式把檔案送到遠端的伺服器上。 M-x emacs-wiki-publish 會將所有的 Wiki 檔案都轉換成 html, 並且傳送到遠端, 在頻寬較小的情況下, 相當的耗費時間, 可以利用 M-x emacs-wiki-publish-this-page 來傳送目前編輯的頁面。</span><br />
如果你嫌每次都要按 M-x emacs-wiki-publish-this-page 打太多字, 可以參考 Emacs Wiki 專案首頁的建議<sup><a href="file:///Users/jjhuang/Library/Containers/com.apple.mail/Data/Library/Mail%20Downloads/EmacsWikiAndFootnoteMode.html#fn.1" id="fnr.1">1</a></sup>, 將 C-x C-p 按鍵定義成 M-x emacs-wiki-publish-this-page, 只要你在 ~/.emacs 加入以下幾行即可:<br />
<pre class="example" style="margin-left: 48px;">(add-hook 'emacs-wiki-mode-hook
(lambda () (global-set-key "\C-x\C-p" 'emacs-wiki-publish-this-page)))
</pre>
<span style="background-color: white;">這樣就會在每一次進入 Emacs Wiki 模式時將此按鍵加入。 你就可以在每一次編輯完一個檔案, 想要上傳時, 按 C-x C-p 來上傳目前編輯的檔案, 以節省傳輸時間。</span><br />
<h2>
<span style="font-size: x-large;">
註腳模式</span></h2>
<h3>
說明</h3>
註腳模式(footnote-mode) 是一個次要模式(minor mode), 與 Emacs Wiki 並無直接關聯, 是 Emacs 內建的次要模式。 筆者通常用這個模式配合 gnus 使用, 在編輯文章的時候加一些註腳用。 Emacs Wiki 採用的註腳格式與註腳模式產生出來的格式完全一樣, 所以我們也可以利用註腳模式來協助編輯 Emacs Wiki 檔案。<br />
與其他的次要模式一樣, 註腳模式的命令可以開啟或關閉註腳模式。 註腳模式的命令是<br />
<pre class="example" style="margin-left: 48px;">M-x footnote-mode
</pre>
<span style="background-color: white;">當註腳模式開啟的時候, Emacs 視窗下方的模式列會顯示 FN 的字樣。 當我們要新增一個註腳的時候, 只要在想要新增的位置鍵入</span><br />
<pre class="example" style="margin-left: 48px;">M-x footnote-add-footnote
</pre>
<span style="background-color: white;">接下來註腳模式會自動在新增的位置填上一個數字前後加上方括號, 並且跳到文章的最後, 加上註腳(Footnote) 字樣, 游標會停在要編輯的註腳後面等待使用者輸入註腳的說明文字。 輸入完之後, 我們可以輸入</span><br />
<pre class="example" style="margin-left: 48px;">M-x footnote-back-to-message
</pre>
<span style="background-color: white;">然後游標會回到剛剛新增註腳的位置, 使用者可以繼續本文的編輯。 其餘的註腳模式功能請參考快速鍵列表, Emacs Wiki 可以完全處理註腳模式產生的格式, 這篇文章就是利用註腳模式來來產生註腳的。</span><br />
<h3>
快速鍵列表</h3>
註腳模式的快速鍵不多, 只有六個, 表列如下:<br />
<table border="2" cellpadding="5" class="ewiki-table" style="color: black;"><thead>
<tr><th>按鍵</th><th>命令(鍵入之前先按 M-x)</th><th>說明</th></tr>
</thead><tbody>
<tr><td>C-c ! a</td><td>M-x footnote-add-footnote</td><td>增加註腳</td></tr>
<tr><td>C-c ! b</td><td>M-x footnote-back-to-message</td><td>由註腳說明處回到引用處</td></tr>
<tr><td>C-c ! d</td><td>M-x footnote-delete-footnote</td><td>刪除註腳</td></tr>
<tr><td>C-c ! g</td><td>M-x footnote-goto-footnote</td><td>跳到註腳解釋</td></tr>
<tr><td>C-c ! r</td><td>M-x footnote-renumber-footnotes</td><td>重新編排註腳號碼</td></tr>
</tbody><tfoot>
<tr><td>C-c ! c</td><td>M-x footnote-cycle-style</td><td>變換註腳形式</td></tr>
</tfoot></table>
<br />
<hr />
<sup>[<a href="file:///Users/jjhuang/Library/Containers/com.apple.mail/Data/Library/Mail%20Downloads/EmacsWikiAndFootnoteMode.html#fnr.1" id="fn.1">1</a>]</sup> Emacs Wiki 專案首頁, <a href="http://repose.cx/emacs/wiki/#sec5">http://repose.cx/emacs/wiki/#sec5</a>Albert Huanghttp://www.blogger.com/profile/15756607906352002721noreply@blogger.com0tag:blogger.com,1999:blog-5393693761509999841.post-49552779808534649382012-10-15T12:59:00.000+08:002012-11-21T12:46:38.893+08:00How to use HHKB Pro 2 as an external keyboard to an iPad<br />
Happy Hacking Keyboard Professional 2 (HHKB Pro 2), which is produced by PFU Limited of Japan, is a great keyboard with a small footprint, and it contains only 60 keys. As a new iPad owner, I wonder if I can combine these two gadgets and write notes on-the-go.<br />
<br />
After some trial-and-error, finally I make it work! Here is how to make it. First you need to buy iPad Camera Connectivity Kit from Apple. This kit is designed for connecting to a digital camera, so if you ask any salesperson in Apple store, he or she will probably tell you it's not designed to connect to an external keyboard. Never mind what he or she says, just buy it. And then you'll need a USB hub with external power supplied, i.e. you actually need to plug the external power cord to a power source because HHKB Pro 2 draws larger current from USB port than an iPad can supply. Now connect your HHKB Pro 2 to the USB hub with external power supplied, and then connect the USB hub to your iPad via the camera connectivity kit. Open any text-oriented application, e.g. OmniOutliner, and then you can type by your HHKB Pro 2!<br />
<br />
To use these gadgets on-the-go, I bought a mobile battery with me so that the USB hub can be supplied by the battery. Here are the photos of them:<br />
<br />
<a href="http://www.flickr.com/photos/22393596@N06/8089081539/" target="_blank">What you need</a><br />
<br />
<a href="http://www.flickr.com/photos/22393596@N06/8089081935/" target="_blank">How to connect HHKB Pro 2 to a new iPad</a><br />
<br />
<br />
Requirements:<br />
- a new iPad, or iPad 3<br />
- a Happy Hacking Keyboard Professional 2<br />
- a USB hub with external power source<br />
- a mobile battery if you want to use them on-the-go<br />
<br />
Note I'm not sure if older iPad works this way.<br />
<div>
<br /></div>
Albert Huanghttp://www.blogger.com/profile/15756607906352002721noreply@blogger.com1tag:blogger.com,1999:blog-5393693761509999841.post-51958662968838179102012-10-12T21:02:00.004+08:002012-11-21T12:47:10.591+08:00Emacs etags 簡介<br />
這也是筆者多年前發表在 NNTP news 上的文章,留存備份。<br />
<br />
etags 簡介<span class="Apple-tab-span" style="white-space: pre;"> </span>-*- Outline -*-<br />
<br />
* 前言<br />
有許多的 IDE(Integrated Development Environment) 都提供了函數名稱的<br />
自動完成功能( 亦即,輸入前面幾個字元之後,編輯器可以自動幫你完成後面<br />
的函數名稱)。Vi 裡面有 ctags 可以做到這件事,那麼 Emacs 呢?答案是<br />
etags. 在這篇文章裡,我會簡短的介紹如何使用 etags.<br />
<br />
* etags 使用方法<br />
** 建立函數及關鍵字列表<br />
在使用之前,你必須先在你的發展環境目錄底下建立列表; 假設你的發展環<br />
境目錄名稱叫做 /path/to/developer/, 建立列表的方法如下:<br />
<br />
% cd /path/to/developer/<br />
% etags *.h *.c<br />
<br />
這樣就建立完成了,根據 etags/ctags 的手冊, etags/ctags 可以處理的語<br />
言有 C, Objective C, C++, Java, Fortran, Ada, Cobol, Erlang, LaTeX,<br />
Emacs Lisp/Common Lisp, makefiles, Pascal, Perl, Postscript,<br />
Python, Prolog, Scheme and most assembler-like syntaxes.<br />
預設的列表檔名是 TAGS.<br />
<br />
** 把函數及關鍵字列表讀進 Emacs<br />
開始用 Emacs 編輯檔案, 比如說你正在編輯 foo.c, 你先用 C-x C-f 把<br />
foo.c 讀進來之後,你需要使用 etags 的功能,那麼你就執行<br />
M-x visit-tags-table <ret> /path/to/developer/TAGS <ret></ret></ret><br />
把 /path/to/developer/TAGS 檔案讀進來。註:<ret> 表示 Return 鍵,或</ret><br />
是在鍵盤上通常標示為 Enter.<br />
<br />
** 在 Emacs 中搜尋函數內容<br />
有的時候我們會想要直接跳到某個函數裡面去修改他的內容,你可以使用<br />
M-. (沒錯,就是 Meta 跟一個句點) 然後輸入函數名稱就會跳到該函數的<br />
code 那裡去; 如果你按 M-. 的時候游標指著一個函數名稱,你可以在輸入<br />
函數名稱的時候直接按 <ret> 即可跳到該函數源碼的地方。跳過去之後,如</ret><br />
果你想要回來原來地方,你可以用 M-* 來做到。<br />
<br />
如果你想要在另一個視窗內看到該函數源碼,而不是你現在的這個視窗(對照<br />
方便), 那麼你可以用 C-x 4 . TAG <ret> 來達成這件事。</ret><br />
<br />
如果你要搜尋某些函數與關鍵字,你可以用 M-x tags-search 的功能,這個<br />
可以用 regular expression 來搜尋。當你用 M-x tags-search <ret></ret><br />
REGEXP <ret> 之後,你可以用 M-, (Meta 逗點), 找下一個搜尋到的函數名</ret><br />
或關鍵字。<br />
<br />
** 函數及關鍵字自動完成<br />
etags 並沒有提供函數及關鍵字自動完成(auto-completion)的功能, 但是<br />
Emacs 有提供一個功能可以達成這件事,叫做 dynamic abbreviation<br />
expansion. 這個功能事實上是把去找在開啟的 buffer 裡面有那些字串是你<br />
輸入字串的完整字串,而 TAGS 列表就在一個 buffer 裡面,所以可以達成<br />
函數及關鍵字自動列表。當你輸入一個函數名稱或是一個變數名稱的前面幾<br />
個字母,比如說: foo-, 然後按 M-/, 這時候 Emacs 會把所有可能的字串找<br />
到,並把第一個可能的字串直接完成,所以你按了一次 M-/ 之後可能會變成<br />
foo-bar-function, 你繼續按 M-/ 可以變換成其他可能的字串,直到沒有為<br />
止。或者是你也可以按 C-M-/, 這時候 Emacs 會像其他時候的<br />
auto-completion 的行為一樣,跳出一個視窗把所有的可能列表列出來給你<br />
選擇。<br />
<br />
* 結語<br />
當我開始使用 etags 的功能之後,我就沒有辦法不用這個功能了,因為實在<br />
是太方便了。etags 也可以幫你自動完成標準函式庫裡的名稱,只要你在<br />
etags 的時候把 /usr/include 裡的表頭檔案也包含進來就可以了。etags 還<br />
有其他比較進階的功能,我沒有一一列出來,有興趣的人可以去看看 M-x<br />
info 裡的 Emacs 手冊。最後我做一個這次提到的功能列表,供讀者參考用。<br />
<br />
* 按鍵列表<br />
M-x visit-tags-table <ret> TAGS-file <ret></ret></ret><br />
把 TAGS-file 檔案讀進 Emacs<br />
M-. TAG <ret> 尋找函數或關鍵字定義的源碼</ret><br />
C-x 4 . TAG <ret> 在另一個視窗尋找函數或關鍵字定義</ret><br />
M-* 回到尋找關鍵字定義之前的地方<br />
M-x tags-search <ret> REGEXP <ret> 用正規表示式搜尋函數或關鍵字定義</ret></ret><br />
M-, 找下一個搜尋到的函數或關鍵字<br />
M-/ 自動完成可能的函數或關鍵字<br />
C-M-/ 列出所有函數或關鍵字名稱的自動完成列表<br />
Albert Huanghttp://www.blogger.com/profile/15756607906352002721noreply@blogger.com0