csr8670音频发射器.doc
CSR867x — CSR8670平台开发调试经验.doc
/*
This file was autogenerated by ButtonParsePro
*/
#include "source_buttons.h"
#include
#include
#include
#include
#include
#include
#include
/* Pio bits that trigger messages */
#define MSG_BITS (BUTTON_PAIR_CONNECT|BUTTON_POWER|CHARGER)
/* Pio masks that requires map before use it */
#define PIO_MAP_MASK ((uint32)(0x1FFFE000))
/* Pio bits that trigger a raw message */
#define RAW_BITS 0
/* Charger to local PIO map defines */
#define MAP_BUTTON_POWER 23
#define MAP_CHARGER 22
/* Mask of bits mapped to CHARGER events */
#define CHG_MASK (1UL< /* Mask of bits mapped to External PIO events */ #define EXT_MASK 0 static const PioActionMessage action_table[] = { { BUTTON_PAIR_CONNECT, BUTTON_PAIR_CONNECT, HELD, 2000, 0, BUTTON_MSG_ENTER_PAIRING_MODE }, { BUTTON_PAIR_CONNECT, BUTTON_PAIR_CONNECT, HELD, 7000, 0, BUTTON_MSG_RESET_PAIRED_DEVICE_LIST }, { BUTTON_POWER, BUTTON_POWER, HELD, 2000, 0, BUTTON_MSG_ON_OFF_HELD }, { CHARGER, CHARGER, ENTER, 0, 0, CHARGER_CONNECTED }, { BUTTON_PAIR_CONNECT, BUTTON_PAIR_CONNECT, RELEASE, 0, 0, BUTTON_MSG_CONNECT }, { BUTTON_POWER, BUTTON_POWER, RELEASE, 0, 0, BUTTON_MSG_ON_OFF_RELEASE }, { CHARGER, CHARGER, RELEASE, 0, 0, CHARGER_DISCONNECTED } }; /* Task messages */ enum { internal_held_timer_message, internal_repeat_timer_message, internal_held_release_timer_message, internal_double_timer_message, pio_external_message }; static void enterAction( PioState *piostate, const PioActionMessage *pam, pio_bits_t pio_bits ) { /* If all the bits, for the msg, are 'on', and at least one of those bits, * was just turned on, then ... */ if ( pam->bits == (pio_bits & pam->mask) ) { /* A new enter action cancels any existing repeat timer */ (void) MessageCancelAll( &piostate->task, internal_repeat_timer_message ); MessageSend(piostate->client, pam->message, 0); /* if there is a repeat on this action, start the repeat timer */ if (pam->repeat) { piostate->stored.repeat = pam; MessageSendLater( &piostate->task, internal_repeat_timer_message, 0, pam->repeat ); } else piostate->stored.repeat = 0; } /* if any of the bits are turned off and there is a repeat timer, * cancel it and clear the stored PAM */ else if ( pam->repeat && piostate->stored.repeat == pam && pam->bits == (piostate->stored.pio_bits & pam->mask) && pam->bits != (pio_bits & pam->mask) ) { (void) MessageCancelAll( &piostate->task, internal_repeat_timer_message ); piostate->stored.repeat = 0; } } /* There can be 1 held action/messages on the same PIO */ static void heldAction( PioState *piostate, const PioActionMessage *pam, pio_bits_t pio_bits ) { /* If all the PIO, for the msg, are 'on'... */ if ( pam->bits == (pio_bits & pam->mask) ) { /* Send a pointer to this PAM as part of the timer message so that it * can be handled when the timeout expired */ const PioActionMessage **m = (const PioActionMessage **) PanicNull( malloc(sizeof(const PioActionMessage *)) ); *m = pam; MessageSendLater( &piostate->task, internal_held_timer_message, m, pam->timeout ); } /* If any of the bits are turned off... */ else if ( pam->bits == (piostate->stored.pio_bits & pam->mask) && pam->bits != (pio_bits & pam->mask) ) { /* Cancel any active held or repeat timers. */ if (!MessageCancelAll(&piostate->task, internal_held_timer_message)) { (void) MessageCancelAll( &piostate->task, internal_repeat_timer_message ); } } } static void pioChanged(Task task, PioState *piostate, pio_bits_t pio_bits) { pio_bits_t changed = piostate->stored.pio_bits ^ pio_bits; /* If any of the msg bits have changed... */ if (changed & MSG_BITS) { /* Go through the action table to determine what action to do & * message may need to be sent. */ const PioActionMessage *pam; /* Only interested in the pio bits that trigger messages. */ pio_bits_t pio_msg_bits = pio_bits & MSG_BITS; for ( pam = action_table; pam != &(action_table[ sizeof(action_table)/sizeof(PioActionMessage) ]); pam ) { if (changed & pam->mask) { switch (pam->action) { case ENTER: enterAction(piostate, pam, pio_msg_bits); break; case RELEASE: /* Only a release if the PIO were previously on and now * have been turned off, and a release message was not * to be supressed */ if (pam->bits == (piostate->stored.pio_bits & pam->mask) && pam->bits != (pio_msg_bits & pam->mask) && ( pam->bits != ( piostate->stored.pio_release_disabled & pam->mask )) ) { MessageSend(piostate->client, pam->message, 0); } /* Re-enable Release messages for the next release action */ piostate->stored.pio_release_disabled &= ~(pam->bits); break; case HELD: heldAction(piostate, pam, pio_msg_bits); break; default: break; } } } } /* store the bits previously reported */ piostate->stored.pio_bits = pio_bits; } static void pioHandler(Task task, MessageId id, Message data) { PioState *piostate = (PioState *) task; switch(id) { case MESSAGE_PIO_CHANGED: { const MessagePioChanged *mpc = (const MessagePioChanged *)data; /* Only change the actual PIO bits. Xor with pskey_wakeup * for pio that are active low not active high */ pio_bits_t pio_bits = (piostate->stored.pio_bits & (CHG_MASK|EXT_MASK)) | (mpc->state ^ piostate->stored.pskey_wakeup) | (((uint32)mpc->state16to31) << 16); pioChanged(task, piostate, pio_bits); } break; case MESSAGE_CHARGER_CHANGED: { const MessageChargerChanged *m = (const MessageChargerChanged *)data; pio_bits_t pio_bits = ((uint32)m->charger_connected< ((uint32)m->vreg_en_high< (piostate->stored.pio_bits & ~CHG_MASK); pioChanged(task, piostate, pio_bits); } break; /* If a pio has been HELD for the timeout required, then * send the message stored. */ case internal_held_timer_message: { const PioActionMessage **m = (const PioActionMessage**) data; const PioActionMessage *pam = *m; MessageSend( piostate->client, pam->message, 0 ); /* Cancel any existing repeat timer that may be running */ (void) MessageCancelAll( &piostate->task, internal_repeat_timer_message ); /* Now that a held message has been issued, suppress future release messages*/ piostate->stored.pio_release_disabled |= pam->bits; /* If there is a repeat action start the repeat on * this message and store the PAM. */ if (pam->repeat) { MessageSendLater( &piostate->task, internal_repeat_timer_message, 0, pam->repeat ); piostate->stored.repeat = pam; } } break; case internal_repeat_timer_message: if (piostate->stored.repeat) { MessageSend( piostate->client, (piostate->stored.repeat)->message, 0 ); /* Start the repeat timer again */ MessageSendLater( &piostate->task, internal_repeat_timer_message, 0, (piostate->stored.repeat)->repeat ); } break; default: break; } } void pioInit(PioState *piostate, Task client) { MessagePioChanged *mpc = malloc(sizeof(MessagePioChanged)); uint32 pio_val = PioGet32(); uint16 pskey_wakeup = 0; MessageChargerChanged *mcc = malloc(sizeof(MessageChargerChanged)); bool vreg_en = PsuGetVregEn(); bool chgr_en; { charger_status status = ChargerStatus(); if ( status == TRICKLE_CHARGE || status == FAST_CHARGE || status == STANDBY ) chgr_en = TRUE; else chgr_en = FALSE; } piostate->task.handler = pioHandler; piostate->client = client; /* Retrieve the PIO Deep Sleep wake up state PS Key. which indicates * the state that a PIO must be in to wake the chip from deep sleep. * This therefore also indicates if a PIO is reversed in effect e.g * active low instead of active high. * The default is all PIO are active high e.g. 0xFFFF. */ { uint16 pskey_val = 0xFFFF; PsFullRetrieve(PSKEY_PIO_WAKEUP_STATE, &pskey_val, sizeof(pskey_val)); pskey_wakeup = pskey_wakeup | ~pskey_val; } PsFullRetrieve(PSKEY_PIO_WAKEUP_STATE, &pskey_wakeup, sizeof(pskey_wakeup)); pskey_wakeup = ~pskey_wakeup; /* Set the initial pio states for the task. */ piostate->stored.pskey_wakeup = pskey_wakeup; piostate->stored.pio_bits = (pio_val ^ pskey_wakeup) & (RAW_BITS); /* Initalise PAM stored states to 0. */ piostate->stored.held_release = 0; piostate->stored.double_tap = 0; piostate->stored.repeat = 0; piostate->stored.pio_release_disabled = 0; /* Set the Pio Task handler to this button handler. */ (void) MessagePioTask(&piostate->task); /* If the message button has been mapped by firmware, panic it.*/ if(PioGetMapPins32() & MSG_BITS) { Panic(); } /* Map some message PIOs */ if(PIO_MAP_MASK & MSG_BITS) { PioSetMapPins32((PIO_MAP_MASK & MSG_BITS), (PIO_MAP_MASK & MSG_BITS)); } /* Set the Debounce for all pio - Message bits and Raw bits. * Exclude PIO bits that are mapped to charger or ext messages */ if ( PioDebounce32( (uint32)(RAW_BITS|MSG_BITS)^(CHG_MASK|EXT_MASK), 1, 0 ) ) { Panic(); /* If the result is not zero (0) then a PIO that cannot be used * as an input has been defined in the PioDebounce32() call. * The PioDebounce will not have been set in this case so * the VM application is panicked. */ } /* Set the Message Charger handler (VGEN and CHG) to this button * handler. */ (void) MessageChargerTask(&piostate->task); /* Set the Debounce for all Charger events. */ ChargerDebounce((CHARGER_VREG_EVENT|CHARGER_CONNECT_EVENT), 1, 0); /* Send an intial message to indicate pio status */ mpc->state = (uint16)(pio_val & (RAW_BITS|MSG_BITS)); mpc->state16to31 = (uint16)((pio_val & (RAW_BITS|MSG_BITS)) >> 16); mpc->time = 0; MessageSend(&piostate->task, MESSAGE_PIO_CHANGED, mpc); /* Send an inital message to indicate charger status */ mcc->charger_connected = chgr_en; mcc->vreg_en_high = vreg_en; MessageSend(&piostate->task, MESSAGE_CHARGER_CHANGED, mcc); }