Author: jaguarondi
Date: 2008-08-14 18:31:42 +0200 (Thu, 14 Aug 2008)
New Revision: 1490

Modified:
   firmware/tuxaudio/branches/demo/PC_communication.c
   firmware/tuxaudio/branches/demo/communication.c
   firmware/tuxaudio/branches/demo/communication.h
   firmware/tuxaudio/branches/demo/flash.c
   firmware/tuxaudio/branches/demo/flash.h
   firmware/tuxaudio/branches/demo/main.c
   firmware/tuxaudio/branches/demo/parser.c
   firmware/tuxaudio/branches/demo/varis.c
   firmware/tuxaudio/branches/demo/varis.h
Log:
* Added recording of the sequence. Next step is playing it.


Modified: firmware/tuxaudio/branches/demo/PC_communication.c
===================================================================
--- firmware/tuxaudio/branches/demo/PC_communication.c  2008-08-14 12:23:17 UTC 
(rev 1489)
+++ firmware/tuxaudio/branches/demo/PC_communication.c  2008-08-14 16:31:42 UTC 
(rev 1490)
@@ -31,6 +31,7 @@
 
 void adapt_audio_rate(void);
 
+uint16_t static no_action;
 void spiTransaction(void)
 {
     if (spi_start)    // Wait start
@@ -127,28 +128,32 @@
                         spi_lenght_data = 34;
                     else
                         spi_lenght_data = 17;
-                    if (spi_master_config == 0x08 || spi_master_config == 0x00)
+                    /*if (spi_master_config == 0x08 || spi_master_config == 
0x00)*/
+                    /*{*/
+                        /*no_action ++;*/
+                    /*}*/
+                    if (spi_master_config == 0x00)
                     {
-                        if (frame_without_sound)
-                            frame_without_sound --;
-
-                        else
-                            sound_played = 0;
+                        no_action++;
                     }
                     else
                     {
-                        sound_played = 1;
-                        frame_without_sound = frame_without_sound_timeout;
+                        /* silence has a 8ms unit which is 32kHz divided by
+                         * 256 and 2ms (this frame rate) times 4 */
+                        uint16_t silence = no_action / 4;
+                        if (silence)
+                        {
+                            queue_core_cmd_p(WAIT_CMD, silence, silence >> 8, 
0);
+                        }
+                        no_action = 0;
                     }
-
                     spi_master = PUT_SOUND_FIFO;        // Go to the next state
                 }
                 else if (spi_master == PUT_SOUND_FIFO)
                 {
                     if (spi_master_config & 0x02)
                     {
-                        if (!flashPlay)
-                            FifoPut(PWMFifo, SPDR);       // Put into the FIFO
+                        FifoPut(PWMFifo, SPDR);       // Put into the FIFO
                     }
                     if (spi_count == (spi_lenght_data + 1))
                     {

Modified: firmware/tuxaudio/branches/demo/communication.c
===================================================================
--- firmware/tuxaudio/branches/demo/communication.c     2008-08-14 12:23:17 UTC 
(rev 1489)
+++ firmware/tuxaudio/branches/demo/communication.c     2008-08-14 16:31:42 UTC 
(rev 1490)
@@ -89,6 +89,28 @@
     return 1;
 }
 
+int8_t pop_core_cmd(uint8_t * cmd)
+{
+    uint8_t i;
+
+    if (FifoLength(core_cmdout))
+        /* Send commands received from RF or testers to tuxcore only. */
+    {
+        for (i = 0; i < CMD_SIZE; i++)
+        {
+            if (FifoGet(core_cmdout, &cmd[i]))
+                /* Drop the data if the fifo is corrupted (not enough
+                 * bytes) XXX add an error feedback on this */
+                return -1;
+        }
+    }
+    else
+        /* Nothing to do anymore */
+        return 0;
+
+    return 1;
+}
+
 /**
  * \brief Start an I2C read request to fetch one command from tuxcore.
  * If the rf stack is full, we return immediately.

Modified: firmware/tuxaudio/branches/demo/communication.h
===================================================================
--- firmware/tuxaudio/branches/demo/communication.h     2008-08-14 12:23:17 UTC 
(rev 1489)
+++ firmware/tuxaudio/branches/demo/communication.h     2008-08-14 16:31:42 UTC 
(rev 1490)
@@ -32,6 +32,7 @@
 int8_t queue_core_cmd(uint8_t *command);
 int8_t queue_core_cmd_p(uint8_t command, uint8_t param1, uint8_t param2, \
                      uint8_t param3);
+int8_t pop_core_cmd(uint8_t * cmd);
 int8_t queue_rf_cmd(uint8_t const *status);
 int8_t queue_rf_cmd_p(uint8_t cmd, uint8_t param1, uint8_t param2, \
                      uint8_t param3);

Modified: firmware/tuxaudio/branches/demo/flash.c
===================================================================
--- firmware/tuxaudio/branches/demo/flash.c     2008-08-14 12:23:17 UTC (rev 
1489)
+++ firmware/tuxaudio/branches/demo/flash.c     2008-08-14 16:31:42 UTC (rev 
1490)
@@ -31,65 +31,29 @@
 #include "common/api.h"
 
 /* Declarations */
-static void init_programming(uint8_t adi0, uint8_t adi1, uint8_t adi2);
-static void programming_sound(void);
+static void init_programming(uint8_t adi0, uint8_t adi1, uint8_t adi2, uint8_t 
data);
 static void playInit(uint8_t const nsound);
 static void playingSound(void);
 static void stopPlaying(void);
 
 uint8_t flash_state;
 uint8_t soundNum;
-static uint16_t index;
-static uint8_t sound_stored = 0;
 static uint8_t count, ad0, ad1;
-static uint8_t first_block;
 
 
 /**
  * \ingroup flash
-   \brief Read the number of sound in the flash memory.
-
-   This function scan the sound's indexes, and return the number of sound 
stored
-   in the flash memory.
+   \brief Check if the flash is programmed or not.
    */
 
-uint8_t readFlashNumber(void)
+uint8_t checkFlashState(void)
 {
-    uint8_t i;
-    ad0 = 0x01;
-    ad1 = 0x00;
-    count = 0;
-    while(1)
-    {
-        if (read_data(0x00, ad1, ad0) == 0xFF)
-        {
-            count --;
-            return count;
-        }
-        else
-        {
-            for (i = 0; i < 3; i++)
-            {
-                ad0 ++;
-                if (ad0 == 0)
-                    ad1++;
-            }
-        }
-        count ++;
-    }
-    return 0;
+    if (read_data(0x00, 0x00, 0x01) == 0xFF)
+        return 0;
+    else
+        return 1;
 }
 
-uint8_t readLastBlock(uint8_t num)
-{
-    index = (numSound * 3) + 1;
-    ad[0] = read_data(0x00, (index>>8), (index & 0xFF));
-    index ++;
-    ad[1] = read_data(0x00, (index>>8), (index & 0xFF));
-    index ++;
-    ad[2] = read_data(0x00, (index>>8), (index & 0xFF));
-    return (ad[0] << 4) + (ad[1] >> 4);
-}
 /**
  * \ingroup flash
    \brief Store a sound in the memory.
@@ -111,164 +75,80 @@
 
 */
 
+#define FLASH_CMD_SIZE 5
+#define FLASH_CMD 0x00
 void programming(void)
 {
-    uint8_t static programming_state = DETECT_INDEXES;
-    if (programming_state == DETECT_INDEXES)
-    {
-        TIMSK0 = 0x00;
-        //numSound = readFlashNumber();
-        if (numSound == 0)
-        {
-            /* The flash memory is empty. The first address is 0x000400 */
-            ad[0] = 0x00;
-            ad[1] = 0x04;
-            ad[2] = 0x00;
-            first_block = 0;
-        }
-        else
-        {
-            /* One or more sounds are programmed in the flash memory.
-             * The next sound must be stored after the others */
-            index = (numSound * 3) + 1;
-            ad[0] = read_data(0x00, (index>>8), (index & 0xFF));
-            index ++;
-            ad[1] = read_data(0x00, (index>>8), (index & 0xFF));
-            index ++;
-            ad[2] = read_data(0x00, (index>>8), (index & 0xFF));
+    uint8_t cmd[CMD_SIZE+1] = {FLASH_CMD};
 
-            // Goto the next 4kB block.
-            ad[1] += 0x10;
-            ad[1] &= ~0x0F;
-            if (ad[1] == 0)
-                ad[0] ++;
-            ad[2] = 0;
-            first_block = (ad[0] << 4) + (ad[1] >> 4);
-        }
-        FifoClear(PWMFifo);
-
-        if (ad[0] > 0x07)
-        {
-            programming_state = PROG_END;
-            queue_rf_cmd_p(STATUS_FLASH_PROG_CMD, FLASH_FULL, 0, 0);
-        }
-        else
-            programming_state ++;
-
-        frame_without_sound = 5000;
-        frame_without_sound_timeout = 5000;
-        queue_rf_cmd_p(STATUS_FLASH_PROG_CMD, IN_PROGRESS, ad[0], ad[1]);
-    }
-
-    else if (programming_state == PROG_INIT)
+    if (flashPlay || (ad[0] == 0x07 && ad[1] == 0xFF))
+        /* Last block of the flash, stop here */
     {
-        init_programming(ad[0], ad[1], ad[2]);
-        programming_state ++;
-        flash_state = 1;
-        sound_stored = 0;
+        /* XXX write the end of sequence command at the end of the flash */
+        queue_rf_cmd_p(STATUS_FLASH_PROG_CMD, FLASH_FULL, 1, 0);
+        queue_rf_cmd_p(STATUS_FLASH_PROG_CMD, ad[0], ad[1], ad[2]);
+        programmingFlash = 0;
+        flashPlay = 1;
+        return;
     }
-    else if (programming_state == PROGRAMMING)
-    {
-        if (flash_state)
-            programming_sound();
 
-        else
+    /* Store commands in flash */
+    while (pop_core_cmd(&cmd[1]))
+    {
+        uint8_t i;
+        for (i=0; i<CMD_SIZE+1; i++)
         {
-            write_disable();
-            if (sound_stored)
+            flash_select();
+            spiSend(SEQU_PROGRAM);
+            spiSend(cmd[i]);
+            flash_unselect();
+
+            ad[2] ++;
+            if (ad[2] == 0x00)
             {
-                last_block = (ad[0] << 4) + (ad[1] >> 4);
-                queue_rf_cmd_p(STATUS_FLASH_PROG_CMD, 
WAITING_FOR_CONFIRMATION, last_block - first_block, 0);
-                programming_state ++;
+                ad[1]++;
+                if (ad[1] == 0x00)
+                    ad[0]++;
             }
-            else
-            {
-                queue_rf_cmd_p(STATUS_FLASH_PROG_CMD, NO_SOUND, 0, 0);
-                programming_state = PROG_END;
-            }
+            while (read_status() & BUSY) ;
         }
+        queue_rf_cmd_p(STATUS_FLASH_PROG_CMD, cmd[1], cmd[2], cmd[3]);
     }
-    else if (programming_state == WAITING_STATE)
+
+    /* Store sound in flash */
+    while (!spi_start)
     {
-        if (write_toc == 1)
+        if (FifoLength(PWMFifo))
         {
-            programming_state = PROG_TOC;
-        }
-        else if (write_toc == 2)
-        {
-            queue_rf_cmd_p(STATUS_FLASH_PROG_CMD, ERASING_LAST_SOUND, 0, 0);
-            if (first_block == 0)
+            uint8_t data;
+            flash_select();
+            spiSend(SEQU_PROGRAM);
+            FifoGet(PWMFifo, &data);
+            /* Sound value can't be equal to FLASH_CMD */
+            if (data == FLASH_CMD)
+                data++;
+            spiSend(data);
+            flash_unselect();
+
+            ad[2] ++;
+            if (ad[2] == 0x00)
             {
-                eraseFlag = 1;
-                frame_without_sound_timeout = TTS_TIMEOUT;
-                programming_state = 0;
-                programmingFlash = 0;
+                ad[1]++;
+                if (ad[1] == 0x00)
+                    ad[0]++;
             }
-            else
-            {
-                last_block = (ad[0] << 4) + (ad[1] >> 4);
-                blockErase(first_block, last_block);
-                programming_state = PROG_END;
-            }
+            while (read_status() & BUSY) ;
         }
-        write_toc = 0;
+        else
+            break;
+
+        if (ad[0] == 0x07 && ad[1] == 0xFF)
+            break;
     }
-    else if (programming_state == PROG_TOC)
-    {
-        queue_rf_cmd_p(STATUS_FLASH_PROG_CMD, WRITE_TOC, 0, 0);
-        numSound ++;
-        index = (numSound * 3) + 1;
-        program_flash(0x00, (index>>8), (index & 0xFF), ad[0]);
-        index ++;
-        program_flash(0x00, (index>>8), (index & 0xFF), ad[1]);
-        index ++;
-        program_flash(0x00, (index>>8), (index & 0xFF), ad[2]);
-        last_block = (ad[0] << 4) + (ad[1] >> 4);
-        programming_state ++;
-    }
-    else if (programming_state == PROG_END)
-    {
-        numSound = readFlashNumber();
-        frame_without_sound_timeout = TTS_TIMEOUT;
-        programming_state = 0;
-        programmingFlash = 0;
-        TIMSK0 = 0x01;
-        queue_rf_cmd_p(STATUS_FLASH_PROG_CMD, STANDBY, 0, 0);
-        queue_rf_cmd_p(SOUND_VAR_CMD, numSound, last_block, 0);
-    }
 }
 
 /**
  * \ingroup flash
- * \brief Active the deep power-down mode
- *
- * This mode active the deep-power mode. The consumption will pass to 8mA from
- * 20uA.
- */
-void enter_deep_sleep(void)
-{
-    flash_enable();
-    flash_select();
-    spiSend(DEEP_POWER_MODE);
-    flash_unselect();
-}
-
-/**
- * \ingroup flash
- * \brief Leave the deep power_down mode
- *
- * This function will resume the flash memory from the deep power-down mode.
- */
-void leave_deep_sleep(void)
-{
-    flash_enable();
-    flash_select();
-    spiSend(RESUME_DEEP_MODE);
-    flash_unselect();
-}
-
-/**
- * \ingroup flash
    \brief Erase the flash memory.
 
     The first step is to send the command to erase the flash.
@@ -280,23 +160,23 @@
     uint8_t static enter = 1;
     if (enter)
     {
+        TIMSK0 = 0x00;
+        queue_rf_cmd_p(STATUS_FLASH_PROG_CMD, IN_PROGRESS, 0, 0);
         erase_flash();
         enter = 0;
     }
     else if (!(read_status() & BUSY))
     {
-        //queue_rf_cmd_p(STATUS_FLASH_PROG_CMD, STANDBY, 0, 0);
         enter = 1;
         eraseFlag = 0;
-        program_flash(0x00, 0x00, 0x00, 0xFE);
-        program_flash(0x00, 0x00, 0x01, 0x00);
-        program_flash(0x00, 0x00, 0x02, 0x04);
-        program_flash(0x00, 0x00, 0x03, 0x00);
-        numSound = 0;
-        last_block = 0;
         queue_rf_cmd_p(STATUS_FLASH_PROG_CMD, STANDBY, 0, 0);
-        queue_rf_cmd_p(SOUND_VAR_CMD, numSound, last_block, 0);
         TIMSK0 = 0x01;
+        FifoClear(PWMFifo);
+        /* Initialize the flash address */
+        init_programming(0, 0, 0, 0);
+        ad[0] = 0x00;
+        ad[1] = 0x00;
+        ad[2] = 0x01;
     }
 }
 
@@ -514,83 +394,14 @@
 
    This function perform the first step.
     */
-static void init_programming(uint8_t adi0, uint8_t adi1, uint8_t adi2)
+static void init_programming(uint8_t adi0, uint8_t adi1, uint8_t adi2, uint8_t 
data)
 {
-    uint8_t data;
     write_enable();
     flash_select();
     spiSend(SEQU_PROGRAM);
     spiSend(adi0);
     spiSend(adi1);
     spiSend(adi2);
-    if (FifoGet(PWMFifo, &data) == FIFO_OK)
-        spiSend(data);
-    else
-        spiSend(0x80);
-
+    spiSend(data);
     flash_unselect();              // Chip Deselect
 }
-
-
-/**
- * \ingroup flash
-   \brief Program the sound's data into the flash memory
-
-    This function is executed while the SPI start command is not present.  Each
-    cycle, one byte is popped from the PWM fifo and stored in the sound flash.
-
-    The frame_without_sound variable is decremented each time the RF receive a
-    frame without sound.  When this variable is null, the sound process is
-    stopped.
-
-    If a programming sequence starts, but no sound is received, the cycle is
-    stopped.
-
-    If the address is equal to 0x07FFFF (the last memory address), the 
programming
-    cycle is stopped.
-
-    The sound_stored flag is set when at least one byte is stored in the 
memory.
-    Else, this variable is null.
- */
-
-static void programming_sound(void)
-{
-    while (!spi_start)
-    {
-        if (FifoLength(PWMFifo))
-        {
-            uint8_t data;
-            sound_stored = 1;
-            frame_without_sound = STOP_FRAME_NUMBER;
-            frame_without_sound_timeout = STOP_FRAME_NUMBER;
-
-            flash_select();
-            spiSend(SEQU_PROGRAM);
-            FifoGet(PWMFifo, &data);
-            spiSend(data);
-            flash_unselect();
-
-            ad[2] ++;
-            if (ad[2] == 0x00)
-            {
-                ad[1]++;
-                if (ad[1] == 0x00)
-                    ad[0]++;
-            }
-            while (read_status() & BUSY) ;
-        }
-
-        /* Check for the last sound byte */
-        if (!(frame_without_sound))
-        {
-            flash_state = 0;
-            break;
-        }
-        if (ad[0] == 0x07 && ad[1] == 0xFF && ad[2] == 0xFF)
-        {
-            flash_state = 0;
-            break;
-        }
-    }
-}
-

Modified: firmware/tuxaudio/branches/demo/flash.h
===================================================================
--- firmware/tuxaudio/branches/demo/flash.h     2008-08-14 12:23:17 UTC (rev 
1489)
+++ firmware/tuxaudio/branches/demo/flash.h     2008-08-14 16:31:42 UTC (rev 
1490)
@@ -71,7 +71,7 @@
 extern void programming(void);
 extern void playSound(void);
 extern void erase(void);
-extern uint8_t readFlashNumber(void);
+extern uint8_t checkFlashState(void);
 extern uint8_t readLastBlock(uint8_t num);
 extern void enter_deep_sleep(void);
 extern void leave_deep_sleep(void);

Modified: firmware/tuxaudio/branches/demo/main.c
===================================================================
--- firmware/tuxaudio/branches/demo/main.c      2008-08-14 12:23:17 UTC (rev 
1489)
+++ firmware/tuxaudio/branches/demo/main.c      2008-08-14 16:31:42 UTC (rev 
1490)
@@ -78,7 +78,6 @@
 
     pre_sleep_delay = 0;
     /* Set power savings configuration. */
-    enter_deep_sleep();
     cli();
     PORTB = 0x80;
     PORTC = 0x08;
@@ -107,7 +106,6 @@
     init_avr();
     initCommunicationBuffers();
     communication_init();
-    leave_deep_sleep();
 }
 
 /**
@@ -125,11 +123,8 @@
     if (RF_ONLINE_PIN & RF_ONLINE_MK)
         command[1] |= 0x20;
     command[1] ^= 0x9B;         /* some bits should be inverted */
-    command[2] = soundToPlay;
-    if (soundToPlay || sound_played)
-        command[3] = 1;
-    else
-        command[3] = 0;
+    command[2] = 0;
+    command[3] = 0;
     queue_core_cmd(command);      /* push the command set on the filo stack */
 }
 
@@ -140,10 +135,8 @@
     FifoClear(PWMFifo);        /* Initialise the PWM fifo */
     FifoClear(ADCFifo);        /* Initialise the ADC fifo */
     config_init();              /* load the configuration defaults from EEPROM 
*/
-    numSound = readFlashNumber();
-    last_block = readLastBlock(numSound);
+    flashPlay = checkFlashState();
     communication_init();     /* I2C initialization */
-    frame_without_sound_timeout = TTS_TIMEOUT;
 
     sei();                      /* Init global interrupt */
 
@@ -171,23 +164,26 @@
                 queue_core_cmd(spi_commandRX);
         }
 
-        if (programmingFlash)   // Restora all the context for flash 
programming
-            programming();
-
-        if (flashPlay)
-            playSound();
-
         if (eraseFlag)
             erase();
+        else if (programmingFlash)
+            programming();
+        else
+        {
+            /* Send commands to I2C, otherwise get new status from tuxcore */
+            communication_task();
 
-        /* Send commands to I2C, otherwise get new status from tuxcore */
-        communication_task();
+            if (flashPlay)
+                playSound();
+        }
+
             /*else if (sleep_f)*/
             /*{*/
                 /*sleep_f = 0;*/
                 /*sleep();*/
             /*}*/
 
+#if 0 // we don't need status in this firmware
         if (sendSensorsFlag)
         {
             sendSensorsFlag = 0;
@@ -199,11 +195,6 @@
              * stopped at this time */
             else
                 sendSensors();
-            /* wait for all status to be sent before going to sleep */
-            /* TODO fix these conditions for the sleep */
-            //if (isFifoEmpty(rf_cmdout_buf))
-            /* wait for audio commands to be processed */
-            //if (!audioBufIdx && !flashPlay)
 
             /* Delay used to power the IR receiver slowly */
             if (power_on_reset_delay)
@@ -222,6 +213,7 @@
                     DDRD &= ~0x03;
             }
         }
+#endif
 
         /* Sleep mode */
         if (pre_sleep_delay == 1)

Modified: firmware/tuxaudio/branches/demo/parser.c
===================================================================
--- firmware/tuxaudio/branches/demo/parser.c    2008-08-14 12:23:17 UTC (rev 
1489)
+++ firmware/tuxaudio/branches/demo/parser.c    2008-08-14 16:31:42 UTC (rev 
1490)
@@ -55,14 +55,7 @@
         /* param: cmd[1] : sound number */
         /* cmd[2] : mic sound intensity  */
     {
-        /* Drop the cmd if a sound is already playing */
-        if (!(flashPlay || programmingFlash))
-        {
-            audioLevel = cmd[2];
-            soundToPlay = cmd[1];
-            flashPlay = 1;
-            flash_state = 1;
-        }
+        /* Drop the cmd in this firmware */
     }
     else if (cmd[0] == MUTE_CMD)
     {
@@ -73,21 +66,20 @@
     }
     else if (cmd[0] == STORE_SOUND_CMD)
     {
-        if (flashPlay)
-            flashPlay = 0;
+        flashPlay = 0;
         flash_state = 1; /* Erasing flash flag */
         programmingFlash = 1; /* Set the flag to enter programming sequence */
+        queue_rf_cmd_p(STATUS_FLASH_PROG_CMD, IN_PROGRESS, 1, 0);
+        initCommunicationBuffers();
     }
     else if (cmd[0] == ERASE_FLASH_CMD)
     {
+        flashPlay = 0;
         eraseFlag = 1;
     }
     else if (cmd[0] == CONFIRM_STORAGE_CMD)
     {
-        if (cmd[1])
-            write_toc = 1;
-        else
-            write_toc = 2;
+        flashPlay = 1;
     }
     else
     {

Modified: firmware/tuxaudio/branches/demo/varis.c
===================================================================
--- firmware/tuxaudio/branches/demo/varis.c     2008-08-14 12:23:17 UTC (rev 
1489)
+++ firmware/tuxaudio/branches/demo/varis.c     2008-08-14 16:31:42 UTC (rev 
1490)
@@ -56,7 +56,7 @@
 volatile uint8_t numSound;
 
 // Flash Variables
-volatile unsigned char flashPlay = 0;
+unsigned char flashPlay = 0;
 volatile unsigned char ad[6];
 volatile unsigned char audioLevel;
 uint8_t soundToPlay;
@@ -67,8 +67,6 @@
 
 volatile unsigned char spiCommandFlasg = 0;
 
-uint16_t frame_without_sound = 0;
-uint16_t frame_without_sound_timeout= 0;
 uint8_t sound_played = 0;
 uint8_t last_block = 0;
 

Modified: firmware/tuxaudio/branches/demo/varis.h
===================================================================
--- firmware/tuxaudio/branches/demo/varis.h     2008-08-14 12:23:17 UTC (rev 
1489)
+++ firmware/tuxaudio/branches/demo/varis.h     2008-08-14 16:31:42 UTC (rev 
1490)
@@ -78,8 +78,6 @@
 
 extern volatile unsigned char spiCommandFlasg;
 
-extern uint16_t frame_without_sound;
-extern uint16_t frame_without_sound_timeout;
 extern uint8_t sound_played;
 extern uint8_t last_block;
 


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Tux-droid-svn mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/tux-droid-svn

Reply via email to