コード例 #1
0
ファイル: main.c プロジェクト: NemProjects/CSR1010-MMA9550
/*----------------------------------------------------------------------------*
 *  NAME
 *      spiSlaveSSELStatusCallback
 *
 *  DESCRIPTION
 *      Callback issued by the SPI Slave library when slave select is asserted
 *      (start of transaction) or de-asserted (end of transaction)
 *
 *  PARAMETERS
 *      is_asserted [in]        TRUE if SSEL was asserted, FALSE if de-asserted
 *
 *  RETURNS
 *      Nothing
 *----------------------------------------------------------------------------*/
static void spiSlaveSSELStatusCallback(bool is_asserted)
{
    if (is_asserted)
    {
#ifdef ENABLE_DEBUG_PRINT
        DebugWriteString("\r\n\r\n\r\n SSEL Assert");
#else
        DebugWriteChar('<');
#endif
    }
    else
        /* If SPI Slave is de-selected, prepare the length of the next
         * transaction ready in the Tx queue */
    {
        /* Length of the data in the Rx queue */
        uint16 len = OQSize(&(g_spi_data.rx_q));

        /* Clear the Tx queue and get it ready for the next transaction */
        OQClear(&(g_spi_data.tx_q));

        /* The first octet in the next transaction is the length of the data
         * to be transferred */
        OQQueueData(&(g_spi_data.tx_q), &len, 1U);

        /* Data to be transferred in the next transaction */
        OQTransferData(&(g_spi_data.rx_q), &(g_spi_data.tx_q), len);

        /* Ask for the next data callback to be sent when the next octet is
         * received */
        SpiSlaveConfigDataStatusCallback(spiSlaveDataCallback, 1U);

        if (SpiSlaveGetSharedRAMTxDataSize() > 0)
            /* If the SPI Slave still has some un-transmitted data from the
             * previous transaction */
        {
            /* Reset the SPI Slave to remove the pending data */
            SpiSlaveReset(TRUE);
        }

        /* Update state to indicate we're waiting for the length octet */
        g_spi_data.state = state_waiting_for_len;

        /* Clear the Rx queue and get it ready for the next transaction */
        OQClear(&(g_spi_data.rx_q));

#ifdef ENABLE_DEBUG_PRINT
        DebugWriteString("\r\nSSEL De-Assert -");
        DebugWriteUint16(len);
#else
        DebugWriteChar('>');
#endif
    }
} /* spiSlaveSSELStatusCallback */
コード例 #2
0
ファイル: main.c プロジェクト: NemProjects/CSR1010-MMA9550
/*----------------------------------------------------------------------------*
 *  NAME
 *      AppInit
 *
 *  DESCRIPTION
 *      This user application function is called after a power-on reset
 *      (including after a firmware panic), after a wakeup from Hibernate or
 *      Dormant sleep states, or after an HCI Reset has been requested.
 *
 *      NOTE: In the case of a power-on reset, this function is called
 *      after AppPowerOnReset().
 *
 *  PARAMETERS
 *      last_sleep_state [in]   Last sleep state
 *
 *  RETURNS
 *      Nothing
 *----------------------------------------------------------------------------*/
void AppInit(sleep_state last_sleep_state)
{
    /* Initialise communications */
    DebugInit(1, uartRxDataCallback, NULL);

    DebugWriteString("Hello, world\r\n");
}
コード例 #3
0
static uint8 writeASCIICodedNumber(uint32 value)
{
#define BUFFER_SIZE 11          /* Buffer size required to hold maximum value */
    
    uint8  i = BUFFER_SIZE;     /* Loop counter */
    uint32 remainder = value;   /* Remaining value to send */
    char   buffer[BUFFER_SIZE]; /* Buffer for ASCII string */

    /* Ensure the string is correctly terminated */    
    buffer[--i] = '\0';
    
    /* Loop at least once and until the whole value has been converted */
    do
    {
        /* Convert the unit value into ASCII and store in the buffer */
        buffer[--i] = (remainder % 10) + '0';
        
        /* Shift the value right one decimal */
        remainder /= 10;
    } while (remainder > 0);

    /* Send the string to the UART */
    DebugWriteString(buffer + i);
    
    /* Return length of ASCII string sent to UART */
    return (BUFFER_SIZE - 1) - i;
}
コード例 #4
0
extern void HeartRateHandleAccessWrite(GATT_ACCESS_IND_T *p_ind)
{
    uint8 *p_value = p_ind->value;
    gatt_client_config client_config;
    sys_status rc = sys_status_success;

    switch(p_ind->handle)
    {
        /* Heart Rate measurement characteristic client configuration is being 
         * written 
         */
        case HANDLE_EEG_MEASUREMENT_C_CFG:
        {
            client_config = BufReadUint16(&p_value);


            /* Client Configuration is bit field value so ideally bitwise 
             * comparison should be used but since the application supports only 
             * notifications, direct comparison is being used.
             */
            if((client_config == gatt_client_config_notification) ||
               (client_config == gatt_client_config_none))
            {                            
                /* Store the new client configuration */
                g_eeg_serv_data.hr_meas_client_config = client_config;

                /* Write Heart Rate Measurement Client configuration to NVM if 
                 * the device is bonded.
                 */
                if(AppIsDeviceBonded())
                {
                     Nvm_Write((uint16*)&client_config,
                              sizeof(client_config),
                              g_eeg_serv_data.nvm_offset + 
                              HR_NVM_HR_MEAS_CLIENT_CONFIG_OFFSET);
                }

                /* Start sending the HR measurement notifications if they are 
                 * not being sent currently. 
                 */
                StartSendingHRMeasurements();
            }
            else
            {
                /* INDICATION or RESERVED */

                /* Return Error as only Notifications are supported */
                rc = gatt_status_desc_improper_config;
            }

            break;
        }

        /* EEG channels Control point is being written */
        case HANDLE_EEG_CHANNELS:
        {
            /* Extract the written value */
            g_eeg_serv_data.channel_map = BufReadUint16(&p_value);
            DebugWriteString("\n\rChannel map updated");
            break;
        }
		
		case HANDLE_EEG_ACQUISITION_RATE:
		{
            g_eeg_serv_data.acquisition_rate = BufReadUint16(&p_value);
            TimerDelete(g_eeg_serv_data.acq_tmr);
            g_eeg_serv_data.acq_tmr = TimerCreate((uint32) (1000000/g_eeg_serv_data.acquisition_rate),
                                 TRUE, 
                                 acquireData); 
			DebugWriteString("\n\rAcq Rate changed");
            break;
		}
		
        default:
        {
            /* Write is not permitted on any other characteristic/attribute */
            rc = gatt_status_write_not_permitted;
            break;
        }
    }

    /* Send ACCESS RESPONSE */
    GattAccessRsp(p_ind->cid, p_ind->handle, rc, 0, NULL);

}
コード例 #5
0
ファイル: coolie.c プロジェクト: JohnnyonFlame/jfsw_old
VOID EnemyDefaults(short SpriteNum, ACTOR_ACTION_SETp action, PERSONALITYp person)
    {
    USERp u = User[SpriteNum];
    SPRITEp sp = &sprite[SpriteNum];
    unsigned int wpn;
    short wpn_cnt;
    short depth = 0;
    extern short TotalKillable;
    extern BOOL DebugSecret;

    switch(u->ID)
        {
        case PACHINKO1:
        case PACHINKO2:
        case PACHINKO3:
        case PACHINKO4:
        case 623:
        case TOILETGIRL_R0:
        case WASHGIRL_R0:
        case CARGIRL_R0:
        case MECHANICGIRL_R0:
        case SAILORGIRL_R0:
        case PRUNEGIRL_R0:
        case TRASHCAN:
        case BUNNY_RUN_R0:
            break;
        default:
            {
            TotalKillable++;
            #if DEBUG
            if (DebugSecret)
                {
                sprintf(ds,"COUNTED: spnum %d, pic %d, x %d, y %d",SpriteNum,sp->picnum,sp->x,sp->y);
                DebugWriteString(ds);
                }
            #endif    
            }
            
        break;
        }
    
    RESET(sp->cstat, CSTAT_SPRITE_RESTORE);

    u->spal = sp->pal;
    
    u->RotNum = 5;
    sp->clipdist = (256) >> 2;
    
    u->zclip = Z(48);
    u->lo_step = Z(32);
    
    u->floor_dist = u->zclip - u->lo_step;
    u->ceiling_dist = SPRITEp_SIZE_Z(sp) - u->zclip;
    
    u->Radius = 400;
    
    u->MaxHealth = u->Health;

    u->PainThreshold = DIV16(u->Health) - 1;
    //u->PainThreshold = DIV4(u->Health) - 1;
    
    SET(sp->cstat,CSTAT_SPRITE_BLOCK|CSTAT_SPRITE_BLOCK_HITSCAN);
    SET(sp->extra,SPRX_PLAYER_OR_ENEMY);
    
    sprite[SpriteNum].picnum = u->State->Pic;
    change_sprite_stat(SpriteNum, STAT_ENEMY);
  
    u->Personality = person;
    u->ActorActionSet = action;

    DoActorZrange(SpriteNum);

    //KeepActorOnFloor(SpriteNum); // for swimming actors
    
    // make sure we start in the water if thats where we are
    if (u->lo_sectp)// && SectUser[u->lo_sectp - sector])
        {
        short i,nexti;
        short sectnum = u->lo_sectp - sector;
        
        if (SectUser[sectnum] && TEST(u->lo_sectp->extra, SECTFX_SINK))
            {
            depth = SectUser[sectnum]->depth;
            }
        else    
            {
            TRAVERSE_SPRITE_SECT(headspritesect[sectnum],i,nexti)
                {
                SPRITEp np = &sprite[i];
                if (np->picnum == ST1 && np->hitag == SECT_SINK)
                    {
                    depth = np->lotag;
                    }
                }
            }
コード例 #6
0
ファイル: main.c プロジェクト: NemProjects/CSR1010-MMA9550
/*----------------------------------------------------------------------------*
 *  NAME
 *      showHelp
 *
 *  DESCRIPTION
 *      Send help message to UART
 *
 * PARAMETERS
 *      None
 *
 * RETURNS
 *      Nothing
 *----------------------------------------------------------------------------*/
static void showHelp(void)
{
    /* Send usage information to UART */
    DebugWriteString("\r\n");
    DebugWriteString("\r\n");
    DebugWriteString("Analogue IO Example application\r\n");
    DebugWriteString("===============================\r\n");
    DebugWriteString("\r\n");
    DebugWriteString("Command syntax (<port> can be 0, 1 or 2):\r\n");
    DebugWriteString("\r\n");
    DebugWriteString("  To get measured voltage at an AIO port:  g <port>\r\n");
    DebugWriteString("  To set voltage at an AIO port:           s <port> <voltage (in mV)>\r\n");
    DebugWriteString("  To set digital voltage at an AIO port:   d <port> <0/1>\r\n");
    DebugWriteString("  To clear AIO voltage level:              c <port>\r\n");
    DebugWriteString("  To display this help message:            h\r\n");
    DebugWriteString("\r\n");
    DebugWriteString("NOTE: All the AIOs are multiplexed via an analog switch to a single\r\n");
    DebugWriteString("      physical ADC & DAC instance. Hence it is not possible to use more\r\n");
    DebugWriteString("      than one AIO port at a time\r\n");
    DebugWriteString("\r\n");
}
コード例 #7
0
ファイル: main.c プロジェクト: NemProjects/CSR1010-MMA9550
/*----------------------------------------------------------------------------*
 *  NAME
 *      processRxCmd
 *
 *  DESCRIPTION
 *      Read and process the next command from the byte queue.
 *
 * PARAMETERS
 *      None
 *
 * RETURNS
 *      Nothing
 *----------------------------------------------------------------------------*/
static void processRxCmd(void)
{
    /* Loop until the byte queue is empty */
    while (BQGetDataSize() > 0)
    {
        uint8 byte = '\0';

        /* Read in the next byte */
        if (BQPopBytes(&byte, 1) > 0)
        {
            CMD_T cmd_type;

            /* Convert byte into a command */
            switch (byte)
            {
            case 's':
            case 'S':
                cmd_type = cmd_set;
                break;
            case 'g':
            case 'G':
                cmd_type = cmd_get;
                break;
            case 'c':
            case 'C':
                cmd_type = cmd_clear;
                break;
            case 'd':
            case 'D':
                cmd_type = cmd_digital;
                break;
            case 'h':
            case 'H':
                showHelp();
                continue;
            default:
                /* Discard the byte (we don't know what to do with it) and
                 * jump back to the top of the loop.
                 */
                continue;
            }

            /* At this point a valid command has been found */
            uint32 value;

            /* Read in the port number (in ASCII) from the byte queue */
            if (readASCIICodedNumber(&value))
            {
                const aio_select port = (aio_select)value;

                /* Validate the port number */
                if ((port == value) && (port < NUMBER_OF_AIOS))
                {
                    switch (cmd_type)
                    {
                    /* Read the voltage level of an analogue port */
                    case cmd_get:
                    {
                        /* Read the analogue voltage... */
                        const uint16 mvs = AioRead(port);

                        /* ...and send it to the UART */
                        DebugWriteString("\r\nAnalog voltage measured on AIO ");
                        writeASCIICodedNumber(port);
                        DebugWriteString(" is ");
                        writeASCIICodedNumber(mvs);
                        DebugWriteString("mV\r\n");
                        break;
                    }

                    /* Clear the voltage set on an analogue port */
                    case cmd_clear:
                    {
                        /* Turn off the specified analogue port... */
                        AioOff(port);

                        /* ...and print confirmation to the UART */
                        DebugWriteString("\r\nAnalog voltage set on AIO ");
                        writeASCIICodedNumber(port);
                        DebugWriteString(" is now cleared\r\n");
                        break;
                    }

                    /* Set the requested voltage in mV on an analogue port */
                    case cmd_set:
                    {
                        uint32 vol;

                        /* Read in the requested voltage from the byte queue */
                        if (readASCIICodedNumber(&vol))
                        {
                            /* Validate the requested voltage */
                            if ((uint16)vol == vol)
                            {
                                /* Set the analogue port to the requested voltage... */
                                AioDrive(port, (uint16)vol);

                                /* ...and print confirmation to the UART */
                                DebugWriteString("\r\nAIO ");
                                writeASCIICodedNumber(port);
                                DebugWriteString(" is attempting to drive ");
                                writeASCIICodedNumber((uint16)vol);
                                DebugWriteString( "mV output\r\n");
                            }
                        }
                        break;
                    }

                    /* Set the requested digital output on an analogue port */
                    case cmd_digital:
                    {
                        uint32 vol;

                        /* Read in the requested value from the byte queue */
                        if (readASCIICodedNumber(&vol))
                        {
                            /* Validate the requested value */
                            if ((uint16)vol == vol)
                            {
                                /* Set the analogue port to the requested output... */
                                AioSetDig(port, vol);

                                /* ...and print confirmation to the UART */
                                DebugWriteString("\r\nAIO ");
                                writeASCIICodedNumber(port);
                                DebugWriteString(" is attempting to drive ");
                                DebugWriteString(vol ? "HIGH\r\n" : "LOW\r\n");
                            }
                        }
                        break;
                    }

                    default:
                        /* This case should never be called */
                        DebugWriteString("\r\nCommand not recognised\r\n");
                        break;
                    }
                }
            }
        }
    }
}
コード例 #8
0
ファイル: main.c プロジェクト: NemProjects/CSR1010-MMA9550
/*----------------------------------------------------------------------------*
 *  NAME
 *      AppInit
 *
 *  DESCRIPTION
 *      This user application function is called after a power-on reset
 *      (including after a firmware panic), after a wakeup from Hibernate or
 *      Dormant sleep states, or after an HCI Reset has been requested.
 *
 *      NOTE: In the case of a power-on reset, this function is called
 *      after app_power_on_reset().
 *
 *  PARAMETERS
 *      last_sleep_state [in]   Last sleep state
 *
 *  RETURNS
 *      Nothing
 *----------------------------------------------------------------------------*/
void AppInit(sleep_state last_sleep_state)
{
    /* Length octet for first transaction */
    uint16 len = 0U;

    /* Initialise communications */
    DebugInit(1, NULL, NULL);

    /* Set up the queue containing data to be sent to the SPI Master. The queue
     * is read by the SPI Slave library and the data transferred over to the Tx
     * area of the shared RAM when an interrupt from the PIO controller is
     * received. The application can queue data at any time.
     */
    OQSetFill(&(g_spi_data.tx_q), FALSE, 0U);
    OQCreate(g_spi_data.data_tx, MAX_TRANSACTION_SIZE, OQDataMode_packed,
            &(g_spi_data.tx_q));

    /* Set up the queue containing data received from the SPI Master. Data is
     * transferred from the Rx area of the shared memory and added to the queue
     * by the SPI Slave library when it receives an interrupt from the PIO
     * controller. The application may read data from the queue at any time,
     * but in order to prevent the buffer from overflowing and corrupting the
     * incoming data the queue should be read as soon as possible after the data
     * status callback is received.
     */
    OQSetFill(&(g_spi_data.rx_q), FALSE, 0U);
    OQCreate(g_spi_data.data_rx, MAX_TRANSACTION_SIZE, OQDataMode_packed,
            &(g_spi_data.rx_q));

    /* Only enter shallow sleep mode, because the PIO controller needs to run at
     * 16MHz in order to operate the SPI bus at ~1MHz */
    SleepModeChange(sleep_mode_shallow);

    /* Keep awake when WAKE pin is low */
    SleepWakePinEnable(wakepin_mode_low_level);

    /* Queue the length octet for the first transfer */
    OQQueueData(&(g_spi_data.tx_q), &len, 1U);

    /* Initialise the SPI Slave, and fill the Tx area of the shared RAM with the
     * general response octet, which will be sent in tha absence of any data in
     * the queue.
     */
    SpiSlaveInit(PIO_CTRLR_CODE_ADDR, spiSlaveSSELStatusCallback,
            &(g_spi_data.tx_q), &(g_spi_data.rx_q), GENERAL_RESP);

    /* Configure the SPI Slave data callback to occur when the length octet for
     * the next transaction is received. */
    SpiSlaveConfigDataStatusCallback(spiSlaveDataCallback, 1U);

    /* Set the pull-up for the SSEL pin */
    PioSetPullModes(PIO_BIT_MASK(SPI_SLAVE_PIO_SSEL), pio_mode_weak_pull_up);

    /* Set the pull-up for MOSI pin */
    PioSetPullModes(PIO_BIT_MASK(SPI_SLAVE_PIO_MOSI), pio_mode_weak_pull_up);

    /* Set the pull-up/pull-down for SCLK pin, depending on the SPI Mode */
    PioSetPullModes(PIO_BIT_MASK(SPI_SLAVE_PIO_SCLK), PIO_CTRLR_SCLK_PULL_MODE);

    /* Start the SPI slave */
    SpiSlaveStart();

    /* Set state to indicate we're ready to receive the length octet for the
     * next transaction */
    g_spi_data.state = state_waiting_for_len;

    DebugWriteString("\r\nSPI Slave test application, stores previous data sent"
            " from SPI Master and returns the data in the subsequent "
            "transactions\r\n");

    DebugWriteString("Transaction format: \r\n");

    DebugWriteString("<LEN> <delay (at least 60us)> <DATA>\r\n");

    DebugWriteString("Ready to receive data\r\n");
} /* AppInit */
コード例 #9
0
ファイル: main.c プロジェクト: NemProjects/CSR1010-MMA9550
/*----------------------------------------------------------------------------*
 *  NAME
 *      spiSlaveDataCallback
 *
 *  DESCRIPTION
 *      Data status callback issued by the SPI Slave library when a previously
 *      set threshold number of octets have been received, or a SPI transaction
 *      has completed because the Slave has been de-selected. In this case
 *      p_rx_q will refer to the queue containing the received data.
 *
 *      It will also be issued to notify the application that a certain amount
 *      of data has been transferred over to the Tx area of the shared RAM for
 *      onward transmission to the SPI Master. This allows the application to
 *      keep track of the size of the Tx queue and keep adding more data as
 *      required. In this case p_rx_q will be NULL.
 *
 *  PARAMETERS
 *      p_rx_q [in]             Rx queue handle when data has been received or
 *                              a transaction has completed.
 *                              NULL when data has been transferred from the Tx
 *                              queue into the Tx area of shared RAM.
 *      p_tx_q [in]             Tx queue handle.
 *      tx_data_size [in]       Number of octets that have been transferred over
 *                              to the Tx area of the shared RAM
 *
 *  RETURNS
 *      Nothing
 *----------------------------------------------------------------------------*/
static void spiSlaveDataCallback(OQ_HANDLE p_rx_q,
                                 OQ_HANDLE p_tx_q,
                                 uint16 tx_data_size)
{
    /* Check whether callback has been issued because more data has arrived */
    if (p_rx_q != NULL)
    {
        /* Number of octets received */
        const uint16 rx_data_size = OQSize(p_rx_q);
        
        if (rx_data_size > 0)
        {
            if (g_spi_data.state == state_waiting_for_len)
                /* If waiting for length octet */
            { 
                /* Value of the length octet */
                uint16 len = 0U;

                if (OQPopData(p_rx_q, &len, 1U))
                {
                    /* Ask for the next callback to be sent when the stated
                     * number of octets have been received */
                    SpiSlaveConfigDataStatusCallback(spiSlaveDataCallback, len);

                    /* Update the state to indicate we're waiting for the
                     * data */
                    g_spi_data.state = state_waiting_for_data;

#ifdef ENABLE_DEBUG_PRINT
                    DebugWriteString("\r\nRx Len: 0x");
                    DebugWriteUint16(len);
#else
                    DebugWriteChar('L');
#endif
                }
            }
            else /* (g_spi_data.state == state_waiting_for_data) */
                /* If waiting for the actual data */
            {
#ifdef ENABLE_DEBUG_PRINT
                DebugWriteString("\r\nRx Data Len: 0x");
                DebugWriteUint16(rx_data_size);
#else
                DebugWriteChar('D');
#endif
            }
        }
        else
            /* No data in the Rx queue, we should not have received this
             * callback */
        {
#ifdef ENABLE_DEBUG_PRINT
            DebugWriteString("\r\nSpurious callback: RxDataSize: 0x");
            DebugWriteUint16(rx_data_size);
            DebugWriteString(" TxDataSize: 0x");
            DebugWriteUint16(tx_data_size);
            DebugWriteString(" RemTxDataSize: 0x");
            DebugWriteUint16(OQSize(p_tx_q));
#else
            DebugWriteChar('?');
#endif
        }
    }
    
    /* Ignore callback if issued because more data has been transferred from
     * the Tx queue to the Tx area of the shared memory. */
} /* spiSlaveDataCallback */
コード例 #10
0
ファイル: main.c プロジェクト: NemProjects/CSR1010-MMA9550
/*----------------------------------------------------------------------------*
 *  NAME
 *      AppInit
 *
 *  DESCRIPTION
 *      This user application function is called after a power-on reset
 *      (including after a firmware panic), after a wakeup from Hibernate or
 *      Dormant sleep states, or after an HCI Reset has been requested.
 *
 *      NOTE: In the case of a power-on reset, this function is called
 *      after AppPowerOnReset().
 *
 * PARAMETERS
 *      last_sleep_state [in]   Last sleep state
 *
 * RETURNS
 *      Nothing
 *----------------------------------------------------------------------------*/
void AppInit(sleep_state last_sleep_state)
{
    /* Initialise UART communications */
    DebugInit(1, NULL, NULL);

    DebugWriteString("Configuring PWM Modes\r\n");

    /* Configure the output PIO on which the slow flashing LED signal is
     * generated */
    PioSetDir(PIO_LED, PIO_DIR_OUTPUT);

    /* SLOW FLASHING WITH PWM:
     * Configure PWM 0 to have the following characteristics
     * DULL LED Light is generated by having pulses of 0ms ON and
     *      6ms OFF (~0% duty cycle)
     * BRIGHT LED Light is generated by having pulses of 6ms ON and
     *      0ms OFF (~100% duty cycle)
     * Dullest and Brightest level are held for ~1s
     *
     * The brightness level ramps for ~1s when going from dullest to
     * brightest and vice-versa */
    if (PioConfigPWM(0, pio_pwm_mode_push_pull,
                     /* Pulse timings for the dullest part of the sequence:
                      * dullest part of the sequence has the pulse off for the whole
                      * period, in effect the line stays low for the duration for which
                      * the dullest part of the sequence lasts. */
                     0,          /* ON time for the pulse is 0us */
                     255,        /* OFF time for the pulse is (255 * 30)us */
                     62,         /* Dullest part of the sequence lasts for
                            ( 62 * 16 )ms before ramping up to the brightest
                            part of the sequence */

                     /* Pulse timings for the brightest part of the sequence:
                      * brightest part of the sequence has the pulse ON for the whole
                      * period, in effect the line stays high for the duration for which
                      * the brightest part of the sequence lasts. */
                     255,        /* ON time for the pulse is (255 * 30)us */
                     0,          /* OFF time for the pulse is 0us */
                     62,         /* Brightest part of the sequence lasts for
                            ( 62 * 16 )ms before ramping down to the dullest
                            part of the sequence */

                     /* Ramping between dullest and brightest parts of the sequence
                      * This parameter determines the duration for which the ramping
                      * lasts when going from dullest to the brightest (and vice-versa).
                      *
                      * The total duration for which the ramping lasts is determined by
                      * multiplying this value with one less than the difference between
                      * the on_time or off_time of the two states, whichever is bigger;
                      * in the units of 30us
                      * */
                     132         /* Ramping lasts for ((255-1) * 132 * 30)us */
                    ))
    {
        DebugWriteString("PWM0 was set to ramp between brightest and dullest "
                         "levels\r\n");

        /* Connect PWM0 output to LED */
        PioSetMode(PIO_LED, pio_mode_pwm0);

        /* Enable the PWM0 */
        PioEnablePWM(0, TRUE);
    }
    else
    {
        DebugWriteString("PWM0 couldn't be configured\r\n");
    }

    /* Set both outputs to have strong internal pull ups */
    PioSetPullModes((1UL << PIO_MOTOR) | (1UL << PIO_LED),
                    pio_mode_strong_pull_up);

    /* Configure motor PIO to be output */
    PioSetDir(PIO_MOTOR, PIO_DIR_OUTPUT);

    /* Connect PWM1 output to motor PIO */
    PioSetMode(PIO_MOTOR, pio_mode_pwm1);

    /* Initialise timers */
    TimerInit(MAX_APP_TIMERS, app_timers);

    /* Call the function (with a dummy timer ID to start with) to configure
     * the PWM1 with initial duty cycle and start a timer. When the timer
     * expires the same function gets called again and the duty cycle for
     * PWM1 gets updated. It takes care of restarting the timer and ensuring
     * that duty cycle alternates between 0% and 100% back and forth. */
    dutyCycleTask(TIMER_INVALID);

    /* Enable the PWM1 */
    PioEnablePWM(1, TRUE);
}