2015年10月31日 星期六

大數據(Dig Data)研究筆記1

看了二本書:
1. 天下文化出版"大數據"
2. 高立圖書出版"資料探勘"

"大數據"是現象描述,指出大數據產生之前因後果。
此書對Bee來說已是衝擊,因為從不知大數據所產生之影響力,一但了解便覺得事態嚴重。
因為物聯網是趨勢,卻沒有多少人知道要如何產生商業行為,其中關鍵就是大數據。
農業時代最重要的發明是專業化。
工業時代最重要的發明是動力機器。
資訊時代最重要的發明就是大數據。
或許硬體人會認為是電腦,但電腦只是硬體,軟體才是靈魂。
在了解大數據後,再來便是去看其內容為何?

大數據並不是單一學科,實際上像是離散數學一樣,是一堆方法的集合。
資料探勘算是基礎,於是買書來看。
雖未完整了解,但發現資料探勘Bee之前就遇到一部分了,也見證其威力。
Bee在前公司曾待在新部門開發新產品,遇到機器學習。對於機器學習的威力感到震憾。
若當時產品成功,一堆軟體工程師便直接失業。
當大家都以為軟體工程師算是新行業,但新行業的技術會終結一半的專業人員,威力巨大超過想像。
正因為親身經歷過,如今其技術擴張為大數據,自然了解影響層面不止在軟體。

現在了解了大數據,其實算是晚了。再來要加速了解,並評估其影響。

2015年10月1日 星期四

8位元MCU終結於物聯網

8位元MCU一直有人說會終結於32位元MCU。這點Bee無法認同,除了價格外,找不到致命點。
不過,可以的話Bee還是想用32位元MCU,在函式庫上修改的少。

但在進入物聯網後,情況不同了。
物聯網使用MCU機會更大,但要解通信的地方也大增。
就以藍芽應用來看,光是藍芽函式庫就超過64KB,還有要加上HAL函式庫,看來少說96KB跑不掉。
已經超過8位元MCU容量64KB限制。以擴充的8051來說,要換Bank或是除錯,都變得很不容易。
也就是物聯網本質上,已經將8位元MCU排除在外。
8位元MCU變成無法單獨應用於物聯網,除非只做元件,由另一個32位元MCU去做連線功能。
但這仍只是暫態,以MCU的多功能腳位,只要腳位夠,基本上加強設計大部分可以免除。
結果物聯網應用一但展開,所以舊式MCU都會轉到物聯網上,等於宣判8位元MCU死刑。
8位元MCU在物聯網上,除了Sensor外,已無空間。
從應用端終結,才是真正的終結!

2015年9月30日 星期三

換MCU累人?巴不得早點換

Bee和許多工程師推新MCU,幾乎推不動。原因在於換MCU後,軟體工程浩大。
但對Bee來說卻不是,換MCU軟體只改一點點,主要都在信號測試驗證。
為何差異如此?因為利用RTOS。
Bee總是將RTOS做為多人開發及PC模擬工具。所以函式庫的再利用率很高。
不只MCU用,PC上也可以使用,拿去做PC工具也可以用。
而PC模擬也可以做部分前期發展。
規劃得宜,只有二件事可以做:新功能元件開發及拼裝測試。

那移程式到MCU這件事,還是有工作要做嗎?有只有動RTOS。
基本上在可以相容於PC,這件事等於是已經做好MCU移動的打算。
所以真正移動到MCU,只要小調及測試。

MCU已經單價很低,工程師薪水也只會低。
若是沒有自由換MCU能力,又怎能突顯存在價值。
所以,巴不得馬上換,去老闆面前展示,變成主要目標了。

2015年9月12日 星期六

2015年9月10日 星期四

TIOBE上Objective-C的怪異現象

Objective-C在過去一年內驟降,幅度已到10%佔有率,對於學程式語言至少要一年以上來說,這是很嚴重的流失。可是使用平台的人數實際上是成長的,這非常不合理。問題是人到那去了?

將前十項有C相關的線抽出來看,人口流向JavaC++。但swift應為Objective-C的繼承者,佔有率提升不是很多。

使用人口移動,大部分是和應用有關,但這次不是。想了一下,查了Java是否可在iOS上執行,答案是有轉換器(bridge)。也就是C++也有在iOS上的bridge,這就解釋了人口的移動。因為一套程式碼,可以同時賣二個平台,還是很重要的。維護二套程式,還是容易出錯。

2015年9月9日 星期三

看智慧家電心得

看到新的智慧家電,其中一款有新元素出現。它是食材秤,用來量測食物份量,但支援平板APP,告知食物型式,可以查到熱量、營養成分及組成比例等。可以簡化食品營養規劃,對於減肥塑身的人來說,這非常有用。
也就是結合雲端資料查詢的智慧家電,可使原先單一功能家電有不同的面貌。比一般秤貴,是因為同時買了雲端服務,不只是單買下硬體。不過變成家電業要同時負担雲端服務。

或許這個才是物聯網的本質,一個物理數值連網不能代表物聯網,物理數值再加上相關資料庫,才是真正的物聯網。

2015年7月19日 星期日

物聯綱MCU使用分析

物聯網有五大領域
1. 穿載式
2. 智慧車
3. 智慧家庭
4. 智慧城市
5. 智慧工廠
MCU可發揮空間只有三個,穿載式、智慧家庭及智慧工廠。另外二項不是小公司玩的。
穿載式用在老人照護,看來做醫療儀器公司會去主導。
智慧工廠,就要看狀況了。
所以智慧家庭是MCU最有可能發揮的地方。
但智慧家庭的最大問題是,那一個才是智能家管中心?
控制中心可以確定,其他相關的家電才可以穩定發展。
現在智慧家庭其控制中心完全沒有規格。
大部分是專用,也有NAS,也有router。所以實在難以發展。
只能等控制中心穩定了。

2015年6月27日 星期六

AutoIt試用心得

必須往系統設計上發展,也就是MCU及PC程式皆要會寫。
但PC上太多資源不好查,又要很深入C++,這個學習時間太長。
後來找到外掛程式AutoIt,看來這個可以解決問題。
它可以做膠合程式及PC GUI界面,所以只要使用C程式就可以了。
後來發現其實AutoIt比原預期的多,變成可以做出大部分測試及外掛程式。
且AutoIt可用範圍也比我想的大,也就是簡單應用就全包了。
使用它,也可以簡單學習windows程式設計。
先玩TCP/IP,因為這個手機也會用到。

MCU終極的應用程式Interpreter及Data Base

為何會說是終極,因為再做下去就是Shell了,用到Shell不如去用單板電腦上的Shell。
會有這一篇主要是做資源需求的記錄。

Interpreter的選擇比較多,易上手的是Lua。
Lua的ROM需求大約是300KB~400KB之間,因為還要加上User功能,所以只能給大約值。
主要的問題在RAM,因為程式是跑在RAM上,所以RAM的需求高些。這個不好估算。

要使用最小的Interpreter,就屬Forth了,ROM的容量從不到64KB到128kB。
看使用的Forth是用組合語言建造的,還是用C。

再來是Data Base,只有一套合用,就是SQLite。ROM大約要400KB,RAM需求不大。
但Data Base的速度依賴File System的速度。所以用在SDIO上是必須的。
以SD卡的高容量,Data Base應是很能發揮其功能。這點是Bee相當看好的新應用。
若是沒有用到查詢功能,理論上ROM可以更小,也許在250KB。
不使用查詢的狀況,大概是純記錄用,要解析時再將SD卡拿到PC去解析。
大部分還是機上查詢,還是算400KB,不然有擴充就完蛋了。

MCU上安裝Data Base是Bee以前從未想過的。
但在STM32F446出現,也開始考量這樣的需求。
但在MCU使用了Data Base之後,也表示MCU的軟體已經走到底了。
再複雓的應用,就是單板電腦接手了。
一項技術玩到底了,再來怎辦?
這成為Bee下一個思考的題目了!

2015年6月20日 星期六

單板電腦興起壓迫MCU應用

四年前看到Cortex-A系列開始以低於10美元供應,會有新的應用。
只是後來沒有機會用上。
現在看到單板電腦用Cortex-A系列CPU做的單板電腦以低於10美元出現。
可以確定Cortex-A系列正式進入MCU市場,因為最後一個障礙已消失了。
Cortex-A之所以無法進入MCU市場,主要在於它是CPU,必須外掛RAM,使得Layout要使用多層板。
以MCU市場來說,多層板的價格及複雜度高,使得工程師不易採用。就算價格低,仍不具足夠吸引力。
若用單板電腦,是不用煩惱Layout但價格又會變高。
不過單板電腦價格再降,變成直接使用,現在就是如此。
單板電腦已有基本作業系統及函式庫,這是MCU比較缺的。
單板電腦的程式開發,軟體函式庫拼裝能力比較重要。
這種開發方式其實就和MCU使用RTOS開發是相同的。
也就是MCU工程師會使用RTOS,要轉成單板電腦是比較沒有問題。
所以低價單板電腦的出現,將MCU工程師再次分級。

單板電腦在GUI上的函式庫很多,可以輕易完成很好的GUI,這是MCU不易做的。
好的GUI是很好的加分附加,對於商品推展有很大的幫助。
使用單板電腦也有降低庫存的壓力,因為是半成本,變成不用備太多原物料。
使用半成品做開發,也有助於加速開發時程。
找工程師及訓練也比MCU工程人員好找。

可以預見的是單板電腦進入MCU市場,只會加速工程師換代。
使用RTOS會是快速評比新舊工程師的有效方法。

2015年5月23日 星期六

MCU進入C++時代--個人觀點

MCU上使用C++並不是新事件。對Bee來說,只是何時?為何?
Bee很少使用C++,因為機會不多。連PC程式也都是用C寫的。
MCU開始使用SD卡,檔案系統出現後,PC/MCU程式開始不再分。
在使用GUI相關應用後,開始使用其他PC原始碼。
但常常可以找到的是C++程式碼。這種情況越來越多。
可以不用修改就在MCU執行PC程式,使用起來就像中毒一樣,因為實在太方便了。
沒多久就遇到要使用C++程式的問題。因為應用程式是c++寫的。

MCU目前仍以C為主,不管是驅動函式庫,RTOS,或是其他常用函式庫皆以C為主。
C++因為對記憶體需求高,另外經常調用動態記憶體。在記憶體不多的MCU上皆屬不合適使用的。
但現在MCU進展已很快了。不管是Cortex-A5系列的出現,或是支援Quad-SPI Flash的出現。
皆已解除應用程式容量問題。有了較大型應用程式出現,記憶體需求也提升。
SDRAM支援已是一般MCU擴充選項,所以對RAM的需求也沒有限制。

唯一的限制只剩下PC/MCU環境差異。RTOS及File system為MCU和PC最基本的需求。
在架好和PC相容環境後的MCU就可以直接使用PC原始碼。
再來就是遇到C++的應用程式。
因為底層系統仍是C,應用層則是C++,C/C++混合使用便是第一個要解決的。
就這樣,自然的在MCU上使用C++開始變成常態。

2015年3月16日 星期一

找質數程式2

改用快速開根

#include <stdio.h>

unsigned int test_number;

float SquareRootFloat(float number)
{
    long i;
    float x, y;
    const float f = 1.5F;

    x = number * 0.5F;
    y  = number;
    i  = * ( long * ) &y;
    i  = 0x5f3759df - ( i >> 1 );
    y  = * ( float * ) &i;
    y  = y * ( f - ( x * y * y ) );
    y  = y * ( f - ( x * y * y ) );
    return number * y;
}

unsigned int not_prime(unsigned int x)
{
    unsigned int q_x;
    unsigned int i;

    if ( !(x & 0x1) ) return 2;
    q_x = SquareRootFloat(x);
    for (i=3; i<=q_x; i+=2)
        if ( x % i == 0 ) return i;
    return 0;
}

void main()
{
    test_number = 0x73d58987;
    if ( test_number % 2 == 0 ) test_number--;
    while ( not_prime(test_number) )
        test_number -= 2;
    printf("%d\n", test_number);
}

2015年3月12日 星期四

找質數程式

找一個質數,做為通信檢查用。
#include <stdio.h>
#include <math.h>

unsigned int test_number;

unsigned int not_prime(unsigned int x)
{
    unsigned int q_t;
    unsigned int i;

    if ( !(x & 0x1) ) return 2;
    q_t = sqrt(x);
    for (i=3; i<=q_t; i+=2)
        if ( x % i == 0 ) return i;
    return 0;
}

void main()
{
    test_number = 0x80000000;
    if( test_number % 2 == 0 ) test_number--;
    while( not_prime(test_number) )
       test_number -= 2; 
    printf("%d\n", test_number);
}

2015年3月3日 星期二

Virtual Box內的XP使用USB-COM接線的方法

自己的PC裝置,其中COM1為標準裝置,可以直接轉到Virtual Box內使用。COM4為USB轉RS232線產生出來的Virtual COM。
 Virtual Box內的設定
設定好開機,可以用超級終端機連上就是成功。
但不一定每一台PC都可以。也許和晶片組相關。

2015年2月28日 星期六

STM32 I/O檢查程式

主要是利用xprintf函式做出一個命令式的I/O讀取及觸發程式。
方便電子設計初期的訊號及功能檢查。
xprintf的設計不錯用。只使用二個I/O函式,所以很容易移植。
利用callback方式,除了連接方便外,也可以中途移轉到另一組通道去。
只要使用xdev_in()及xdev_out()就可以掛載I/O函式了。
程式如下:

#include "xprintf.h"

unsigned short usart6_buf;
unsigned int usart6_rx_cnt =0;
void USART6_IRQHandler(void)
{
    if (USART_GetITStatus(USART6, USART_IT_RXNE) != RESET)
    {
        usart6_buf = USART_ReceiveData(USART6);
        usart6_rx_cnt++;
    }
}

unsigned char usart6_getc(void)
{
    static unsigned int usart6_rx_out = 0;

    /* Wait for Rx FIFO ready */
    while (usart6_rx_out == usart6_rx_cnt) vTaskDelay(1);
    usart6_rx_out++;
    return (usart6_buf & 0xFF);
}

void usart6_putc(unsigned char c)
{
//    while (USART_GetFlagStatus(USART6,USART_FLAG_TXE) == RESET) vTaskDelay(1);
    USART_SendData(USART6, c);
    vTaskDelayMs(1);
}

GPIO_TypeDef * const port[7] =
{
    GPIOA,
    GPIOB,
    GPIOC,
    GPIOD,
    GPIOE,
    GPIOF,
    GPIOG
};
unsigned short const pin[16] =
{
    GPIO_Pin_0,
    GPIO_Pin_1,
    GPIO_Pin_2,
    GPIO_Pin_3,
    GPIO_Pin_4,
    GPIO_Pin_5,
    GPIO_Pin_6,
    GPIO_Pin_7,
    GPIO_Pin_8,
    GPIO_Pin_9,
    GPIO_Pin_10,
    GPIO_Pin_11,
    GPIO_Pin_12,
    GPIO_Pin_13,
    GPIO_Pin_14,
    GPIO_Pin_15
};

char Line[256];                /* Console input buffer */

static void vParser_Task( void *pvParameters )
{
    char *ptr;
    long p1;
    long p2;
    GPIO_TypeDef*  GPIOx;
    unsigned short GPIO_Pin_y;

    (void) pvParameters;
    // set device
    USART6_Config();
    xdev_in(usart6_getc);
    xdev_out(usart6_putc);
    xputs("\nI/O test monitor for STM32F205 evaluation board.\n");
//    xprintf("LFN=%s, CP=%u\n", _USE_LFN ? "Enabled" : "Disabled", _CODE_PAGE);
    for ( ;; )
    {
        xputc('>');
        xgets(Line, sizeof Line);

        ptr = Line;
        switch (*ptr++)
        {
        case '?' :    /* Show Command List */
            xputs(HelpMsg);
            break;

        case 'r' :    // Read Input
            switch (*ptr++)
            {
            case 'a' :    // ra port
                GPIOx = port[0];
                break;
            case 'b' :    // rb port
                GPIOx = port[1];
                break;
            case 'c' :    // rc port
                GPIOx = port[2];
                break;
            case 'd' :    // rd port
                GPIOx = port[3];
                break;
            case 'e' :    // re port
                GPIOx = port[4];
                break;
            case 'f' :    // rf port
                GPIOx = port[5];
                break;
            case 'g' :    // rg port
                GPIOx = port[6];
                break;
            }
            if (!xatoi(&ptr, &p1)) break;
            GPIO_Pin_y = pin[p1];
            GPIO_ReadInputDataBit(GPIOx, GPIO_Pin_y);
            break;
        case 'w' :    // Write Output
            switch (*ptr++)
            {
            case 'a' :    // wa port data
                GPIOx = port[0];
                break;
            case 'b' :    // wb port data
                GPIOx = port[1];
                break;
            case 'c' :    // wc port data
                GPIOx = port[2];
                break;
            case 'd' :    // wd port data
                GPIOx = port[3];
                break;
            case 'e' :    // we port data
                GPIOx = port[4];
                break;
            case 'f' :    // wf port data
                GPIOx = port[5];
                break;
            case 'g' :    // wg port data
                GPIOx = port[6];
                break;
            }
            if (!xatoi(&ptr, &p1)) break;
            if (!xatoi(&ptr, &p2)) break;
            GPIO_Pin_y = pin[p1];
            if ( !p2 )
            {
                GPIO_ResetBits(GPIOx, GPIO_Pin_y);
            }
            else
            {
                GPIO_SetBits(GPIOx, GPIO_Pin_y);
            }
            break;
        }
        vTaskDelayMs(1);
    }
}

void main(void)
{
    void vUSART1_Task( void *pvParameters );

    GPIO_Config();

    xTaskCreate( vParser_Task,   ( signed char * ) "Parser", 512, NULL, tskIDLE_PRIORITY + 1, NULL );

    vTaskStartScheduler();
}

新筆電:GigaByte Q21

此筆電需求是輕、小。
所以從小筆電中找。
找到有雙碟支援,且可以支援8GB記憶體的只有一台=GigaByte Q21。
雙碟是為了安裝SSD所需,又需要HDD容量。
8GB RAM則是要使Win7-64可發揮效能的最低容量。
原始Q21是500G HDD以及2GB RAM,HDD容量還可以,RAM只有一槽,那只有換新了。
所以加購120GB SSD及8GB RAM,然後自己換。
Q21好拆的多,只要卸除背面5顆螺絲就好,沒有隱藏螺絲要找個半天。
再來從電池旁邊開始分開來,慢慢分,到背板全下來。
然後就安裝SSD及8G RAM上去。

再來安裝Win7的工就多了。本來是要保留Win8以SSD安裝Win7做為雙開機系統。
後來發現SSD無法做為開機用(後來發現可以),就安裝EasyBCD做為開機管理。
弄一個不對,Win8掛了(MBR破壞),一切完蛋。

沒想到一切重來竟是新開始。在HDD上重裝Win7,此時發現SSD是可以設定為開機的。
因為BIOS有Secure Boot,在安裝Win7時要取消,使得SSD可以改為開機碟。
但是安裝仍是不行,但還是裝上了Win7在HDD上。後來想了一下,就將HDD先拆掉,只留下SSD。果然可以安裝在SSD上。
在SSD裝好了Win7後再將HDD裝回來,終於完成了Bee想要的配置。不過多了HDD上的Win7,變成可以雙碟開機,那就當成是備用Win7。
接下來是安裝軟體,這個花了不少時間。再加上Win7的一堆升級,升級花了至少十小時。

系統安裝完畢,再來是資料搬家,從PC及NB要搬的檔案一堆,最不好搬的是ISO image檔。
用USB Disk又無法裝單檔大於4GB,除非將USB Disk重新Format成NTFS檔案系統。
用無線連網是沒有檔案大小問題,但傳輸不是很快,又怕干擾到家人使用,就動腦筋到沒有用的Ethernet接頭上。
使用網卡直接對連就可以解決問題,但如何做還是查了不少文。
主要是利用GigaEthernet可以自動換線功能,使用一般網路線就可以對接。
然後人工設定IP,將對方電腦IP設為閘道器。另一台電腦也一樣,然後就可以相互看到。
不過最好設定是工作場所網路,因為Win-XP無法使用家用網路,要從XP上傳資料還是設成工作場所網路。
這樣就解決了大檔案傳輸問題,搬資料也快多了。

弄好了小筆電,就比較一下效能差異,很驚訝的是小筆電效能和大筆電(4年前)的差不了太多。
因為現在CPU型號很多,其實也不好比較,還是找到網站去做比較,好用的是用CPUBoss去比。
可以看出來的確有可能效能差不多。舊筆電CPU是i3,為二核四緒,新筆電是N2930是省電四核。
N2930單一核心比i3的效能少了一半多,但4核總運算量剛好和i3總運算量相近,不過功耗低了很多。

用了一週後,竟發現120GB的SSD已經70%滿了。SSD在快滿時很容易掛掉,所以要找出原因。
做了檔案大小分析,pagefile.sys以及hiberfil.sys佔了很大的量。
pagefile.sys可以用設定虛擬記憶體方式移到HDD去。但hiberfil.sys沒有搬家的方法。
因為hiberfil.sys是休眠用的,以SSD快速開機的能力來說,效果差不多,就直接取消。
找到取消的方法,要用人工下命令的方式。
以系統管理員的身份叫用命令列,然後打powercfg -h off。然後重開機就沒有hiberfil.sys檔了。
但是做了SSD還是近65%滿,分析使用檔案大小只有30G,但使用了66G。
做了磁碟清理,磁碟重排也沒有用。
後來在磁碟清理中找到刪除還原點資料,一執行,釋放了30G以上的空間,系統使用空間降到32GB。
還原點的資料還無法看到,難怪不管分析檔案空間如何分析都不對,原來是還原點備份造成的。

2015年1月20日 星期二

S,Q值計算範例:濾波器

使用整數計算方式,順便記下一階濾波器程式

#define  K              0.01
#define  Q_K            16
#define  Const_Q_K      (int)(K*(1<<Q_K))
#define  K_MUL(x)       (((x)*Const_Q_K)>>Q_K)

#define  Q_ADC          8

#define  INT_Q(x,a)     ((x)<<( a))
#define  Q_INT(x,a)     ((x)>>( a))

_IO  ADC = 0x40001000;
extern int Read_IO(unsigned int address);

int ADC_IN()
{
     static int  Output; // Q_ADC variable
     int Last_Output;    // Q_ADC variable
    
     Last_Output = Output;
     Output += K_MUL(INT_Q(Read_IO(ADC),Q_ADC) - Output );
     if( Q_INT(Last_Output,Q_ADC) != Q_INT(Output,Q_ADC) ) TFT_string( Q_INT(Output,Q_ADC));
     return Q_INT(Output,Q_ADC);
}



2015年1月3日 星期六

Game Mechaninations新體認

Bee很早就看了第五項修練,這本書將控制理論推展到現實世界中。
提供了公司或是經濟系統的解釋。但只能解釋,無法有效了解。因為現實難以量化。
經過許多年,Bee在看Advanced Game Design發現Game Mechaninations這套圖形化語言。
這下總算可以將多年以來的困感解除了。
利用Game Mechaninations可以將第五項修練中的模型圖形化,再加上預估量化,就可以建造可解釋模型。
電腦語言確實可以將抽象理論現實化,並可以模擬。
這算是不同知識系統組合下的結果。

STM32 Quad-SPI Flash支援

STM32最近出了一系列支援Quad-SPI Flash。
Bee一開始不以為意,直到原廠人員特別強調時,才去看有何不同。
Quad-SPI Flash這個規格Bee早知道,但無MCU支援下,大概只有用FPGA才可以寫出來有效發揮的硬體。
不過在看完新的STM32 MCU規格後,發現果然原廠強調是有原因的。
因為Quad-SPI Flash在新MCU上可以支援程式執行。
新的MCU將quad-SPI Flash通信後,直接映射在Memory Space上,所以可以直接使用,包括執行。
這使得MCU外部擴充變得很方便,且讀取速度理論上最大可達40MB/sec,足以應付大部分外擴需求。
有了這項功能,可以將外掛資料及函式庫一起包在一起,提高程式部分升級的應用。

FIFO程式

使用在Verilog及MCU上用的。
在verilog中Buffer管理以2的指數為大小比較好管理。因為運算上方便,只需要用AND取得餘數。
在MCU上則是用在中斷及主程式之間的管理。
程式如下:

#define BUF_SIZE    0x8
#define SIZE_MASK   (BUF_SIZE-1)

int buffer[BUF_SIZE];

unsigned char fifo_wr_count, fifo_rd_count;

int fifo_reset(void)
{
    fifo_wr_count = 0;
    fifo_rd_count = 0;
    return -1;
}


int fifo_write(int data)
{
    unsigned int dist;

    dist = (unsigned char)(fifo_wr_count - fifo_rd_count);
    if ( dist >= BUF_SIZE)
    {
        return 0;
    }
    else
    {
        buffer[(fifo_wr_count&SIZE_MASK)] = data;
        fifo_wr_count++;
        return -1;
    }
}

int fifo_read(int *data)
{
    if ( fifo_rd_count == fifo_wr_count )
    {
        return 0;
    }
    else
    {
        *data = buffer[(fifo_rd_count&SIZE_MASK)];
        fifo_rd_count++;
        return -1;
    }
}