bloggerads

2013年12月28日 星期六

C++ : virtual function

參考以下的範例,若想統一用base class pointer指向base class object以及 derived class object, 但base class 和 derived class 又有相同的函式, 那麼就必須將這種相同的函式宣告成virtual function 才能達到

#include <iostream>

class c1{
  public:
     virtual void vfunc(){ std::cout << "Calling c1\n";}
};
class c2: public c1{
  public:
     virtual void vfunc(){ std::cout << "Calling c2\n";}
};
int main()
{
  class c1 *c;
  class c1 c1_obj;
  class c2 c2_obj;
  
  c = &c1_obj;
  c->vfunc();
  
  c = &c2_obj;
  c->vfunc();
  
  return 0;
}

___________OUTPUT____________
Calling c1
Calling c2

2013年12月26日 星期四

C++ : template

function template (樣板函式):

C++提供template, 用來免去重複撰寫類似的函式(僅變數型態不同的函式)

template<class T> 
// template<typename T> //class or typename
T min (T x, T y) { 
  return (x < y) ? x : y; 
}

同樣的東西, 在C則是使用Macro來達成


#define min(x, y) (((x) < (y)) ? (x) : (y))

2013年12月25日 星期三

C++ Class 小記

這裡示範一個 Class 的 sample:

//--------------------------------------------------------------------------
//  In Tui.hpp file
//--------------------------------------------------------------------------
class CTui
{
// 沒有public的部分即為private members
public:
        CTui();  //Constructor
        ~CTui(); // De-Constructor

        void print(char *p);      

};


//--------------------------------------------------------------------------
// In Tui.cpp file
//--------------------------------------------------------------------------

#include "Tui.hpp"

//
//class members of CTui
//
CTui::CTui() 
{
  // new 記憶體, initial 參數...
}
CTui::~CTui() 
{
  // delete 記憶體
}

void CTui::print(char *p) 
{

}


2013年12月23日 星期一

Differential signaling, 差分/動信號

電磁學有一章節專門討論傳輸線,有一種傳輸線叫做雙線式傳輸線目前廣泛用在電子信號傳輸,如SATA的TX/RX, PCIe的DQS, clock, USB...等等

這種差分信號的好處是可以抗雜訊,但是設計上就較複雜因為晶片要有能力把信號載到射頻上。

因為是射頻的信號,因此要提到特徵阻抗(Characteristic impedance)這個東西,特徵阻抗是電場和磁場的一個比值,單位是歐姆,他和傳輸線的材質/尺寸相關。若不是高頻使用的傳輸線,則傳輸線上的每一點特徵阻抗都會有差異,造成信號的反射(衰減)。

以SATA為例(下圖),SATA傳輸線的特徵阻抗為100Ohm+/-10%,如果信號不好通常就是調整眼圖(Eye Pattern)的參數Emphasis (pre-emphasis / de-emphasis)和Amplitude。
  • Emphasis是信號high, low互相轉換時的斜率
  • Amplitude是信號的振幅
下圖介紹眼圖裡面SNR, Jitter等名詞
圖片出處 (Eye Diagram Basics: Reading and applying eye diagrams)

2013年12月8日 星期日

C++ : class內部宣告static member

以下討論在class裡宣告static member 

static member代表他只與class相關,而不與物件相關 (故無法用this指static member)
static member有static function & static function兩種

static function 只能呼叫static variable & static function, 不可呼叫物件層級的function 和 variable。但物件層級的 function 則可同時呼叫static與非static member

請參考以下範例:


#include <stdio.h>
class cTest
{
public:
 static int Num;
 static void Func() {
  //static function 只能呼叫static variable & static function, 不可呼叫物件相關的function 和 variable member
  printf("%d", Num);
 }
};

int cTest::Num = 9; // static variable的初始值必須寫在global area. 

int main()
{
 cTest::Num = 10;
 cTest::Func();
 return 0;
}

2013年12月4日 星期三

NAND flash 與 NOR flash

EEPROM翻成中文叫電子可抹除唯讀記憶體(非常繞舌),最早發明時其構造為NOR結構,所以有人就直接將其稱為NOR flash, 後來因應大規模儲存記憶體的需求,因此再研發了以NAND為結構的EEPROM,很多人就直接稱NAND結構的EEPROM為NAND flash

所以我們有兩種flash, 一種是NAND一種是NOR

NOR的特點是可IC內執行程式(XIP, eXecute In Place),這樣應用程序可以直接在flash內執行,不必再把程式讀到系統的RAM中,實務上主機板的BIOS就是放在NOR(SPI ROM)裡

NAND實務上則是用來放資料用,如USB/EMMC/SSD這些都是使用Nand當存儲結構。

NAND flash的結構單元尺較NOR來的小很多,這幾年NAND的技術突飛猛進,從SLC->MLC->TLC,閘極通道尺寸也從24nm->19nm->15nm,甚至到了3D NAND,主要的Vendor是Toshiba, Micron, Hynix & Samsung

2013年11月29日 星期五

C 巨集用法經驗談

1. 可用來設定Memory address的value。 巨集的參數記得括弧,整個巨集也要括弧以免別人引用時因為C priority問題產生bug

#include <stdio.h>

typedef unsigned int DWORD;

#define SET_MEM_32( addr, val) \
( *(DWORD* )(addr) = (val) )

#define GET_MEM_32( addr)    (*(DWORD* )(addr))

#define MODIFY_MEM_32( addr, mask, val) \
( *(DWORD* )(addr) = GET_MEM_32(addr) & ~(mask) | (val) & (mask) ) 

int 
main()
{
    unsigned char arr[10]={0,1,2,3,4,5,6,7,8,9};

    SET_MEM_32(arr, 0x22334455);
    printf("%x\n",GET_MEM_32(arr));

    MODIFY_MEM_32(arr, 0xff0000, 0x770000);
    printf("%x\n",GET_MEM_32(arr));
    
    return 0;
}

--------------執行結果--------------
22334455
22774455

Internet Overview (網路概論)


https://en.wikipedia.org/wiki/OSI_model
第4層 傳輸層(Transport Layer): Segments = Data +控制資料
  • 把傳輸表頭(TH)加至資料以形成資料報。傳輸表頭包含了所使用的協定等傳送資訊。例如:傳輸控制協定義(TCP) 等。 (TCP將資料封包化並組成區段)
第3層 網路層(Network Layer): Packet = Segments +控制資料
  • 決定資料的路徑選擇和轉寄,它網路表頭(NH)加至資料報,以形成封包。網路表頭包含了網路資料。例如:網際網路協定(IP) 等。(透過路由(router)找到主機位置(邏輯位址)並決定傳送的路徑), IP分享器也在這層
第2層 資料連結層(Data Link Layer): Frame =  Packet +控制資料
  • 負責網路尋址、錯誤偵測和改錯。(交換器(Switch)分析Frame,並讀取目的端和傳送端的Mac address然後傳送到所對應的連接port)
第1層 實體層(Physical Layer) 
  • 定義一些電器的規格,如電壓,Pin腳等等。 (集線器(Hub)就是一個中繼器(repeater), 忠實的把信號傳到每個port上)
----------------------------------------------------------------
NIC (Network Interface Card): 網路介面卡
MAC address: 實體位址,每張網卡都有獨一無二的Mac address,由6個Byte組成
IP address: 邏輯位址,軟體/伺服器assign的, 透過遮罩大概知道這台電腦是透過哪個主機連過來的
IP 位址: 電腦主機在 Internet 上的位址。
IP 位址=網路位址(Network ID)+主機位址(Host ID)
IP分成class A~E各種等級, A 類、B 類和 C 類是商業類使用之位址,可指定給主機

子網路遮罩: 用來判定來源IP和目的IP是否在同一網域的一個判斷位址。
預設閘道位址: 傳送到不同網域時用以決定封包的傳輸途徑。

DNS伺服器位址: DNS 伺服器的用途在於將主機名稱(Host Name)轉成IP 位址。 

TCP和UDP的差異: ﹐TCP 提供的是可靠傳輸﹐傳輸(送)層檢測手續﹐都會在 TCP 中實現而 UDP 不是可靠傳輸,因此相較於 TCP 來說,一大堆必需佔據封包表頭的都可省略來換取更大的 payload。UDP只是一個單方向的網路協定,如果要作可靠傳輸,那麼,其確認機制將從傳輸層退為應用層進行了 (也就是程式本身要提供可靠傳輸機制)。詳細請參考:TCP 與 UDP



(待續)

2013年11月26日 星期二

C# : Class inherits and virtual (override) example


    public class Father
    {
        public Father() { Console.WriteLine("Father Constructor!"); }
        public virtual void WifeAge() { Console.WriteLine("Age is 50, father's wife!"); }
        public void FamilyName() { Console.WriteLine("Family name: Lee"); }
        ~Father() { Console.WriteLine("Father De-Constructor!"); }
        
    }
    public class Son : Father
    {
        public Son() { Console.WriteLine("Son Constructor!"); }
        public virtual void WifeAge() { Console.WriteLine("Age is 30, son's wife!"); }
        ~Son() { Console.WriteLine("Son De-Constructor!"); }
        
    }
    public class Program
    {
        public static void Main(string[] args)
        {
            Father obj = new Father();
            obj.WifeAge();
            Son obj2 = new Son();
            obj2.WifeAge();
            obj.FamilyName();
            obj2.FamilyName();
        }
    }
_/_/_/_/_/_/ _/  OUTPUT  _/_/_/_/_/_/_/_/

Father Constructor!
Age is 50, father's wife!
Father Constructor!
Son Constructor!
Age is 30, son's wife!
Family name: Lee
Family name: Lee
Son De-Constructor!
Father De-Constructor!
Father De-Constructor!

2013年11月11日 星期一

C++的Container: stack使用範例

// stack.cpp
#include <iostream>
#include <stack>
#include <string>

int main()
{
    std::stack<int> ss;
    std::cout<<"size="<<ss.size()<<std::endl;
    for (int i=0; i<20; i++)
        ss.push(i);
    std::cout<<"size="<<ss.size()<<std::endl;
    while (!ss.empty()){
        std::cout << ' ' << ss.top();
        ss.pop(); //pop() has no return value, use top() to check value
    }
    std::cout<<std::endl;
    return 0;
}

輸出:


martin@martin-K42Jc:~/Code$ g++ -o stack stack.cpp

martin@martin-K42Jc:~/Code$ ./stack
size=0
size=20
 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

2013年11月2日 星期六

C++的Container: Map使用範例

C++提供map容器, [key]=value. 使用key來找尋找、插入、刪除.

map容器的排列會根據key來自動排列. (是一種平衡二元素的實現)


以下是範例:


#include <iostream>
#include <string>
#include <map>
using namespace std;
int find_and_erase(map<string, string> &mm, string ss)
{
    map<string, string>::iterator it;
    //find and erase the element
    if ( mm.end() != ( it = mm.find(ss)) ) {
        mm.erase(it); cout << ">Erase " << ss << endl;
    }else  cout << ">Cannot find " << ss << endl;
}
int show_all(string ss, map<string, string> mm)
{
    map<string, string>::iterator it;
    for(it = mm.begin(); it != mm.end(); it++)
                cout<<it->first<<" "<<it->second<<endl;
    cout << "****Finish job: "<< ss << endl;    
}

int main()
{  
    map<string, string> mm;
 
    mm["John"] = "John_data";
    mm["May"]  = "May_data";
    show_all("add John & May", mm);
    if ( false == mm.insert(pair<string, string>("Martin", "Martin_data")).second )
        cout << "(insert failed)" << endl;
    show_all("insert Martin", mm);
    // Insert same key twice, should get failed return
    if ( false == mm.insert(pair<string, string>("Martin", "Martin_data")).second )
        cout << "(insert failed)" << endl;
    show_all("insert Martin", mm);    
   
    cout << "total size: " << mm.size() << endl;
   
    find_and_erase(mm, "John");
    show_all("erase John", mm);
       
    // Reverse iterator
    for (map<string, string>::reverse_iterator itr = mm.rbegin(); itr != mm.rend(); itr++)
        cout<<itr->first<<" "<<itr->second<<endl;
    cout << "****Reverse Traversal" << endl;
    return 0;
}

Output:

John John_data
May May_data
****Finish job: add John & May
John John_data
Martin Martin_data
May May_data
****Finish job: insert Martin
(insert failed)
John John_data
Martin Martin_data
May May_data
****Finish job: insert Martin
total size: 3
>Erase John
Martin Martin_data
May May_data
****Finish job: erase John
May May_data
Martin Martin_data
****Reverse Traversal

2013年10月31日 星期四

C++: vector Shuffle(洗牌) 函數

C++提供隨機打亂vector的函數, random_shuffle()。若想要每次第一次都是不同的亂法,可以引入一個function pointer, 而這個function限定一個輸入和一個輸出引數, type要和iterator一樣, 且輸出值不能為負數或大於輸入引數

#include <stdio.h>
#include <vector>
#include <algorithm> //random_shuffle
#include <time.h>

int gen(int i) {return rand()%i; }

int main()
{ 
  srand(time(0));
  std::vector<int> v;
  v.push_back(1);
  v.push_back(2);
  v.push_back(3);
  v.push_back(4);

  random_shuffle(v.begin(), v.end(), gen);

  for (unsigned int x=0; x<v.size(); x++)
    printf("%d\n", v[x]);
  return 0;         
}

2013年10月30日 星期三

C++的Container: Vector使用範例

一般C語言如果想要動態增加陣列大小,則必須要呼叫 realloc()。C++提供了vector更靈活的使用陣列,請參考如下的範例:

#include <stdio.h>
#include <vector>

void print(char x, std::vector<int> &vec) // Call by Reference
{
    printf("%c.", x);
    for (int i=0; i<vec.size(); i++)
        printf(" %d", vec[i]);
    puts("");
}

int main()
{  
   std::vector<int> vec;// vector<int> vec(10, 0); //初始size為10個0
   std::vector<int>::iterator end;
     
   vec.push_back(10);  print('a', vec);
   vec.push_back(20);  print('b', vec);
   vec.insert(vec.begin() + 1, 30); // 將30插入陣列中第1個位置
   //vec.insert(vec.begin() + 1, 2, 30); // 將兩個30插入陣列中第1個位置
   print('c', vec);
   //auto end=vec.end()-1;     //  -std=c++11 
   vec.erase(end=vec.end()-1); // 移除最後一個元素
   print('d', vec);
   vec.pop_back();    // 移除最後一個元素
   print('f', vec);
   
   return 0;
}


輸出:
a. 10
b. 10 20
c. 10 30 20
d. 10 30
f. 10

2013年10月28日 星期一

C++的Container: List使用範例

#include<list>
#include<iostream>
#include<stdio.h>
using namespace std;

#define  OFFSET_ITERATOR(iterator, offset)  {\
  iterator = obj1.begin(); \
  for (int i=0; i<offset; i++) \
  iterator++;\
 } //將intertaor移動到offset的節點上


void show_list();

list<int> obj1;//建一個空的list對像
list<int>::iterator j;
list<int>::iterator k;

int main(void)
{

   for(int i=0;i<10;i++)
       obj1.push_front(i);

   show_list();

   // Remove first node (pop front)     
   obj1.pop_front();  printf(">obj1.pop_front();\n");
   show_list();
   
   // Remove node
   OFFSET_ITERATOR(j, 4);
   obj1.erase(j);    printf(">obj1.erase(4); //delete node: j-1, i.e. 4\n");
   show_list();
  
   // Insert node 
   OFFSET_ITERATOR(j, 4);
   obj1.insert(j, 55);  printf(">obj1.insert(4, 55);\n");
   show_list();
   
   // Remove node from j to k-1, where (j, k)=(2, 4)
   OFFSET_ITERATOR(j, 2);
   OFFSET_ITERATOR(k, 4);
   obj1.erase(j, k);     printf(">obj1.erase(2, 3); //delete node: j~k-1, i.e. 2~3\n");
   show_list();
   
   system("pause");
   return 0;
}

void show_list()
{
   for (j=obj1.begin(); j!=obj1.end(); j++)
      cout<< *j <<"  ";
    printf("\n");
}




2013年9月23日 星期一

C++ class的應用(一)

目前想到的應用有兩種,寫成class程式會更漂亮:

  1. TUI: 在DOS底下切換文字視窗
  2. 檔案讀寫: (如下)

+   class CLog
+   {
+   public:   
+       CLog()
+       { 
+           if ( !(fp= fopen("my_log.txt", "w") ) 
+              )
+           { printf("Warning! Unable to create file\n");} 
+       }
+       ~CLog()
+       {
+           fclose(fp);
+       }
+       bool write(const char *p)
+       {
+          return ( fprintf(fp, "%s", p) ? 1: 0 );
+       }
+       bool write(char *p)
+       {
+          return ( fprintf(fp, "%s", p) ? 1: 0 );
+       }
+       
+   private:
+       FILE *fp;
+       
+   };

2013年9月19日 星期四

C++ : string

Example 1

+  //
+  // Find all key world position in a string
+  //
+
+  #include <stdio.h>
+  #include <iostream>       // cout
+  #include <string>         // string
+  
+  int main ()
+  {
+    std::string str ("xx23xx67xxabcdxx");
+    std::string key ("xx");
+  
+    for (int pos = str.find(key) ; pos >= 0; ) 
+    { 
+        printf( "xx at: %d\n", pos);         
+        pos = str.find(key, pos+1); 
+    }
+  
+    return 0;
+  }

___________OUTPUT____________
xx at: 0
xx at: 4
xx at: 8
xx at: 14

Example 2

+  //
+  // string -> char array
+  // char array -> string
+  //
+
+  #include <stdio.h>
+  #include <string>
+  #include <string.h> //strncpy
+  
+  int main () {
+    char c1[]="123";
+    std::string cpp(c1); // char array -> string
+    printf("%s\n", c1);
+    
+    char c2[10];
+    for(int x=0; x<sizeof(c2); c2[x]=0, x++); // Reset c2
+    strncpy(c2, cpp.c_str(), sizeof(c2)-1); // string -> char array
+    
+    printf("%s\n", c2);
+    return 0;
+  }

___________OUTPUT____________
123
123

Example 3

+ #include <stdio.h>
+ #include <string>
+ #include <sstream>
+ // #include <iostream> cout

+
+ int main()
+ {

+    std::stringstream ss;
+    std::string str;
+    //
+    // int -> string 
+    // 
+    int i= 20;
+    // ss.clear();
+    // str = std::st_string(i);
+    ss << i;
+    ss >> str;
+    std::cout << "int -> string " << str << std::endl;
+    printf("----------------------------\n");
+    //
+    // string -> int 
+    //
+    int ival;
+    ss.clear();
+    ss << str;
+    ss >> ival;
+    std::cout << "string -> int " << ival << std::endl;
+    
+    return 0;
+ }

2013年6月14日 星期五

Intel (x86 Ivy+Panther Point) Power Sequence (開機訊號時序)

這篇介紹的是按下電腦開機按鈕到Bios接手之前的訊號時序邏輯, 以Desktop Motherboard為範例

// 開啟電源後,從SIO(super IO)報到南僑
1. PWRBTN# assert (to SIO)
2. SIO assert SB_PWRBTN# to PCH

// PCH和SIO的handshake
3. PCH assert SUS_WARN# to SIO
4. SIO assert SUS_ACK# to PCH

5. PCH de-assertSLP_LAN# 去叫邏輯電路打開 3.3v_ME
6  PCH de-assertSLP_A# 去叫邏輯電路打開 1.05v_ME
7. PCH  de-assert  SLP_S4# 信號去開啟dual power rail (這個power rail是由standby power轉來的)
8. PCH de-assert  SLP_S3# 信號去開啟ATX power的PSON#
9. ATX power 回 ATX_PWROK給PCH
10. PCH發給CPU, DRAM_pwrok 和 CPU_pwrOK,代表VCORE ready
11. PCH de-assert PLTRST# (有些設計是PCIRST#), 接著就開始Reset一些周邊裝置

done.

2013年6月6日 星期四

C# : Show Version

string FileLocate = @"\\Address\Filename.exe";

if (File.Exists(FileLocate) == true)
{
    var versionInfo = FileVersionInfo.GetVersionInfo(FileLocate);
    string version = versionInfo.ProductVersion; //  "1.0.0" as default
    
    string MessageBoxTitle = "Version";
    string MessageBoxContent = version.ToString() + "\n";
    DialogResult dialogResult = MessageBox.Show(MessageBoxContent, MessageBoxTitle, MessageBoxButtons.OK);
}