int main(void) {
    uint8_t  currState;
    uint8_t  targetState;
    uint16_t readbcLength;
    uint32_t nwkId;
    uint8_t  errorCheckInterval = 100;

    // Stop watchdog timer to prevent time out reset
    WDTCTL = WDTPW + WDTHOLD;

    // Initialize the MCU and board peripherals
    halBoardInit();
    halBoardStartXT1();	
    halBoardSetSystemClock(SYSCLK_16MHZ);
    halButtonsInit(BUTTON_ALL);
    halLcdInit();
    halLcdBackLightInit();
    halLcdSetContrast(90);
    halLcdSetBackLight(10);
    halLcdClearScreen();

    halLcdPrintLine("  CC85XX SLAVE   ", 0, OVERWRITE_TEXT );
    halLcdPrintLine("                 ", 1, OVERWRITE_TEXT );
    halLcdPrintLine("S1: Power toggle ", 2, OVERWRITE_TEXT );
    halLcdPrintLine("S2: Pairing start", 3, OVERWRITE_TEXT );
    uifLcdPrintJoystickInfo();

    // Wipe remote control information
    memset(&ehifRcSetDataParam, 0x00, sizeof(ehifRcSetDataParam));

    // Initialize EHIF IO
    ehifIoInit();

    // Reset into the application
    ehifSysResetPin(true);
    currState = CC85XX_STATE_ALONE;
    targetState = CC85XX_STATE_ACTIVE;

    // Get the last used network ID from CC85XX non-volatile storage
    initParam();
    ehifCmdParam.nvsGetData.index = 0;
    ehifCmdExecWithRead(EHIF_EXEC_ALL, EHIF_CMD_NVS_GET_DATA, 
                        sizeof(EHIF_CMD_NVS_GET_DATA_PARAM_T), &ehifCmdParam, 
                        sizeof(EHIF_CMD_NVS_GET_DATA_DATA_T), &ehifCmdData);
    nwkId = ehifCmdData.nvsGetData.data;

    // Handle illegal default network IDs that may occur first time after programming
    if ((nwkId == 0x00000000) || (nwkId == 0xFFFFFFFF)) {
        nwkId = 0xFFFFFFFE;
    }

    // Main loop
    while (1) {

        // Wait 10 ms
        EHIF_DELAY_MS(10);

        // Perform action according to edge-triggered button events (debouncing with 100 ms delay)
        switch (pollButtons()) {

        // POWER TOGGLE
        case BUTTON_S1:
            if (currState == CC85XX_STATE_OFF) {
                targetState = CC85XX_STATE_ACTIVE;
            } else {
                targetState = CC85XX_STATE_OFF;
            }
            break;

        // PAIRING TRIGGER
        case BUTTON_S2:
            if (currState != CC85XX_STATE_OFF) {
                targetState = CC85XX_STATE_PAIRING;
            }
            break;
        }

        // Run the state machine
        if (currState != targetState) {

            if (currState == CC85XX_STATE_OFF) {
                // HANDLE POWER ON

                // Ensure known state (power state 5)
                ehifSysResetPin(true);
                currState = CC85XX_STATE_ALONE;

            } else if (targetState == CC85XX_STATE_OFF) {
                // HANDLE POWER OFF

                // Ensure known state (power state 5)
                ehifSysResetPin(true);
                currState = CC85XX_STATE_ALONE;

                // Set power state 0
                ehifCmdParam.pmSetState.state = 0;
                ehifCmdExec(EHIF_CMD_PM_SET_STATE, sizeof(EHIF_CMD_PM_SET_STATE_PARAM_T), &ehifCmdParam);
                currState = CC85XX_STATE_OFF;

            } else if (targetState == CC85XX_STATE_PAIRING) {
                // HANDLE PAIRING

                // Let the last executed EHIF command complete, with 5 second timeout
                ehifWaitReadyMs(5000);

                // Disconnect if currently connected
                if (ehifGetStatus() & BV_EHIF_STAT_CONNECTED) {
                    initParam();
                    // All parameters should be zero
                    ehifCmdExec(EHIF_CMD_NWM_DO_JOIN, sizeof(EHIF_CMD_NWM_DO_JOIN_PARAM_T), &ehifCmdParam);
                }

                // Search for one protocol master with pairing signal enabled for 10 seconds
                initParam();
                ehifCmdParam.nwmDoScan.scanTo           = 1000;
                ehifCmdParam.nwmDoScan.scanMax          = 1;
                ehifCmdParam.nwmDoScan.reqPairingSignal = 1;
                ehifCmdParam.nwmDoScan.reqRssi          = -128;
                ehifCmdExecWithReadbc(EHIF_EXEC_CMD, EHIF_CMD_NWM_DO_SCAN, 
                                      sizeof(EHIF_CMD_NWM_DO_SCAN_PARAM_T), &ehifCmdParam, 
                                      NULL, NULL);

                // Fetch network information once ready
                ehifWaitReadyMs(12000);
                readbcLength = sizeof(ehifNwmDoScanData);
                ehifCmdExecWithReadbc(EHIF_EXEC_DATA, EHIF_CMD_NWM_DO_SCAN, 
                                      0, NULL, 
                                      &readbcLength, &ehifNwmDoScanData);

                // If found ...
                if (readbcLength == sizeof(EHIF_CMD_NWM_DO_SCAN_DATA_T)) {

                    // Update the network ID to be used next
                    nwkId = ehifNwmDoScanData.deviceId;

                    // Place the new network ID in CC85XX non-volatile storage
                    initParam();
                    ehifCmdParam.nvsSetData.index = 0;
                    ehifCmdParam.nvsSetData.data  = ehifNwmDoScanData.deviceId;
                    ehifCmdExec(EHIF_CMD_NVS_SET_DATA, sizeof(EHIF_CMD_NVS_SET_DATA_PARAM_T), &ehifCmdParam);
                }

                // Done
                currState = CC85XX_STATE_ALONE;
                targetState = CC85XX_STATE_ACTIVE;

            } else if (targetState == CC85XX_STATE_ACTIVE) {

                // We're disconnected. Proceed only if EHIF is ready, so that power toggle and pairing
                // buttons can still be operated
                uint16_t status = ehifGetStatus();
                if (status & BV_EHIF_STAT_CMD_REQ_RDY) {

                    // Perform join operation first and then activate audio channels. We're using remote
                    // volume control
                    if (!(status & BV_EHIF_STAT_CONNECTED)) {

                        // Enable disconnection notification to avoid unnecessary EHIF activity while active
                        initParam();
                        ehifCmdParam.ehcEvtClr.clearedEvents = BV_EHIF_EVT_NWK_CHG;
                        ehifCmdExec(EHIF_CMD_EHC_EVT_CLR, sizeof(EHIF_CMD_EHC_EVT_CLR_PARAM_T), &ehifCmdParam);
                        initParam();
                        ehifCmdParam.ehcEvtMask.irqGioLevel = 0;
                        ehifCmdParam.ehcEvtMask.eventFilter = BV_EHIF_EVT_NWK_CHG;
                        ehifCmdExec(EHIF_CMD_EHC_EVT_MASK, sizeof(EHIF_CMD_EHC_EVT_MASK_PARAM_T), &ehifCmdParam);

                        // Not connected: Start JOIN operation
                        initParam();
                        ehifCmdParam.nwmDoJoin.joinTo = 100;
                        ehifCmdParam.nwmDoJoin.deviceId = nwkId;
                        ehifCmdExec(EHIF_CMD_NWM_DO_JOIN, sizeof(EHIF_CMD_NWM_DO_JOIN_PARAM_T), &ehifCmdParam);

                    } else {
                        // Connected: Subscribe to audio channels (0xFF = unused)
                        memset(&ehifCmdParam, 0xFF, sizeof(EHIF_CMD_NWM_ACH_SET_USAGE_PARAM_T));
                        ehifCmdParam.nwmAchSetUsage.pAchUsage[0] = 0; // Front left  -> I2S LEFT
                        ehifCmdParam.nwmAchSetUsage.pAchUsage[1] = 1; // Front right -> I2S RIGHT
                        ehifCmdExec(EHIF_CMD_NWM_ACH_SET_USAGE, sizeof(EHIF_CMD_NWM_ACH_SET_USAGE_PARAM_T), &ehifCmdParam);
                        currState = CC85XX_STATE_ACTIVE;
                    }
                }
            }

        } else {

            // Only OFF and ACTIVE are permanent target states. SCAN is only a temporary target state.
            // In the OFF state we do nothing, so only need to handle the ACTIVE state.
            if (currState == CC85XX_STATE_ACTIVE) {

                // Detect network disconnection without generating noise on the SPI interface
                if (EHIF_INTERRUPT_IS_ACTIVE()) {
                    currState = CC85XX_STATE_ALONE;
                }

                // Perform error checking at 10 ms * 100 = 1 second intervals:
                // - No timeouts or SPI errors shall have occurred
                // - We should be connected unless disconnection has been signalized
                if (--errorCheckInterval == 0) {
                    errorCheckInterval = 100;
                    uint16_t status = ehifGetStatus();
                    if (ehifGetWaitReadyError() || (status & BV_EHIF_EVT_SPI_ERROR) ||
                        (!(status & BV_EHIF_STAT_CONNECTED) && !(status & BV_EHIF_EVT_NWK_CHG))) {

                        // The device is in an unknown state -> restart everything
                        ehifSysResetPin(true);
                        currState = CC85XX_STATE_ALONE;
                    }
                }

                // If the network connection is up and running...
                if (currState == CC85XX_STATE_ACTIVE) {

                    // Send remote control commands (mouse or play control, depending on which uif file
                    // is included in the build)
                    if (uifPollFunc(&ehifRcSetDataParam)) {
                        ehifCmdExec(EHIF_CMD_RC_SET_DATA, sizeof(EHIF_CMD_RC_SET_DATA_PARAM_T), &ehifRcSetDataParam);
                    }
                }
            }
        }
    }

} // main
Beispiel #2
0
uint8_t editNumber(S32MMSValCb_t* s32, uint8_t aY)
{
    // aY is the current yPos from were the edit was triggered
    /**
     * calculate the rectangle height on the display: 
     *    fontheight + 1 pix on top + 1 pix at bottom + 2*2 pix for the frame 
     */
    int32_t valBackup = s32->m_val; // backup the old value
    uint8_t fontHeight = FONTHEIGHT(EDITFONT);
    // re-use aY
    aY = (aY < LCDHEIGHT/2 - 9 ? aY+11: aY - 25);

    // maximum size, for a scaled long: "-2123456.789" + 1 leading blank + 0x00 = 14
    char valBuf[14]; 
    // put this in a block to release memory after calculation
    { 
        // get the biggest absolute value to calculate longest
        // possible string
        uint32_t min = (s32->m_min < 0) ? -s32->m_min : s32->m_min;
        uint32_t max = (s32->m_max < 0) ? -s32->m_max : s32->m_max;
        valBuf[0] = ' '; // leading blank
        valBuf[1] = '-'; // prepend minus-sign
        valBuf[2] = '.'; // prepend decimal point
        ltoa( (max > min ? max : min), valBuf+2, 10);
        //        maxDigits = strlen(valBuf+2);
    }

    uint8_t textLength = lcdBufPuts(AT_RAM, valBuf, &EDITFONT, 0, 0, LA_CHARWIDTHONLY); 
    
    uint8_t x = (LCDWIDTH - textLength - 8) / 2;     
    drawEditFrame(x, aY, textLength, fontHeight);
    x += 4;
    aY += 4;
    uint8_t endX = x + textLength;
    uint8_t clearLength = textLength;
    uint8_t key = 0;
    uint8_t accel = 1;
    int32_t step = 1;

    CallbackFunctor_t cb = s32->m_callback;

    // call the callback if exists
    if (cb)
        cb(CT_ENTRY, s32); 

    do
    {
        /** 
         * procedure: - clear rectangle
         *              write value to string
         *              length = (write string to ldcBuffer, width_only)
         *              clear area of (width x length)
         *              paint rectangle
         *              write string to lcdbuffer(last digit inverse)
         *              display buffer
         *              read key
         *                if (enter) update & return
         *                if (back) return
         *                if (accel) inc-value <<= 2;
         *                   else inc-value = 1; 
         *                if (up) increase
         *                if (down) decrease
         */
        
        lcdBufFillRect(x, aY, clearLength, fontHeight+1, COL_WHITE);
        // write current value
        ltoa(s32->m_val, valBuf, 10);

        if (s32->m_scale)
            rescale(s32->m_scale, valBuf);

        // get size in pixels
        textLength = lcdBufPuts(AT_RAM, valBuf, &EDITFONT, 0, 0, LA_CHARWIDTHONLY);
        uint8_t xt = endX - textLength;

        lcdBufPuts(AT_RAM, valBuf, &EDITFONT, xt, aY, COL_BLACK);
        //        lcdBufPuts(AT_RAM, valBuf, &EDITFONT, endX - textLength, aY, COL_BLACK);

        uint8_t iconMask = BT_BACK|BT_ENTER;
        if (s32->m_val > s32->m_min) 
            iconMask |= BT_MINUS;
        if (s32->m_val < s32->m_max) 
            iconMask |= BT_PLUS;

        setIcons(IT_EDIT, iconMask);
        lcdUpdate(1);

        key = pollButtons(BT_ALL, BF_ACCEL|BF_DELAY); 

        if (key & BF_ACCEL)
        {
            if (accel == 10)
            {
                accel = 1;
                if (step < (s32->m_max/8))
                    step *= 8;
            }
            else
                ++accel;
        }
        else
        {
            accel = 1;
            step = 1;
        }

        switch (key & 0xF0) // clean code
        {
            case BT_BACK: 
            case BT_ENTER:
                break;

            case BT_PLUS: 
                s32->m_val += step;
                if (s32->m_val > s32->m_max)
                    s32->m_val = s32->m_max;
                break;
            case BT_MINUS: 
                s32->m_val -= step; 
                if (s32->m_val < s32->m_min)
                    s32->m_val = s32->m_min;
                break;
        } // switch key
        
        // call the callback if exists
        if (cb)
            cb((CT_CHANGE | (key & 0xF0)), s32); 
    } while (! (key & (BT_BACK | BT_ENTER)) );

    if (key & BT_BACK) // restore old value if BT_BACK was pressed
        s32->m_val = valBackup;
    if (cb)
        cb((CT_RETURN | (key & 0xF0)), s32);     
    return key & 0xF0; // return pure key
} // editNumber (s32 ..)
Beispiel #3
0
int main(void)
{
	// Configure port directions
	DDRB = 0xFF;
	DDRC = 0xFF;
	DDRD = 0xFF;
	
	// Clear all ports
	PORTB = 0x00;
	PORTC = 0x00;
	PORTD = 0x00;
	
	// Power up delay of 1 second
	// This is required since we don't have a capacitor on the reset line
	// which can cause the reset to bounce as power ramps up after being
	// turned on
	for (unsigned int delay = 0; delay < 100; delay++) _delay_ms(10);
	
	// Initialise the TLC5940s
	initialiseTlc5940();

	// Initialise the LED fading control
	initialiseFadingLeds();
	
	// Enable interrupts globally
	sei();
	
	// Initialise the DS1302 RTC
	initialiseRTC();
	
	// Check if the RTC is set or unset (first run)
	if (readClockStatus() == CLOCK_UNSET)
	{
		// Clock is unset, so we set it to 00:00
		datetime.hours = 0;
		datetime.minutes = 0;
		datetime.seconds = 0;
		datetime.dayNo = 0;
		datetime.day = 12;
		datetime.month = 6;
		datetime.year = 11;
		
		// Set the clock
		setRTC();
	}
	
	// Initialise the LDR
	initialiseLdr();
	
	// Initialise the buttons
	initialiseButtons();
	
	// Initialise state-machine to run power-up test
	unsigned char clockState = STATE_CHASETEST;
	//unsigned char clockState = STATE_CLOCKRUNNING;
	
	// Set the start brightness
	int displayBrightness = 4095;
	
	// State-machine delay counter
	unsigned int delayCounter1 = 0;
	
	// Button functions are hours, minutes, LDR on/off and test
	unsigned char minuteButtonDownFlag = 0;
	unsigned char hourButtonDownFlag = 0;
	
	unsigned char ldrActiveFlag = 1; // LDR is active
	
	// Set the led fading speed
	setLedFadeSpeed(30, 100);
	
	while(1)
	{
		// Update the delay counter
		delayCounter1++;
		
		// Poll the button states
		pollButtons();
		
		// Clock running state
		if (clockState == STATE_CLOCKRUNNING)
		{
			// Update the clock display ------------------------------------------------------------------
			if (delayCounter1 > 30000)
			{	
				int minuteOfDay = 0;
			
				// Read the real-time clock
				readRTC();
			
				// Calculate the minute of the day
				minuteOfDay = (datetime.hours * 60) + datetime.minutes;
			
				// Update the display
				displayMinute(minuteOfDay, displayBrightness);
				
				// Reset the delay counter
				delayCounter1 = 0;
			}
			
			// Button handling ---------------------------------------------------------------------------
			
			// Minute button pressed?
			if (button[BUTTON_MINUTE].buttonState == PRESSED && minuteButtonDownFlag == 0)
			{
				// Read the current time
				readRTC();
				
				// Advance one minute and reset seconds
				if (datetime.minutes == 59)
				{
					datetime.minutes = 0;
				}
				else datetime.minutes++;
				datetime.seconds = 0;
				
				// Set the RTC
				setRTC();
				
				minuteButtonDownFlag = 1;
			}
			
			// Minute button released?
			if (button[BUTTON_MINUTE].buttonState == RELEASED && minuteButtonDownFlag == 1)
			{
				minuteButtonDownFlag = 0;
			}
			
			// Hour button pressed?
			if (button[BUTTON_HOUR].buttonState == PRESSED && hourButtonDownFlag == 0)
			{
				// Read the current time
				readRTC();
				
				// Advance one hour and reset seconds
				if (datetime.hours == 23)
				{
					datetime.hours = 0;
				}
				else datetime.hours++;
				datetime.seconds = 0;
				
				// Set the RTC
				setRTC();
				
				hourButtonDownFlag = 1;
			}
			
			// Minute button released?
			if (button[BUTTON_HOUR].buttonState == RELEASED && hourButtonDownFlag == 1)
			{
				hourButtonDownFlag = 0;
			}
			
			// Test button pressed? If so change state
			if (button[BUTTON_TEST].buttonState == 1) clockState = STATE_CHASETEST;
			
			// LDR brightness control --------------------------------------------------------------------
			if (ldrActiveFlag == 1)
			{
				unsigned int ldrValue = 0;
				
				// Read the LDR brightness level (0-15)
				ldrValue = readLdrValue();
				
				// Here we use a switch statement to translate the LDR level into the brightness
				// level for the PWM (which allows us to choose a logarithmic or linear scale)
				switch(ldrValue)
				{
					case 0 :	displayBrightness = 100;
								break;
					
					case 1 :	displayBrightness = (4095/16) * 1;
								break;
					
					case 2 :	displayBrightness = (4095/16) * 2;
								break;
					
					case 3 :	displayBrightness = (4095/16) * 3;
								break;
					
					case 4 :	displayBrightness = (4095/16) * 4;
								break;
					
					case 5 :	displayBrightness = (4095/16) * 5;
								break;
					
					case 6 :	displayBrightness = (4095/16) * 6;
								break;
					
					case 7 :	displayBrightness = (4095/16) * 7;
								break;
					
					case 8 :	displayBrightness = (4095/16) * 8;
								break;
					
					case 9 :	displayBrightness = (4095/16) * 9;
								break;
					
					case 10 :	displayBrightness = (4095/16) * 10;
								break;
					
					case 11 :	displayBrightness = (4095/16) * 11;
								break;
					
					case 12 :	displayBrightness = (4095/16) * 12;
								break;
					
					case 13 :	displayBrightness = (4095/16) * 13;
								break;
					
					case 14 :	displayBrightness = (4095/16) * 14;
								break;
					
					case 15 :	displayBrightness = 4095;
								break;
				}
			}
		}
		
		// Clock test state
		if (clockState == STATE_CHASETEST)
		{
			// Perform the test
			chaseTest();
			emrTest();

			// Set the led fading speed
			setLedFadeSpeed(30, 100);

			// Go back to the clock running state
			clockState = STATE_CLOCKRUNNING;
		}
	}
}