/*!
 * \brief Send Ethernet packet.
 *
 * \param dev   Identifies the device to use.
 * \param nb    Network buffer structure containing the packet to be sent.
 *              The structure must have been allocated by a previous
 *              call NutNetBufAlloc().
 *
 * \return 0 on success, -1 in case of any errors.
 */
int LancOutput(NUTDEVICE * dev, NETBUF * nb)
{
    static uint32_t mx_wait = 5000;
    int rc = -1;
    lanc111_nic_t *ni;

    /*
     * After initialization we are waiting for a long time to give
     * the PHY a chance to establish an Ethernet link.
     */
    if (NutEventWait(&nic->ni_tx_rdy, mx_wait) == 0) {
        ni = (lanc111_nic_t *) dev->dev_dcb;

        if (NicPutPacket(nb) == 0) {
            ni->ni_tx_packets++;
            rc = 0;
            /* Ethernet works. Set a long waiting time in case we
               temporarly lose the link next time. */
            mx_wait = 5000;
        }
        NutEventPost(&nic->ni_tx_rdy);
    }
    /*
     * Probably no Ethernet link. Significantly reduce the waiting
     * time, so following transmission will soon return an error.
     */
    else {
        mx_wait = 500;
    }
    return rc;
}
/*!
 * \brief Read or verify a single block.
 *
 * \param ifc Specifies the hardware interface.
 * \param blk Block number to read or verify.
 * \param buf Data buffer. Receives the data or is verified against the
 *            data being read from the card.
 *
 * \return 0 on success, -1 otherwise.
 */
static int At91MciReadSingle(MCIFC * ifc, u_long blk, u_char * buf)
{
    int rc = -1;
    u_int sr;

    /* Gain mutex access. */
    NutEventWait(&mutex, 0);

#ifdef NUTDEBUG
    printf("[RB%lu]", blk);
#endif

    sr = At91MciTxCmd(ifc, MCI_MAXLAT | MCI_RSPTYP_48 | MMCMD_SELECT_CARD, ifc->ifc_reladdr << 16);
    if ((sr & 0xC07F0000) == 0) {
        sr = At91MciTxCmd(ifc, MCI_MAXLAT | MCI_RSPTYP_48 | MMCMD_SET_BLOCKLEN, MMC_BLOCK_SIZE);
        if ((sr & 0xC07F0000) == 0) {
            ifc->ifc_buff = buf;
            sr = At91MciTxCmd(ifc, MCI_TRDIR | MCI_TRCMD_START | MCI_MAXLAT | MCI_RSPTYP_48 |
                              MMCMD_READ_SINGLE_BLOCK, blk * MMC_BLOCK_SIZE);
            if ((sr & 0xC07F0000) == 0) {
                rc = 0;
            }
        }
        At91MciTxCmd(ifc, MMCMD_SELECT_CARD, 0);
    }

    /* Release mutex access. */
    NutEventPost(&mutex);

    return rc;
}
Beispiel #3
0
/*! \brief Select a device on the first SPI bus.
 *
 * Locks and activates the bus for the specified node.
 *
 * \param node Specifies the SPI bus node.
 * \param tmo  Timeout in milliseconds. To disable timeout, set this
 *             parameter to NUT_WAIT_INFINITE.
 *
 * \return 0 on success. In case of an error, -1 is returned and the bus 
 *         is not locked.
 */
int NplSpiBusSelect(NUTSPINODE * node, uint32_t tmo)
{
    int rc;

    /* Sanity check. */
    NUTASSERT(node != NULL);
    NUTASSERT(node->node_bus != NULL);

    /* Allocate the bus. */
    rc = NutEventWait(&node->node_bus->bus_mutex, tmo);
    if (rc) {
        errno = EIO;
    } else {
        /* If the mode update bit is set, then update our shadow registers. */
        if (node->node_mode & SPI_MODE_UPDATE) {
            NplSpiSetup(node);
        }

        /* Finally activate the node's chip select. */
        rc = NplSpiChipSelect(node->node_cs, 0);
        if (rc) {
            /* Release the bus in case of an error. */
            NutEventPost(&node->node_bus->bus_mutex);
        }
    }
    return rc;
}
Beispiel #4
0
/*! 
 * \brief Wait until all SPI bus transfers are done.
 *
 * \param node Specifies the SPI bus node.
 * \param tmo  Timeout in milliseconds. To disable timeout, set this
 *             parameter to NUT_WAIT_INFINITE.
 *
 * \return Always 0.
 */
int At91SpiBusWait(NUTSPINODE * node, uint32_t tmo)
{
    while ((inr(node->node_bus->bus_base + SPI_SR_OFF) & SPI_RXBUFF) == 0) {
        if (NutEventWait(&node->node_bus->bus_ready, tmo)) {
            return -1;
        }
    }
    return 0;
}
Beispiel #5
0
/*! 
 * \brief Transfer data on the SPI bus using double buffered PDC.
 *
 * A device must have been selected by calling At91SpiSelect().
 *
 * \todo Not yet done. Given up after SAM7SE SDRAM problems.
 *       Currently working fine on SAM7X platform
 * \todo Is this working asynchronously? Old comments mentioned that 
 *       the transfer might be still active when function returns.
 *
 * \param node Specifies the SPI bus node.
 * \param txbuf Pointer to the transmit buffer. If NULL, undetermined
 *              byte values are transmitted.
 * \param rxbuf Pointer to the receive buffer. If NULL, then incoming
 *              data is discarded.
 * \param xlen  Number of bytes to transfer.
 *
 * \return Always 0.
 */
int At91SpiBusDblBufTransfer(NUTSPINODE * node, CONST void *txbuf, void *rxbuf, int xlen)
{
    uintptr_t base;
    uint32_t cr;
    uint32_t ir = 0;

#if defined(SPIBUS0_DOUBLE_BUFFER_HEURISTIC) || defined(SPIBUS1_DOUBLE_BUFFER_HEURISTIC)
    if (xlen < SPI_DOUBLE_BUFFER_MIN_TRANSFER_SIZE) {
        return At91SpiBusPollTransfer(node, txbuf, rxbuf, xlen);
    }
#endif

    /* Sanity check. */
    NUTASSERT(node != NULL);
    NUTASSERT(node->node_bus != NULL);
    NUTASSERT(node->node_bus->bus_base != 0);
    base = node->node_bus->bus_base;

    outr(base + PERIPH_PTCR_OFF, PDC_TXTDIS | PDC_RXTDIS);

    if (xlen) {
        /* Set first transmit pointer and counter. */
        if (txbuf) {
            outr(base + PERIPH_TPR_OFF, (uint32_t)txbuf);
        } else {
            outr(base + PERIPH_TPR_OFF, (uint32_t)rxbuf);
        }
        cr = PDC_TXTEN;
        outr(base + PERIPH_TCR_OFF, xlen);
        /* Set first receive pointer and counter. */
        if (rxbuf) {
            outr(base + PERIPH_RPR_OFF, (uint32_t)rxbuf);
            outr(base + PERIPH_RCR_OFF, xlen);
            cr |= PDC_RXTEN;
            ir = SPI_RXBUFF;
        } else {
            cr |= PDC_RXTDIS;
            ir = SPI_TXBUFE;
            outr(base + PERIPH_RPR_OFF, 0);
            outr(base + PERIPH_RCR_OFF, 0);
        }
        outr(base + PERIPH_TNPR_OFF, 0);
        outr(base + PERIPH_TNCR_OFF, 0);
        outr(base + PERIPH_RNPR_OFF, 0);
        outr(base + PERIPH_RNCR_OFF, 0);

        outr(base + SPI_IDR_OFF, (unsigned int) - 1);
        outr(base + SPI_IER_OFF, ir);
        outr(base + PERIPH_PTCR_OFF, cr);
        
        NutEventWait(&node->node_bus->bus_ready, NUT_WAIT_INFINITE);
        outr(base + PERIPH_PTCR_OFF, PDC_TXTDIS | PDC_RXTDIS);
    }
    return 0;
}
/*
 * Background thread for playing stream.
 */
THREAD(Displayer, arg)
{
    u_int step[2] = { 0, 0 };
    u_int stepmx[2] = { 0, 0 };
    char *line;
    char *sptr = 0;
    u_char scrolling = DISPLAY_LINES;
    u_char ln;

    fputs(ESC_CURSOROFF, lcd);
    NutThreadSetPriority(128);
    for (;;) {
        NutEventWait(&updevt, 125);

        for (ln = 0; ln < DISPLAY_LINES; ln++) {
            if (mticks[ln]) {
                line = mline[ln];
                mticks[ln]--;
            } else
                line = sline[ln];
            if (stepmx[ln] != strlen(line)) {
                sptr = 0;
                scrolling = DISPLAY_LINES;
                stepmx[ln] = strlen(line);
                step[ln] = 0;
            }
            fprintf(lcd, ESC_POS "%c" "\x20", ln + 32);
            if (stepmx[ln] <= 16) {
                fputs(line, lcd);
                if (stepmx[ln] < 16)
                    fputs(ESC_CLREOL, lcd);
            } else {
                if (step[ln] == stepmx[ln]) {
                    if (scrolling == DISPLAY_LINES)
                        scrolling = ln;
                    if (scrolling == ln) {
                        if (sptr == 0)
                            sptr = line;
                        else {
                            sptr++;
                            if (strlen(sptr) <= 16)
                                step[ln]++;
                        }
                        fprintf(lcd, "%.16s", sptr);
                    }
                } else if (step[ln]++ == 0) {
                    fprintf(lcd, "%.16s", line);
                    sptr = 0;
                    scrolling = DISPLAY_LINES;
                } else if (step[ln] >= stepmx[ln] + 16)
                    step[ln] = 0;
            }
        }
    }
}
/*!
 * \brief Listen for incoming data from a master.
 *
 * If this function returns without error, the bus is blocked. The caller
 * must immediately process the request and return a response by calling
 * TwSlaveRespond().
 *
 * \note This function is only available on ATmega128 systems. The
 *       function is not reentrant.
 *
 * \param sla    Points to a byte variable, which receives the slave
 *               address sent by the master. This can be used by the
 *               caller to determine whether the the interface has been
 *               addressed by a general call or its individual address.
 * \param rxdata Points to a data buffer where the received data bytes
 *               are stored.
 * \param rxsiz  Specifies the maximum number of data bytes to receive.
 * \param tmo	 Timeout in milliseconds. To disable timeout,
 *               set this parameter to NUT_WAIT_INFINITE.
 *
 * \return The number of bytes received, -1 in case of an error or timeout.
 */
int TwSlaveListen(u_char * sla, void *rxdata, u_short rxsiz, u_long tmo)
{
#ifndef __AVR_ENHANCED__
    return -1;
#else
    int rc = -1;

    NutEnterCritical();

    /* Initialize parameters for slave receive. */
    tw_sm_err = 0;
    tw_sr_siz = rxsiz;
    tw_sr_buf = rxdata;

    /*
     * If the interface is currently not busy then enable it for
     * address recognition.
     */
    if(tw_if_bsy == 0) {
        u_char twsr = inb(TWSR);
        if((twsr & 0xF8) == TW_NO_INFO) {
            if(tw_mt_len || tw_mr_siz)
                outb(TWCR, _BV(TWEA) | _BV(TWEN) | _BV(TWIE) | _BV(TWSTA));
            else
                outb(TWCR, _BV(TWEA) | _BV(TWEN) | _BV(TWIE));
        }
    }

    /* Clear the queue. */
    //*broken?! NutEventBroadcastAsync(&tw_sr_que);
    if (tw_sr_que == SIGNALED) {
        tw_sr_que = 0;
    }

    /* Wait for a frame on the slave mode queue. */
    if (NutEventWait(&tw_sr_que, tmo)) {
        NutEnterCritical();
        tw_sm_err = TWERR_TIMEOUT;
        tw_sr_siz = 0;
        NutExitCritical();
    }
    NutExitCritical();

    /*
     * Return the number of bytes received and the destination slave
     * address, if no slave error occured. In this case the bus is
     * blocked.
     */
    if(tw_sm_err == 0) {
        rc = tw_sr_idx;
        *sla = tw_sm_sla;
    }
    return rc;
#endif /* __AVR_ENHANCED__ */
}
Beispiel #8
0
/*!
 * \brief Transmit and/or receive data as a master.
 *
 * The two-wire serial interface must have been initialized by calling
 * TwInit() before this function can be used.
 *
 * \param sla    Slave address of the destination. This slave address
 *               must be specified as a 7-bit address. For example, the
 *               PCF8574A may be configured to slave addresses from 0x38
 *               to 0x3F.
 * \param txdata Points to the data to transmit. Ignored, if the number
 *               of data bytes to transmit is zero.
 * \param txlen  Number of data bytes to transmit. If zero, then the
 *               interface will not send any data to the slave device
 *               and will directly enter the master receive mode.
 * \param rxdata Points to a buffer, where the received data will be
 *               stored. Ignored, if the maximum number of bytes to
 *               receive is zero.
 * \param rxsiz  Maximum number of bytes to receive. Set to zero, if
 *               no bytes are expected from the slave device.
 * \param tmo    Timeout in milliseconds. To disable timeout, set this
 *               parameter to NUT_WAIT_INFINITE.
 *
 * \return The number of bytes received, -1 in case of an error or timeout.
 *
 * \note Timeout is not used in the bit banging version.
 */
int NutTwiMasterTranceive(NUTTWIBUS *bus, uint8_t sla, const void *txdata, uint16_t txlen, void *rxdata, uint16_t rxsiz, uint32_t tmo)

{
    int rc = 0;
    uint8_t *cp;
    NUTTWIICB *icb = bus->bus_icb;

    if (!twibb_initialized) {
        TwInit(0);
    }

    /* This routine is marked reentrant, so lock the interface. */
    if (NutEventWait(&bus->bus_mutex, tmo)) {
        icb->tw_mm_error = TWERR_IF_LOCKED;
        return -1;
    }

    TwStart();
    /* Send SLA+W and check for ACK. */
    if ((rc = TwPut(sla << 1)) == 0) {
        for (cp = (uint8_t *)txdata; txlen--; cp++) {
            if ((rc = TwPut(*cp)) != 0) {
                break;
            }
        }
    }
    if (rc == 0 && rxsiz) {
        TwStart();
        /* Send SLA+R and check for ACK. */
        if ((rc = TwPut((sla << 1) | 1)) == 0) {
            for (cp = rxdata;; cp++) {
                *cp = TwGet();
                if (++rc >= rxsiz) {
                    break;
                }
                TwAck();
            }
        }
    }
    TwStop();

    if (rc == -1) {
        icb->tw_mm_error = TWERR_SLA_NACK;
    }

    /* Release the interface. */
    NutEventPost(&bus->bus_mutex);

    return rc;
}
/*!
 * \brief Configure a network interface including the default gateway.
 *
 * Devices must have been registered by NutRegisterDevice() before
 * calling this function.
 *
 * For Ethernet devices applications may alternatively call
 * NutDhcpIfConfig(), which allows automatic configuration by DHCP or
 * the so called ARP method.
 *
 * \param name    Name of the device to configure.
 * \param params  Pointer to interface specific parameters.
 * \param ip_addr Specified IP address in network byte order. This must
 *                be a unique address within the Internet. If you do not
 *                directly communicate with other Internet hosts, you can
 *                use a locally assigned address. With PPP interfaces this
 *                may be set to 0.0.0.0, in which case the remote peer
 *                will be queried for an IP address.
 * \param ip_mask Specified IP network mask in network byte order.
 *                Typical Ethernet networks use 255.255.255.0, which
 *                allows upto 254 hosts. For PPP interfaces 255.255.255.255
 *                is the default.
 * \param gateway Specified IP address of gateway or next router in LAN.
 *
 * \return 0 on success, -1 otherwise.
 *
 * \note I do not like this function, because setting a gateway should
 *       be handled by NutIpRouteAdd(). It's not yet deprecated, but I
 *       recommend not to use it in application code.
 */
int NutNetIfConfig2(CONST char *name, void *params, u_long ip_addr, u_long ip_mask, u_long gateway)
{
    NUTDEVICE *dev;
    IFNET *nif;

    /*
     * Check if this is a registered network device.
     */
    if ((dev = NutDeviceLookup(name)) == 0 || dev->dev_type != IFTYP_NET)
        return -1;

    /*
     * Setup Ethernet interfaces.
     */
    nif = dev->dev_icb;
    if (nif->if_type == IFT_ETHER) {
        memcpy(nif->if_mac, params, sizeof(nif->if_mac));
        return NutNetIfSetup(dev, ip_addr, ip_mask, gateway);
    }

    /*
     * Setup PPP interfaces.
     */
    else if (nif->if_type == IFT_PPP) {
        PPPDCB *dcb = dev->dev_dcb;

        /*
         * Set the interface's IP address, make sure that the state
         * change queue is empty and switch hardware driver into
         * network mode.
         */
        dcb->dcb_local_ip = ip_addr;
        dcb->dcb_ip_mask = ip_mask ? ip_mask : 0xffffffff;
        NutEventBroadcast(&dcb->dcb_state_chg);
        _ioctl(dcb->dcb_fd, HDLC_SETIFNET, &dev);

        /* Ugly hack to get simple UART drivers working. */
        ppp_hackup = 1;

        /*
         * Wait for network layer up and configure the interface on
         * success.
         */
        if (NutEventWait(&dcb->dcb_state_chg, 60000) == 0 && dcb->dcb_ipcp_state == PPPS_OPENED) {
            return NutNetIfSetup(dev, dcb->dcb_local_ip, dcb->dcb_ip_mask, dcb->dcb_remote_ip);
        }
    }
    return -1;
}
/*
 * Low priority background thread. 
 */
THREAD(Low, arg)
{
    NutThreadSetPriority(96);
    for(;;) {
        puts("                  Request");
        if (NutEventWait(&mutex, 3000)) {
            puts("                  Timeout");
        }
        else {
            puts("                  Acquired");
            NutSleep(3500);
            puts("                  Release");
            NutEventPost(&mutex);
        }
    }
}
/*
 * High priority background thread. 
 */
THREAD(High, arg)
{
    NutThreadSetPriority(32);
    for(;;) {
        puts("Request");
        if (NutEventWait(&mutex, 2000)) {
            puts("Timeout");
        }
        else {
            puts("Acquired");
            NutSleep(2500);
            puts("Release");
            NutEventPost(&mutex);
        }
        NutSleep(1000);
    }
}
Beispiel #12
0
/*
 * Demonstrate Nut/OS one-shot timer.
 *
 * One-shot timers will call the callback function once and then stop
 * the timer automatically.
 *
 * Note that this function also demonstrates event timeouts.
 */
static void OneShotDemo(int s)
{
    HANDLE t;
    HANDLE e = NULL;
    int w;

    printf("Start %d s one-shot timer\n", s);
    t = NutTimerStart(s * 1000UL, TimerCallback, &e, TM_ONESHOT);
    for (w = 1; w < s + 1; w++) {
        printf("  Waiting %d s...", w);
        if (NutEventWait(&e, 1000UL) == 0) {
            puts("elapsed");
            break;
        }
        puts("timed out");
    }
}
/*
 * Main application routine. 
 */
int main(void)
{
    uint32_t baud = 115200;

    /*
     * Register the UART device, open it, assign stdout to it and set 
     * the baudrate.
     */
    NutRegisterDevice(&DEV_CONSOLE, 0, 0);
    freopen(DEV_CONSOLE_NAME, "w", stdout);
    _ioctl(_fileno(stdout), UART_SETSPEED, &baud);

    /*
     * Print title.
     */
    puts("\nNut/OS Event Queue Demo");
    puts("High     Main     Low      ");

    /*
     * Post an initial event. This will put the queue into signaled 
     * state and immediately grant the next call to NutEventWait().
     */
    NutEventPost(&mutex);

    /*
     * Start two background threads.
     */
    NutThreadCreate("high", High, 0, 256);
    NutThreadCreate("low", Low, 0, 256);

    for(;;) {
        puts("         Request");
        if (NutEventWait(&mutex, 1000)) {
            puts("         Timeout");
        }
        else {
            puts("         Acquired");
            NutSleep(1500);
            puts("         Release");
            NutEventPost(&mutex);
        }
        NutSleep(1000);
    }
    return 0;
}
Beispiel #14
0
/*!
 * \brief Reentrant variant of RawFsFileOpen().
 */
static NUTFILE *RawFsApiFileOpen(NUTDEVICE * dev, CONST char *path, int mode, int acc)
{
    NUTFILE *rc;
    RAWVOLUME *vol;

    NUTASSERT(dev != NULL);
    vol = (RAWVOLUME *) dev->dev_dcb;
    NUTASSERT(vol != NULL);

    /* Lock filesystem access. */
    NutEventWait(&vol->vol_fsmutex, 0);
    /* Call worker routine. */
    rc = RawFsFileOpen(dev, path, mode, acc);
    /* Release filesystem lock. */
    NutEventPost(&vol->vol_fsmutex);

    return rc;
}
Beispiel #15
0
/*!
 * \brief Load sector.
 *
 * \param dev  Specifies the file system device.
 * \param sect Sector to load.
 *
 * \return 0 on success, -1 on failures.
 */
static int RawFsSectorLoad(NUTDEVICE * dev, uint32_t sect)
{
    int rc = -1;
    RAWVOLUME *vol;

    NUTASSERT(dev != NULL);
    vol = (RAWVOLUME *) dev->dev_dcb;

    /* Gain mutex access. */
    NUTASSERT(vol != NULL);
    NutEventWait(&vol->vol_iomutex, 0);

    /* Nothing to do if sector is already loaded. */
    if (vol->vol_sect_num == sect) {
        rc = 0;
    }
    /* Make sure that the sector buffer is clean. */
    else if (RawFsSectorFlush(dev) == 0) {
        NUTFILE *blkmnt = dev->dev_icb;
        NUTDEVICE *blkdev = blkmnt->nf_dev;
        BLKPAR_SEEK pars;

        blkmnt = dev->dev_icb;
        NUTASSERT(blkmnt != NULL);
        blkdev = blkmnt->nf_dev;
        NUTASSERT(blkdev != NULL);

        /* Set the block device's sector position. */
        pars.par_nfp = blkmnt;
        pars.par_blknum = sect;
        if ((*blkdev->dev_ioctl) (blkdev, NUTBLKDEV_SEEK, &pars) == 0) {
            /* Read a single block from the device. */
            if ((*blkdev->dev_read) (blkmnt, vol->vol_sect_buf, 1) == 1) {
                vol->vol_sect_num = sect;
                rc = 0;
            }
        }
    }

    /* Release mutex access. */
    NutEventPostAsync(&vol->vol_iomutex);

    return rc;
}
Beispiel #16
0
/*!
 * \brief Reentrant variant of RawFsFileRead().
 */
static int RawFsApiFileRead(NUTFILE * nfp, void *buffer, int size)
{
    int rc;
    RAWVOLUME *vol;

    NUTASSERT(nfp != NULL);
    NUTASSERT(nfp->nf_dev != NULL);
    vol = (RAWVOLUME *) nfp->nf_dev->dev_dcb;
    NUTASSERT(vol != NULL);

    /* Lock filesystem access. */
    NutEventWait(&vol->vol_fsmutex, 0);
    /* Call worker routine. */
    rc = RawFsFileRead(nfp, buffer, size);
    /* Release filesystem lock. */
    NutEventPost(&vol->vol_fsmutex);

    return rc;
}
Beispiel #17
0
/*!
 * \brief I2C bus transfer (STM I2C implementation).
 *
 * This function is called by the platform independent code via the
 * NUTI2C_BUS::bus_tran function pointer.
 */
static int I2cBusTran(NUTI2C_SLAVE *slave, NUTI2C_MSG *msg)
{
    NUTI2C_BUS *bus;
    STM32_I2CCB *icb;
    I2C_TypeDef *i2c;
    uint32_t cr2;
    int rc = 0;

    bus = slave->slave_bus;
    NUTASSERT(bus != NULL);
    NUTASSERT(bus->bus_icb != NULL);
    icb = (STM32_I2CCB *) bus->bus_icb;
    icb->icb_msg = msg;
    icb->errors = 0;
    i2c = (I2C_TypeDef *) icb->icb_base;
    cr2 = i2c->CR2;
    cr2 &= 0xf8000000; /* Clean out */
    cr2 |= slave->slave_address << 1;
    msg->msg_widx = 0;
    msg->msg_ridx = 0;
    /* are there bytes to write? */
    if (msg->msg_wlen)
    {
        i2c->CR1 |= I2C_CR1_TXIE | I2C_CR1_TCIE | I2C_CR1_STOPIE | I2C_CR1_NACKIE;
        if (msg->msg_wlen > 0xff)
            cr2 |= I2C_CR2_NBYTES | I2C_CR2_RELOAD;
        else
            cr2 |= msg->msg_wlen << 16;
    }
    else if (msg->msg_rsiz)
    {
        i2c->CR1 |= I2C_CR1_RXIE | I2C_CR1_STOPIE  | I2C_CR1_NACKIE;
        if (msg->msg_rsiz > 0xff)
            cr2 |= I2C_CR2_RD_WRN | I2C_CR2_NBYTES | I2C_CR2_RELOAD;
        else
            cr2 |= I2C_CR2_RD_WRN | msg->msg_rsiz << 16;
    }
    i2c->CR2 = cr2 | I2C_CR2_START;
    rc = NutEventWait(&icb->icb_queue, slave->slave_timeout);
    if ((icb->errors) || (rc))
        msg->msg_ridx = -1;
    return msg->msg_ridx;
}
Beispiel #18
0
/*
 * Demonstrate Nut/OS periodic timer.
 *
 * Periodic timers will call the callback function and then restart
 * the timer automatically. They must be explicitly stopped, if no
 * longer needed.
 */
static void PeriodicDemo(int s)
{
    HANDLE t;
    HANDLE e = NULL;
    int i;
    uint32_t ms;

    printf("Start %d s periodic timer\n", s);
    t = NutTimerStart(s * 1000UL, TimerCallback, &e, 0);
    for (i = 0; i < 5; i++) {
        ms = NutGetMillis();
        printf("  Waiting...");
        NutEventWait(&e, NUT_WAIT_INFINITE);
        ms = NutGetMillis() - ms;
        printf("elapsed after %lu ms\n", ms);
    }
    puts("  Stop periodic timer");
    NutTimerStop(t);
}
Beispiel #19
0
/*!
 * \brief Reentrant variant of RawFsIOCtl().
 */
static int RawFsApiIOCtl(NUTDEVICE * dev, int req, void *conf)
{
    int rc;
    RAWVOLUME *vol;

    NUTASSERT(dev != NULL);
    vol = (RAWVOLUME *) dev->dev_dcb;

    /* Lock filesystem access. */
    if (req != FS_VOL_MOUNT && vol) {
        NutEventWait(&vol->vol_fsmutex, 0);
    }
    /* Call worker routine. */
    rc = RawFsIOCtl(dev, req, conf);
    /* Release filesystem lock. */
    if (req != FS_VOL_MOUNT && req != FS_VOL_UNMOUNT && vol) {
        NutEventPost(&vol->vol_fsmutex);
    }
    return rc;
}
Beispiel #20
0
/*!
 * \brief Flush file buffers.
 *
 * \param nfp Specifies the file.
 *
 * \return 0 on success, -1 otherwise.
 */
static int RawFsFileFlush(NUTFILE * nfp)
{
    int rc;
    NUTDEVICE *dev;
    RAWVOLUME *vol;

    NUTASSERT(nfp != NULL);
    dev = nfp->nf_dev;
    NUTASSERT(dev != NULL);
    vol = (RAWVOLUME *) dev->dev_dcb;
    NUTASSERT(vol != NULL);

    /* Gain mutex access. */
    NutEventWait(&vol->vol_iomutex, 0);
    /* Flush sector buffer. */
    rc = RawFsSectorFlush(nfp->nf_dev);
    /* Release mutex access. */
    NutEventPost(&vol->vol_iomutex);

    return rc;
}
/*
 * \return 0 on success, -1 in case of any errors.
 */
static int SendRawByte(AHDLCDCB * dcb, uint8_t ch, uint8_t flush)
{
    /*
       * If transmit buffer is full, wait until interrupt routine
       * signals an empty buffer or until a timeout occurs.
     */
    while ((uint8_t) (dcb->dcb_wr_idx + 1) == dcb->dcb_tx_idx) {
        if (NutEventWait(&dcb->dcb_tx_rdy, dcb->dcb_wtimeout))
            break;
    }

    /*
     * If transmit buffer is still full, we have a write timeout.
     */
    if ((uint8_t) (dcb->dcb_wr_idx + 1) == dcb->dcb_tx_idx) {
        return -1;
    }

    /*
     * Buffer has room for more data. Put the byte in the buffer
     * and increment the write index.
     */
    dcb->dcb_tx_buf[dcb->dcb_wr_idx] = ch;
    dcb->dcb_wr_idx++;

    /*
     * If transmit buffer has become full and the transmitter
     * is not active, then activate it.
     */
    if (flush || (uint8_t) (dcb->dcb_wr_idx + 1) == dcb->dcb_tx_idx) {

        NutEnterCritical();

        outr(US1_IER, US_TXRDY);

        NutExitCritical();
    }
    return 0;
}
Beispiel #22
0
/*! \brief Select a device on the SPI bus.
 *
 * Locks and activates the bus for the specified node.
 *
 * \param node Specifies the SPI bus node.
 * \param tmo Timeout in milliseconds. To disable timeout, set this
 *            parameter to NUT_WAIT_INFINITE.
 *
 * \return 0 on success. In case of an error, -1 is returned and the bus 
 *         is not locked.
 */
int GpioSpiBus0Select(NUTSPINODE * node, uint32_t tmo)
{
    int rc;

    /* Sanity check. */
    NUTASSERT(node != NULL);
    NUTASSERT(node->node_stat != NULL);

    /* Allocate the bus. */
    rc = NutEventWait(&node->node_bus->bus_mutex, tmo);
    if (rc) {
        errno = EIO;
    } else {
        /* Do the update, if the mode update bit is set. */
        if (node->node_mode & SPI_MODE_UPDATE) {
            GpioSpiSetup(node);
        }
        /* Set clock output using the correct idle mode level. */
#if defined(SBBI0_SCK_BIT)
        GpioPinSetLow(SBBI0_SCK_PORT, (node->node_mode & SPI_MODE_CPOL) != 0);
        GpioPinConfigSet(SBBI0_SCK_PORT, SBBI0_SCK_BIT, GPIO_CFG_OUTPUT);
#endif
        /* Enable MOSI output and MISO input. */
#if defined(SBBI0_MOSI_BIT)
        GpioPinConfigSet(SBBI0_MOSI_PORT, SBBI0_MOSI_BIT, GPIO_CFG_OUTPUT);
#endif
#if defined(SBBI0_MISO_BIT)
        GpioPinConfigSet(SBBI0_MISO_PORT, SBBI0_MISO_BIT, 0);
#endif
        /* Activate the node's chip select. */
        if (GpioSpi0ChipSelect(node->node_cs, (node->node_mode & SPI_MODE_CSHIGH) != 0) == NULL) {
            /* Release the bus in case of an error. */
            NutEventPost(&node->node_bus->bus_mutex);
            rc = -1;
        }
    }
    return rc;
}
Beispiel #23
0
static void MMCLock(void)
{
    NutEventWait(&hMMCSemaphore, 0);
} /* MMCLock */
Beispiel #24
0
/*! \brief Select a device on the SPI bus.
 *
 * Locks and activates the bus for the specified node.
 *
 * \param node Specifies the SPI bus node.
 * \param tmo  Timeout in milliseconds. To disable timeout, set this
 *             parameter to NUT_WAIT_INFINITE.
 *
 * \return 0 on success. In case of an error, -1 is returned and the bus
 *         is not locked.
 */
static int Stm32SpiBusSelect(NUTSPINODE * node, uint32_t tmo)
{
	int rc;
	SPI_TypeDef* base;

	/* Sanity check. */
	NUTASSERT(node != NULL);
	NUTASSERT(node->node_bus != NULL);
	NUTASSERT(node->node_stat != NULL);

	base=(SPI_TypeDef*)(node->node_bus->bus_base);

	/* Allocate the bus. */
	rc = NutEventWait(&node->node_bus->bus_mutex, tmo);
	if (rc) {
		errno = EIO;
	} else {
		SPI_TypeDef *spireg = node->node_stat;

		SPI_ENABLE_CLK;
		/* Activate the IO Pins to avoid glitches*/
		GpioPinConfigSet(SPIBUS_SCK_PORT,  SPIBUS_SCK_PIN,  GPIO_CFG_DISABLED);//SCK
		GpioPinConfigSet(SPIBUS_MISO_PORT, SPIBUS_MISO_PIN, GPIO_CFG_DISABLED );//MISO
		GpioPinConfigSet(SPIBUS_MOSI_PORT, SPIBUS_MOSI_PIN, GPIO_CFG_DISABLED);//MOSI

		/* If the mode update bit is set, then update our shadow registers. */
		if (node->node_mode & SPI_MODE_UPDATE) {
			Stm32SpiSetup(node);
		}

		/* Set SPI mode. */
		base->CR1 = spireg->CR1;
		base->CR1 |= SPI_CR1_SSI|SPI_CR1_MSTR;
		base->CR2=spireg->CR2;
#if !defined(STM32L1XX_MD)
		base->I2SCFGR=spireg->I2SCFGR;
		base->I2SPR=spireg->I2SPR;
#endif
		//No enable - set it only during transfer

#if defined(STM32F10X_CL)
#if defined(SPIBUS_REMAP_BB)
		SPIBUS_REMAP_BB = SPI_DOREMAP;
#endif
#elif defined (MCU_STM32L1) || defined (MCU_STM32F2) || defined (MCU_STM32F4)
		GPIO_PinAFConfig( SPIBUS_SCK_PORT,  SPIBUS_SCK_PIN,  SPI_GPIO_AF);
		GPIO_PinAFConfig( SPIBUS_MISO_PORT, SPIBUS_MISO_PIN, SPI_GPIO_AF);
		GPIO_PinAFConfig( SPIBUS_MOSI_PORT, SPIBUS_MOSI_PIN, SPI_GPIO_AF);
#endif
		GpioPinConfigSet(SPIBUS_SCK_PORT,  SPIBUS_SCK_PIN,  GPIO_CFG_OUTPUT|GPIO_CFG_PERIPHAL);//SCK
		GpioPinConfigSet(SPIBUS_MISO_PORT, SPIBUS_MISO_PIN,                 GPIO_CFG_PERIPHAL);//MISO
		GpioPinConfigSet(SPIBUS_MOSI_PORT, SPIBUS_MOSI_PIN, GPIO_CFG_OUTPUT|GPIO_CFG_PERIPHAL);//MOSI
		/* Finally activate the node's chip select. */
		rc = Stm32SpiChipSelect(node->node_cs, (node->node_mode & SPI_MODE_CSHIGH) != 0);
		if (rc) {
			/* Release the bus in case of an error. */
			NutEventPost(&node->node_bus->bus_mutex);
		}
	}
	return rc;
}
Beispiel #25
0
int NutTwiMasterRegWrite( NUTTWIBUS  *bus,
                          uint8_t sla,
                          uint32_t iadr, uint8_t iadrlen,
                          const void *txdata, uint16_t txsiz,
                          uint32_t tmo )
{
    int rc = -1;
    NUTTWIICB *icb = bus->bus_icb;

//    TPRINTF( "TMRW ");

    /* Quit if nothing to do */
    if( txsiz==0) {
        TPRINTF("! txs=0... OUT\n");
        return rc;
    }

    /* This routine is marked reentrant, so lock the interface. */
    if( NutEventWait( &bus->bus_mutex, tmo ) ) {
        icb->tw_mm_error = TWERR_IF_LOCKED;
        TPRINTF("! mtx=LOCKED... OUT\n");
        return rc;
    }
#if 0
    /* Check if bus is blocked for any reason */
    if (TwWaitBusFree( bus))
    {
        return rc;
    }
#endif
    /* Clear errors. */
    icb->tw_mm_err = 0;
    /* fetch transfer parameters for current transaction */
    icb->tw_mm_sla = sla<<1;
    icb->tw_mm_iadrlen = iadrlen;
    if( iadrlen) {
        /* little-endian machine! */
        icb->tw_mm_iadr = ((uint8_t*)&iadr)+iadrlen-1;
    }
    icb->tw_mm_txbuf = (uint8_t*)txdata;
    icb->tw_mm_txlen = txsiz;
    icb->tw_mm_rxbuf = 0;
    icb->tw_mm_rxlen = 0;
    icb->tw_mm_dir = MODE_WRITE;
    icb->tw_mm_err = 0;

    /* Issue start and wait till transmission completed */
    NutTwiStartRolling( bus, tmo);

    /* Check for errors that may have been detected
     * by the interrupt routine.
     */
    if( icb->tw_mm_err ) {
        icb->tw_mm_error = icb->tw_mm_err;
        rc = -1;
        TPRINTF( "! Error 0x%d\n", icb->tw_mm_err);
        /* Soft-Reset this Bus */
        // NutTwiSoftReset( bus);
    }
    else {
        rc = (int)(txsiz - icb->tw_mm_txlen);
    }

    /* Release the interface. */
    NutEventPost( &bus->bus_mutex );
//    TPRINTF( "* Bye rc=%d\n", rc);

    return rc;
}
Beispiel #26
0
/*
 * Main application routine.
 *
 * Nut/OS automatically calls this entry after initialization.
 */
int main(void)
{
    uint32_t baud = 115200;
    /* IP of the local network in host byte order. */
    uint32_t net_ip;
    /* Currently scanned IP in host byte order. */
    uint32_t scan_ip;
    /* Currently scanned IP in network byte order. */
    uint32_t dest;
    /* Host portion mask in host byte order. */
    uint32_t host_mask;
    /* Current echo request sequence number. */
    uint16_t seq = 0;

    /*
     * Assign stdout to the DEBUG device.
     */
    NutRegisterDevice(&DEV_CONSOLE, 0, 0);
    freopen(DEV_CONSOLE.dev_name, "w", stdout);
    _ioctl(_fileno(stdout), UART_SETSPEED, &baud);

    /*
     * Print out our version information.
     */
    printf("\n\nNut/OS %s\n", NutVersionString());
    printf("PingNet %s " __DATE__ " " __TIME__ "\n", APP_VERSION);

    /*
     * Configure the network interface. It is assumed, that
     * we got a valid configuration in non-volatile memory.
     *
     * For alternatives see
     * http://www.ethernut.de/nutwiki/Network_Configuration
     */
    printf("Configure %s...", DEV_ETHER_NAME);
    if (NutRegisterDevice(&DEV_ETHER, 0, 0)) {
        FatalError("failed");
    }
    if (NutDhcpIfConfig("eth0", 0, 60000)) {
        FatalError("no valid network configuration");
    }
    printf("%s ready\n", inet_ntoa(confnet.cdn_ip_addr));
    /* Some Ethernet device drivers seem to return from initialization
       even if they are not fully up and running. Typically this is no
       problem, because upper layers will do retries. However, in our
       special case we'd lose some nodes during the first scan. So just
       take a short nap to give the driver some more time. */
    NutSleep(2000);

    /*
     * Register an ICMP callback function to inspect all incoming
     * ICMP packets.
     */
    if (NutRegisterIpHandler(IPPROTO_ICMP, IcmpCallback)) {
        FatalError("failed to register ICMP callback");
    }

    /*
     * Determine the host portion mask and the IP of the local
     * network from our IP configuration. Note, that Nut/Net
     * stores all IP address items in network byte order.
     */
    host_mask = ~ntohl(confnet.cdn_ip_mask);
    net_ip = ntohl(confnet.cdn_ip_addr) & ~host_mask;

    /*
     * Allocate a bit field to store the state of all possible
     * nodes of our local network. Limit this to 2^16 (class B)
     * and also reject point to point configurations.
     */
    if (host_mask > 0xFFFF || host_mask < 0x0003) {
        FatalError("Bad network size");
    }
    upnodes = calloc((host_mask + 1) / 8, 1);
    if (upnodes == NULL) {
        FatalError("out of memory");
    }

    /*
     * Scan the whole network endlessly.
     */
    for (;;) {
        int retries = 0;

        seq++;
        scan_ip = net_ip;
        /*
         * Scan node by node.
         */
        for (;;) {
            int got = 0;

            /* If this is not a retry, move to the next possible node
               address. */
            if (retries == 0) {
                scan_ip++;
            }
            /* All nodes processed if we reached the broadcast address. */
            if ((scan_ip & host_mask) == host_mask) {
                break;
            }
            /* Send an echo request to the current IP (network byte order). */
            dest = htonl(scan_ip);
            printf("\r%s ", inet_ntoa(dest));
            if (IcmpSendPing(dest, 1, seq, 32) == 0) {
                /* Wait until our ICMP handler signals new packets. */
                while (got == 0 && NutEventWait(&sign_queue, 100) == 0) {
                    /* Inspect all queued packets. */
                    while (nbuf_queue) {
                        NETBUF *nb;
                        IPHDR *ip = (IPHDR *) nbuf_queue->nb_nw.vp;

                        /* Check if this packet is from the currently scanned
                           node address. We may additionally check ID and
                           sequence number, but actually anything from that
                           interface will be just fine to mark it as up. */
                        got += (ip->ip_src == dest);
                        nb = nbuf_queue;
                        nbuf_queue = nb->nb_next;
                        NutNetBufFree(nb);
                    }
                }
                if (NODE_IS_UP(scan_ip & host_mask)) {
                    /* If the node has been up and is now down, then
                       do a few retries first to be sure that it is
                       really not responding anymore. */
                    if (got == 0) {
                        if (retries < 3) {
                            retries++;
                        } else {
                            retries = 0;
                            NODE_DOWN(scan_ip & host_mask);
                            puts("down");
                        }
                    }
                }
                else if (got) {
                    /* New node detected. */
                    NODE_UP(scan_ip & host_mask);
                    puts("up");
                }
            } else {
                /* Failed to send out the request. */
                puts("ICMP transmit error");
            }
        }
        /* Sleep one minute before scanning the network again. */
        printf("\rSleeping                ");
        NutSleep(60000);
    }
    /* Never reached, but required to suppress compiler warning. */
    return 0;
}
/*!
 * \brief Load a packet into the nic's transmit ring buffer.
 *
 * Interupts must have been disabled when calling this function.
 *
 * \param nb Network buffer structure containing the packet to be sent.
 *           The structure must have been allocated by a previous
 *           call NutNetBufAlloc(). This routine will automatically
 *           release the buffer in case of an error.
 *
 * \return 0 on success, -1 in case of any errors. Errors
 *         will automatically release the network buffer 
 *         structure.
 */
static int NicPutPacket(NETBUF * nb)
{
    u_int16_t sz;
    uint8_t odd = 0;
    uint8_t imsk;

    //printf("[P]");
    /*
     * Calculate the number of bytes to be send. Do not send packets 
     * larger than the Ethernet maximum transfer unit. The MTU
     * consist of 1500 data bytes plus the 14 byte Ethernet header
     * plus 4 bytes CRC. We check the data bytes only.
     */
    if ((sz = nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz) > ETH_DATA_LEN)
        return -1;

    /* Disable all interrupts. */
    imsk = nic_inlb(NIC_MSK);
    nic_outlb(NIC_MSK, 0);

    /* Allocate packet buffer space. */
    nic_bs(2);
    nic_outlb(NIC_MMUCR, MMU_ALO);
    if (NicMmuWait(100))
        return -1;

    /* Enable interrupts including allocation success. */
    nic_outlb(NIC_MSK, imsk | INT_ALLOC);

    /* The MMU needs some time. Use it to calculate the byte count. */
    sz += nb->nb_dl.sz;
    sz += 6;
    if (sz & 1) {
        sz++;
        odd++;
    }

    /* Wait for allocation success. */
    while ((nic_inlb(NIC_IST) & INT_ALLOC) == 0) {
        if (NutEventWait(&maq, 125)) {
            nic_outlb(NIC_MMUCR, MMU_RST);
            NicMmuWait(1000);
            nic_outlb(NIC_MMUCR, MMU_ALO);
            if (NicMmuWait(100) || (nic_inlb(NIC_IST) & INT_ALLOC) == 0) {
                if (NutEventWait(&maq, 125)) {
                    return -1;
                }
            }
        }
    }

    /* Disable interrupts. */
    imsk = nic_inlb(NIC_MSK);
    nic_outlb(NIC_MSK, 0);


    nic_outlb(NIC_PNR, nic_inhb(NIC_PNR));

    nic_outw(NIC_PTR, 0x4000);

    /* Transfer control word. */
    nic_outlb(NIC_DATA, 0);
    nic_outlb(NIC_DATA, 0);

    /* Transfer the byte count. */
    nic_outw(NIC_DATA, sz);

    /* Transfer the Ethernet frame. */
    NicWrite(nb->nb_dl.vp, nb->nb_dl.sz);
    NicWrite(nb->nb_nw.vp, nb->nb_nw.sz);
    NicWrite(nb->nb_tp.vp, nb->nb_tp.sz);
    NicWrite(nb->nb_ap.vp, nb->nb_ap.sz);

    if (odd)
        nic_outlb(NIC_DATA, 0);

    /* Transfer the control word. */
    nic_outw(NIC_DATA, 0);

    /* Enqueue packet. */
    if (NicMmuWait(100))
        return -1;
    nic_outlb(NIC_MMUCR, MMU_ENQ);

    /* Enable interrupts. */
    imsk |= INT_TX | INT_TX_EMPTY;
    nic_outlb(NIC_MSK, imsk);

    return 0;
}
/*! \fn NicRxLanc(void *arg)
 * \brief NIC receiver thread.
 *
 */
THREAD(NicRxLanc, arg)
{
    NUTDEVICE *dev;
    IFNET *ifn;
    lanc111_nic_t *ni;
    NETBUF *nb;
    uint8_t imsk;

    dev = arg;
    ifn = (IFNET *) dev->dev_icb;
    ni = (lanc111_nic_t *) dev->dev_dcb;

    /*
     * This is a temporary hack. Due to a change in initialization,
     * we may not have got a MAC address yet. Wait until a valid one
     * has been set.
     */
    while (!ETHER_IS_UNICAST(ifn->if_mac)) {
        NutSleep(10);
    }

    /*
     * Do not continue unless we managed to start the NIC. We are
     * trapped here if the Ethernet link cannot be established.
     * This happens, for example, if no Ethernet cable is plugged
     * in.
     */
    while(NicStart(ifn->if_mac)) {
        NutSleep(1000);
    }

    //LANC111_SIGNAL_MODE();

    // Enable IRQs. Enabled on irq allocation.
    //sbi(EIMSK, LANC111_SIGNAL_IRQ);

    NutEventPost(&nic->ni_tx_rdy);

    /* Run at high priority. */
    NutThreadSetPriority(9);

    for (;;) {

        /*
         * Wait for the arrival of new packets or
         * check the receiver every two second.
         */
        NutEventWait(&ni->ni_rx_rdy, 2000);

        /*
         * Fetch all packets from the NIC's internal
         * buffer and pass them to the registered handler.
         */
        imsk = nic_inlb(NIC_MSK);
        nic_outlb(NIC_MSK, 0);
        while ((nb = NicGetPacket()) != 0) {
            if (nb != (NETBUF *) 0xFFFF) {
                ni->ni_rx_packets++;
                (*ifn->if_recv) (dev, nb);
            }
        }
        nic_outlb(NIC_MSK, imsk | INT_RCV | INT_ERCV);
    }
}
Beispiel #29
0
THREAD(SoundFFT, arg)
{
	printf("SoundFFT started\n");
	fflush(stdout);
	SoundStruct* ss = arg;

	int i, j;

	//short x = 10;

	short * melBuffer = malloc( WIN_SIZE/2 * sizeof(short)); // 64
	short * cepsBuffer = malloc( CEPS_COUNT * WIN_SIZE * sizeof(short) ); // 4096
	short * real;

	short * im = malloc( WIN_SIZE * sizeof(short) ); // 128
	for(i = 0; i < WIN_SIZE; i++) im[i] = 0;


	int ** ceps = malloc(CEPS_COUNT * sizeof(int*)); // 32
	for( i = 0; i< CEPS_COUNT; i++)
		ceps[i] = malloc(SIGNIFICANTS * sizeof(int)); // 20

	if(ss->recording)
	{
		// wait for sample
		NutEventWait( &recordBufferReadyRead, 0 );

		memcpy( cepsBuffer, ss->buffer, ss->ceps_count * WIN_SIZE * sizeof(short) );
		real = cepsBuffer;

		SR_PreFilter(real, ss->ceps_count * WIN_SIZE);

		int ** sampleceps = malloc(CEPS_COUNT * sizeof(int*));
		for( i = 0; i< ss->ceps_count; i++)
			sampleceps[i] = malloc(SIGNIFICANTS * sizeof(int));

		for(i = 0; i < ss->ceps_count; i++)
		{
			SR_generateMFC(real, im, melBuffer, WIN_SIZE_E, sampleceps[i]);

			real += WIN_SIZE;


		}
		printf("Sample tallessa!\n\n%d\n", ss->ceps_count);

		// Tulostaa tallennetun samplen ja stoppaa


		printf("{\n");
		for( i = 0; i< ss->ceps_count; i++)
		{
			printf("{");
			for( j = 0; j < SIGNIFICANTS; j++)
			{
				printf("%d, ", sampleceps[i][j]);
			}
			printf("},\n");
		}
		printf("},\n");
		for(;;) NutThreadYield();
	}

	int minDist, minDistKey, distance, ceps_count;

	for(;;)
	{
		minDist = INT_MAX;
		minDistKey = 10;

		NutEventWait( &recordBufferReadyRead, 0 );

		//copy samples from ss->buffer to cepsBuffer
		memcpy( cepsBuffer, ss->buffer, ss->ceps_count * WIN_SIZE * sizeof(short) );
		real = cepsBuffer;
		ceps_count = ss->ceps_count;

		//SR_PreFilter(real, ss->ceps_count * WIN_SIZE);

		for(i = 0; i < ceps_count; i++)
		{
			SR_generateMFC(real, im, melBuffer, WIN_SIZE_E, ceps[i]);
			real += WIN_SIZE;
		}

		//recognition
		for(i = 0; i < SAMPLE_LIB_SIZE; i++)
		{
			distance = SR_DTWDistance(ss, ceps, i, ceps_count);

			if( distance < minDist )
			{
				minDist = distance;
				minDistKey = i;
			}
		}
		//printf("%d - %d\n", minDistKey, minDist);
		if ( minDist < DTW_TRESHOLD )
		{
			short com = 0;
			switch ( minDistKey ) {
			case 0:
				com = ARROW_UP;
				break;
			case 1:
				com = ARROW_DOWN;
				break;
			case 2:
				com = ARROW_LEFT;
				break;
			case 3:
				com = ARROW_RIGHT;
				break;
			case 4:
				com = ENTER_BUTTON;
				break;
			case 5:
				com = UNDO_BUTTON;
				break;
			default:
				break;
			}

			if(com != 0) UI_CQpush(ss->ui, com);


		}

		//printf("MinDistance: %d - %d\n", minDistKey, minDist);
		//fflush(stdout);

	}
	for(;;) NutThreadYield();
}
/*!
 * \brief Get next infrared code.
 *
 * \param tmo Timeout in milliseconds.
 *
 * \return The code received from an infrared decoder or -1 on timeout.
 */
long NutIrGet(u_long tmo)
{
    if (NutEventWait(&nut_irqueue, tmo))
        return -1L;
    return nut_ircode;
}