Esempio n. 1
0
/*
 * Rising edge on the data line while the clock line is high indicates
 * a stop condition.
 *
 * Entry: SCL low, SDA any
 * Exit: SCL high, SDA high
 */
static void TwStop(GPIO_TWICB* icb)
{
    I2C_SDA_LO();
    NutMicroDelay (icb->delay_unit);
    I2C_SCL_HI();
    NutMicroDelay (2 * icb->delay_unit);
    I2C_SDA_HI();
    NutMicroDelay (8 * icb->delay_unit);
}
Esempio n. 2
0
/*!
 * \brief Send byte to LCD controller.
 *
 * \param data Byte to send.
 */
static void LcdWriteByte(unsigned int data)
{
    /* If configured set RW low */
#ifdef LCD_RW_BIT
    LCD_RW_CLR();
#endif

    /* If using 4-bit access, write two nibbles now */
#ifdef LCD_IF_4BIT
    LcdWriteNibble(data >> 4);
    LcdNanoDelay(LCD_PW_EH);
    LcdWriteNibble(data);
#else
    /* else write one byte */
	LcdWriteNibble(data);
#endif

    /* If configured, let the task sleep before next character */
#if defined(LCD_SLEEP_DLY)
    NutSleep(1);
#else
    /* or add a fixed delay and immediately process next char */
    NutMicroDelay(LCD_E2E_DLY);
#endif
}
Esempio n. 3
0
/*!
 * \brief Send half byte to LCD controller.
 *
 * \param nib The four least significant bits are sent.
 */
static void LcdWriteNibble(unsigned int nib)
{
#ifdef LCD_DATA_LSB
    nib <<= LCD_DATA_LSB;
#else
    {
        unsigned int val = 0;
        if (nib & 0x01) {
            val |= LCD_D0;
        }
        if (nib & 0x02) {
            val |= LCD_D1;
        }
        if (nib & 0x04) {
            val |= LCD_D2;
        }
        if (nib & 0x08) {
            val |= LCD_D3;
        }
        nib = val;
    }
#endif
    LcdSetBits(nib & LCD_DATA);
    LcdClrBits(~nib & LCD_DATA);

    /* Create Enable Pulse:
     * For HD44780 Displays we need:
     * Vcc = 5.0V -> PWeh >= 230ns
     * Vcc = 3.3V -> PWeh >= 500ns
     */
    LCD_EN_SET();
    NutMicroDelay(LCD_SHORT_DELAY);
    LCD_EN_CLR();
}
Esempio n. 4
0
/*
 * Toggles in a single byte in master mode.
 *
 * Entry: SCL low, SDA any
 * Exit: SCL low, SDA low with ack set, high else
 *
 * Change SDA only when SCL is low!
 * Sample SDA short before setting SCL low!
 */
static uint8_t TwGet(GPIO_TWICB* icb, uint8_t ack)
{
    uint8_t rc = 0;
    int i;

    /* SDA is input. */
    I2C_SDA_HI();
    NutMicroDelay (1 * icb->delay_unit);
    for (i = 0x80; i; i >>= 1) {
        NutMicroDelay (2 * icb->delay_unit);
        I2C_SCL_HI();
        NutMicroDelay (2 * icb->delay_unit);
        while(I2C_SCL_GET() == 0)
        {
            /* Clock stretching*/
            NutMicroDelay (2 * icb->delay_unit);
        }
        if (I2C_SDA_GET()) {
            rc |= i;
        }
        I2C_SCL_LO();
    }
    if (ack)
    {
        /* Master sets acknowledge */
        I2C_SDA_LO();
    }
    NutMicroDelay (2 * icb->delay_unit);
   I2C_SCL_HI();
    NutMicroDelay (2 * icb->delay_unit);
    I2C_SCL_LO();
    NutMicroDelay (2 * icb->delay_unit);
    return rc;
}
Esempio n. 5
0
static int LcdInit(NUTDEVICE * dev)
{
	LCD_RS_CLR();			
	LCD_RW_CLR();			
	LcdClrBits(LCD_DATA);	
	NutMicroDelay(30);
	LCD_EN_CLR();
	NutMicroDelay(30);
	NutSleep(18);

    /* This initialization will make sure, that the LCD is switched
     * to 8-bit mode, no matter which mode we start from or we finally
     * need.
     */
	LcdWriteCmd(_BV(LCD_FUNCTION) | _BV(LCD_FUNCTION_8BIT));
    NutSleep(16);
	LcdWriteCmd(_BV(LCD_FUNCTION) | _BV(LCD_FUNCTION_8BIT));
    NutSleep(4);
	LcdWriteCmd(_BV(LCD_FUNCTION) | _BV(LCD_FUNCTION_8BIT));
    NutSleep(2);
    LcdWriteInstruction((_BV(LCD_FUNCTION)) |  (_BV(LCD_FUNCTION_8BIT)) |  (_BV(LCD_EXT)) , LCD_SHORT_DELAY);

	/* Switch display and cursor off. */
    LcdWriteNibble(_BV(LCD_ON_CTRL) >> 4);
    LcdWriteNibble(_BV(LCD_ON_CTRL));
    NutSleep(2);

	/* Clear display. */
    LcdClear();
	
    /* Set entry mode. */
    LcdWriteCmd(_BV(LCD_ENTRY_MODE) | _BV(LCD_ENTRY_INC));
	
   /* Switch display on. */
    LcdWriteCmd(_BV(LCD_ON_CTRL) | _BV(LCD_ON_DISPLAY));

    /* Move cursor home. */
    LcdCursorHome();

	/* Set data address to zero. */
    LcdWriteCmd(_BV(LCD_DDRAM));

	return 0;
}
/* This function is a bit critical as some chipsets are known to
 * release the redy bit some time early. So after rady goes low,
 * another fixed delay has to be added before soing the next access.
 */
static void LcdWaitReady(unsigned int delay)
{
    while (delay--) {
#if defined(HD44_RW_BIT)
        if ((LcdReadStatus() & _BV(LCD_BUSY)) == 0) {
            break;
        }
#endif
        NutMicroDelay(1);
    }
}
Esempio n. 7
0
/*
 * Demonstrate Nut/OS delay timer.
 *
 * The delay function will not release the CPU, keeping all other threads
 * blocked. It is a good choice for very short delays, where context
 * switching is undesirable or would take too long. Use it sparingly and
 * for short delays only.
 */
static void DelayDemo(void)
{
    uint32_t req;
    uint32_t act;

    for (req = 1024UL; req <= 8UL * 1024UL * 1024UL; req *= 2) {
        printf("Delaying %lu us, ", req);
        act = NutGetMillis();
        NutMicroDelay(req);
        act = NutGetMillis() - act;
        printf("delayed %lu ms\n", act);
    }
}
Esempio n. 8
0
/* Idle clock is high and data is captured on the rising edge. */
static void SpiMode3Transfer(GSPIREG *gspi, CONST uint8_t *txbuf, uint8_t *rxbuf, int xlen)
{
#if defined(SBBI0_SCK_BIT)
    uint_fast8_t mask;

    while (xlen--) {
        for (mask = 0x80; mask; mask >>= 1) {
            NutMicroDelay(gspi->gspi_dly_rate);
            GpioPinSetLow(SBBI0_SCK_PORT, SBBI0_SCK_BIT);
#if defined(SBBI0_MOSI_BIT)
            if (txbuf) {
                GpioPinSet(SBBI0_MOSI_PORT, SBBI0_MOSI_BIT, (*txbuf & mask) != 0);
            }
#endif /* SBBI0_MOSI_BIT */
            NutMicroDelay(gspi->gspi_dly_rate);
            GpioPinSetHigh(SBBI0_SCK_PORT, SBBI0_SCK_BIT);
#if defined(SBBI0_MISO_BIT)
            if (rxbuf) {
                if (GpioPinGet(SBBI0_MISO_PORT, SBBI0_MISO_BIT)) {
                    *rxbuf |= mask;
                }
                else {
                    *rxbuf &= ~mask;
                }
            }
#endif /* SBBI0_MISO_BIT */
        }
        if (txbuf) {
            txbuf++;
        }
        if (rxbuf) {
            rxbuf++;
        }
    }
#endif /* SBBI0_SCK_BIT */
}
Esempio n. 9
0
/*
 * Toggles out a single byte in master mode.
 *
 * Entry: SCL low, SDA any
 * Exit: SCL low, SDA high
 *
 * Change SDA only when SCL is low!
 * Sample SDA short before setting SCL low!
 */
static int TwPut(GPIO_TWICB* icb, uint8_t octet)
{
    int i;

    for (i = 0x80; i; i >>= 1) {
        /* Set the data bit. */
        if (octet & i) {
            I2C_SDA_HI();
        } else {
            I2C_SDA_LO();
        }
        /* Wait for data to stabilize. */
        NutMicroDelay (2 * icb->delay_unit);
        /* Toggle the clock. */
        I2C_SCL_HI();
        NutMicroDelay (2 * icb->delay_unit);
        while(I2C_SCL_GET() == 0)
        {
            /* Clock stretching*/
            NutMicroDelay (2 * icb->delay_unit);
        }
        I2C_SCL_LO();
    }

    /* Release data line to receive the ACK bit. */
    I2C_SDA_HI();
    NutMicroDelay (2 * icb->delay_unit);
    I2C_SCL_HI();
    NutMicroDelay (2 * icb->delay_unit);
    if (I2C_SDA_GET()) {
        i = -1;
    } else {
        i = 0;
    }
    I2C_SCL_LO();
    NutMicroDelay (2 * icb->delay_unit);

    return i;
}
static int LcdInit(NUTDEVICE * dev)
{
#if defined(PMC_PCER)
    outr(PMC_PCER, _BV(LCD_RS_PIO_ID) | _BV(LCD_EN_PIO_ID));
#endif

    /* Initialize GPIO lines. */
#ifdef LCD_RW_BIT
    outr(PMC_PCER, _BV(LCD_RW_PIO_ID));
    LCD_RW_CLR();
#endif

#ifdef LCD_EN2_BIT
    outr(PMC_PCER, _BV(LCD_EN2_PIO_ID));
    LCD_EN2_CLR();
#endif

#ifdef LCD_RST_BIT
    outr(PMC_PCER, _BV(LCD_RST_PIO_ID));
    LCD_RST_CLR();
#endif

    LCD_RS_CLR();
    LCD_RW_CLR();
    LcdClrBits(LCD_DATA);
    NutMicroDelay(30);
    LCD_EN_CLR();
    NutMicroDelay(30);

    /* Initial delay. Actually only required after power on. */
    NutSleep(16);

    /* This initialization will make sure, that the LCD is switched
     * to 8-bit mode, no matter which mode we start from or we finally
     * need.
     */
    LcdWriteNibble((_BV(LCD_FUNCTION) | _BV(LCD_FUNCTION_8BIT)) >> 4);
    NutSleep(15);
    LcdWriteNibble((_BV(LCD_FUNCTION) | _BV(LCD_FUNCTION_8BIT)) >> 4);
    NutSleep(4);
    LcdWriteNibble((_BV(LCD_FUNCTION) | _BV(LCD_FUNCTION_8BIT)) >> 4);
    NutSleep(2);

#ifdef LCD_IF_4BIT
    /* We now switch to 4-bit mode */
    LcdWriteNibble(_BV(LCD_FUNCTION) >> 4);
    NutSleep(2);

    // TODO: Add support for large font in single line displays
    /* Set number of lines and font. Can't be changed later. */
#if (LCD_ROWS == 2) || (LCD_ROWS==4)
    LcdWriteNibble((_BV(LCD_FUNCTION) | _BV(LCD_FUNCTION_2LINES)) >> 4);
    LcdWriteNibble(_BV(LCD_FUNCTION) | _BV(LCD_FUNCTION_2LINES));
#else
    LcdWriteNibble(_BV(LCD_FUNCTION) >> 4);
    LcdWriteNibble(_BV(LCD_FUNCTION) );
#endif
#else /* LCD_IF_4BIT */
    LcdWriteCmd(_BV(LCD_FUNCTION) | _BV(LCD_FUNCTION_8BIT));
#endif /* LCD_IF_4BIT */
    NutSleep(2);

    /* Switch display and cursor off. */
    LcdWriteNibble(_BV(LCD_ON_CTRL) >> 4);
    LcdWriteNibble(_BV(LCD_ON_CTRL));
    NutSleep(2);

    /* Clear display. */
    LcdClear();

    /* Set entry mode. */
    LcdWriteCmd(_BV(LCD_ENTRY_MODE) | _BV(LCD_ENTRY_INC));
    /* Switch display on. */
    LcdWriteCmd(_BV(LCD_ON_CTRL) | _BV(LCD_ON_DISPLAY));
    /* Move cursor home. */
    LcdCursorHome();
    /* Set data address to zero. */
    LcdWriteCmd(_BV(LCD_DDRAM));

    return 0;
}
Esempio n. 11
0
/*!
 * \brief Loop for a specified number of milliseconds.
 *
 * This call will not release the CPU and will not switch to another
 * thread. Because of absent thread switching, the delay time is more
 * exact than with NutSleep().
 *
 * \param ms Delay time in milliseconds, maximum is 255.
 *
 * \deprecated New applications should use NutMicroDelay().
 */
void NutDelay(uint8_t ms)
{
    NutMicroDelay((uint32_t)ms * 1000);
}