void rpm2LEDs(DWORD curRate) { //if (curRate < 1000) { SetLEDs(0b00000000); MotorState = FALSE; curRate = 10;} //else { MotorState = TRUE; } int per = (curRate / PWM_PERIOD) * 100; int setting = toSetting(per); SetLEDs(setting); /* SetLEDs(setting); if (curRate < 25 ) { SetLEDs(0b00000000); } if (curRate >= 50 ) { SetLEDs(0b10000000); } if (curRate >= 100) { SetLEDs(0b11000000); } if (curRate >= 150) { SetLEDs(0b11100000); } if (curRate >= 175) { SetLEDs(0b11110000); } if (curRate >= 200) { SetLEDs(0b11111000); } */ }
// Called from userspace to do something, like set the LEDs IOReturn WirelessHIDDevice::setReport(IOMemoryDescriptor *report, IOHIDReportType reportType, IOOptionBits options) { char data[2]; if (report->readBytes(0, data, 2) < 2) return kIOReturnUnsupported; switch (data[0]) { case 0x01: // LED if ((data[1] != report->getLength()) || (data[1] != 0x03)) return kIOReturnUnsupported; report->readBytes(2, data, 1); SetLEDs(data[0]); return kIOReturnSuccess; case 0x02: // Power PowerOff(); return kIOReturnSuccess; default: return super::setReport(report, reportType, options); } }
int main() { RCC_ClocksTypeDef RCC_Clocks; RCC_GetClocksFreq(&RCC_Clocks); SysTick_Config(RCC_Clocks.HCLK_Frequency / 100); InitializeLEDs(); MyUSART_Init(); setvbuf(stdout, 0, _IONBF, 0); printf("Hello!\r\n"); char c; while(1) { if(USART_ReceiveChar(&c)) USART_SendChar(c); SetLEDs(c); } }
int main() { RCC_ClocksTypeDef RCC_Clocks; RCC_GetClocksFreq(&RCC_Clocks); SysTick_Config(RCC_Clocks.HCLK_Frequency / 100); InitializeLEDs(); MyUSART_Init(); setvbuf(stdout, 0, _IONBF, 0); printf("Hello!\r\n"); InitializeSnesController(); while(1) { snes_button_state_t btn = GetControllerState(); printf("SNES: %02X\r\n", btn.raw); printf( "%s %s %s %s %s %s %s %s %s %s %s %s\r\n", btn.buttons.A ? "A" : "", btn.buttons.B ? "B" : "", btn.buttons.X ? "X" : "", btn.buttons.Y ? "Y" : "", btn.buttons.L ? "L" : "", btn.buttons.R ? "R" : "", btn.buttons.Start ? "Start" : "", btn.buttons.Select ? "Select" : "", btn.buttons.Left ? "Left" : "", btn.buttons.Up ? "Up" : "", btn.buttons.Down ? "Down" : "", btn.buttons.Right ? "Right" : "" ); SetLEDs(btn.buttons.A << 3 | btn.buttons.B << 2 | btn.buttons.X << 1 | btn.buttons.Y); } }
void T1init(void) { // Initialize LED pins PORTB |= 0x1F; DDRB |= 0x1F; SetLEDs(50); //Initialize button input pullup and pin change interrupt DDRA &= ~(1<<PORTA3); PORTA |= (1<<PORTA3); PCMSK0 = 0x08; //Enable Pin change interrupt on pin 3 PCICR = 0x01; //Enable Pin change 0 interrupt // Configure the timers used for the LEDs TCCR1A = 0; TCCR1B = 2; //prescale = 8 OCR1A = 10; //use 75% brightness level so we can see the waveform for testing OCR1B = 240; //available for PWM use by FETs TIFR1 = 0x0F; //force all timer interrupt flags to be cleared. TIMSK1 = (1<<TOIE1);// (1<<OCIE1A)|(1<<OCIE1B); //enable interrupts as needed. }
static void RunLEDFlow() { int8_t components[3]; ReadRawAccelerometerData(components); int32_t dx=components[0]-zero[0]; int32_t dy=components[1]-zero[1]; int32_t r=sqrti(dx*dx+dy*dy); dx=(dx<<12)/r; dy=(dy<<12)/r; x+=r*25; // x+=components[0]-zero[0]; // y+=components[1]-zero[1]; int leds=0; leds|=(((x+dx)>>14)&1)<<1; leds|=(((x-dx)>>14)&1)<<3; leds|=(((x+dy)>>14)&1)<<0; leds|=(((x-dy)>>14)&1)<<2; SetLEDs(leds); }
int main() { InitializeSystem(); SysTick_Config(HCLKFrequency()/100); InitializeLEDs(); SetLEDs(0x01); uint8_t *framebuffer1=(uint8_t *)0x20000000; uint8_t *framebuffer2=(uint8_t *)0x20010000; SetLEDs(0x03); memset(framebuffer1,0,320*200); memset(framebuffer2,0,320*200); SetLEDs(0x07); IntializeVGAScreenMode320x200(framebuffer1); #define NumberOfStars 1050 static struct Star { int x,y,dx,f; } stars[NumberOfStars]; for(int i=0;i<NumberOfStars;i++) { stars[i].x=(RandomInteger()%352-16)<<12; stars[i].y=RandomInteger()%200; int z=sqrti((NumberOfStars-1-i)*NumberOfStars)*1000/NumberOfStars; stars[i].dx=6000*1200/(z+200); stars[i].f=(6-(z*7)/1000)+(RandomInteger()%6)*7; } const RLEBitmap *sprites[7*6]={ &Star1_0,&Star2_0,&Star3_0,&Star4_0,&Star5_0,&Star6_0,&Star7_0, &Star1_1,&Star2_1,&Star3_1,&Star4_1,&Star5_1,&Star6_1,&Star7_1, &Star1_2,&Star2_2,&Star3_2,&Star4_2,&Star5_2,&Star6_2,&Star7_2, &Star1_3,&Star2_3,&Star3_3,&Star4_3,&Star5_3,&Star6_3,&Star7_3, &Star1_4,&Star2_4,&Star3_4,&Star4_4,&Star5_4,&Star6_4,&Star7_4, &Star1_5,&Star2_5,&Star3_5,&Star4_5,&Star5_5,&Star6_5,&Star7_5, }; Bitmap frame1,frame2; InitializeBitmap(&frame1,320,200,320,framebuffer1); InitializeBitmap(&frame2,320,200,320,framebuffer2); int frame=0; while(1) { WaitVBL(); Bitmap *currframe; if(frame&1) { currframe=&frame2; SetFrameBuffer(framebuffer1); } else { currframe=&frame1; SetFrameBuffer(framebuffer2); } ClearBitmap(currframe); for(int i=0;i<NumberOfStars;i++) { DrawRLEBitmap(currframe,sprites[stars[i].f], (stars[i].x>>12)-16,stars[i].y-16); stars[i].x-=stars[i].dx; if(stars[i].x<=-16<<12) { stars[i].x=(320+16)<<12; stars[i].y=RandomInteger()%200; stars[i].f=(stars[i].f%7)+(RandomInteger()%6)*7; } } frame++; } }
/*! \brief The main function. * * This contains initialization and the main loop as described in the * application note. Interrupt service routines (ISR) supply all data to be * processed in the main loop. * */ int main( void ) { /* Initialisation of peripheral modules: - Watchdog (timeout must be more than longer than the longest conversion period used for the CC-ADC) - Turn of unneeded modules (only SPI atm) - Bandgap - Set Current protection levels/configuration - V-ADC - Get cell voltages (requires that interrupts are enabled) - Get temperature - Estimate capacity ("gas gauging") - Check battery voltage and release the device from DUVR mode - CC-ADC - Get initial current reading (momentary and average). - Communication */ // Initialization. wdt_reset(); WDT_SetTimeOut( WDTO_2Kms ); //Set Watchdog timeout to 2 sec #ifdef DEBUG if( FAILURE == Reset_Initialization() ){ // TODO: The Watchdog has triggered several times - might want to shut down the battery?! // POWMAN_Shutdown(); } #endif // Enable power reduction for SPI PRR_DISABLE_SPI(); // Disable digital input for port a DIDR0 = (1<<PA0DID) | (1<<PA1DID); // Enable pull-ups for port b to avoid floating pins PORTB = (1<<PORTB0) | (1<<PORTB1) | (1<<PORTB2) | (1<<PORTB3) | (1<<PORTB4) | (1<<PORTB5) | (1<<PORTB6) | (1<<PORTB7); DDRB = (1<<PORTB0) | (1<<PORTB1) | (1<<PORTB2) | (1<<PORTB3) | (1<<PORTB4); // Check the CRC checksum of the battery parameters struct errorFlags.checksumFailure = (! BATTPARAM_CheckCRC()) | (! CheckSignatureCRC()); // Initialize Bandgap reference. if( FAILURE == BANDGAP_Initialization() ){ errorFlags.criticalConditionDetected = true; } // Initialize the battery protection module (enabled by default - if default settings are good // this is not required). BATTPROT_SetShortCircuitDetection( battParams.shortcircuitCurrent, battParams.shortcircuitReactionTime ); BATTPROT_SetOverCurrentDetection( battParams.overcurrentDischarge, battParams.overcurrentCharge, battParams.overcurrentReactionTime ); BATTPROT_SetHighCurrentDetection( battParams.highcurrentDischarge, battParams.highcurrentCharge, battParams.highcurrentReactionTime ); BATTPROT_DisableDischargeHighCurrentProtection(); // Don't want a high discharging current to disable the FETs (in this example) BATTPROT_EnableAllInterrupts(); //Enable DUVR from the start, so we are always in DUVR mode. FETCTRL_EnableDeepUnderVoltageMode(); // On reset, the device is in DUVR mode depending on the fuse setting DUVRINIT stateFlags.inDUVR = true; // Enable the voltage regulator monitor interrupt VREGMON_InterruptEnable(); // Initialize V-ADC and configure a full scan VADC_InitializeVadcCoefficients(); VADC_ScanConfig( (vadcIndex_t)HIGHEST_CELL, (vadcIndex_t)HIGHEST_VADC, (vadcIndex_t)VTEMP ); // This can only fail if the VADC is set-up with an invalid ScanConfig if( FAILURE == VADC_StartScan() ){ errorFlags.criticalConditionDetected = true; } else { __enable_interrupt(); while( VADC_RUNNING == VADC_ScanState() ); __disable_interrupt(); VADC_ClearReadyFlags(); disableDUVRIfPossible(); VBSoC_Init(); } // Calculate the coefficient numbers for ccadc_ticks to mA and gas_gauging to mAh functions BATTCUR_CalculateShuntCoeffient(battParams.shuntResistance, CCADC_VOLTREF); uint16_t temp = RCCAL_CalculateUlpRCperiod(coreTemperature/10); CCGASG_CalculateShuntCoefficients(temp, battParams.shuntResistance, CCADC_VOLTREF); // Calculate values for the sram battery parameters struct BATTPARAM_InitSramParameters(); // Copy key from eeprom to sram if using AES #if defined(AUTH_USE_AES) AUTH_CopyKeyToSram(); #endif // If a critical condition occured, (either bandgap didn't work or VADC was configured wrong) // don't do any of the battery related initialization and disable DUVR mode (so charging is impossible) if( errorFlags.criticalConditionDetected ) { FETCTRL_DisableDeepUnderVoltageMode(); FETCTRL_DisableFets(); } else { // Initialize the CC-ADC (sample every second and set regular current level) CCADC_Init( ACCT_1024, RCCI_1024, 10 mA ); CCADC_SetMode( CCADC_ACC ); // Set initial remaining capacity in the CCGASG module, it is marked as in- // accurate and updated the first time the VBSoC have an accurate reading. CCGASG_SetStateofCharge(VBSoC_EstimatedSoC()); stateFlags.remainingCapacityInaccurate = 1; __enable_interrupt(); // Needs to run a conversion before the value is correct while( !CCADC_isAccResultReady() ); wdt_reset(); __disable_interrupt(); // Calculate the CCADC Accumulating conversion offset if it is invalid and // DUVR mode is disabled if(CCADC_GetRawAccOffset() == 32767 && ! stateFlags.inDUVR) { FETCTRL_DisableFets(); // Disable FETs when measuring offset as changes in current not is good __enable_interrupt(); CCADC_CalculateAccOffset(); __disable_interrupt(); } // If two or more cells, init the misbalance corrector #if BATTPARAM_CELLS_IN_SERIES >= 2 BATTVMON_InitializeBalancing(); #endif //Store information about the current (to be able to reply if host asks...) BATTCUR_StoreCurrent( CCADC_GetAccResult() ); BATTCUR_InitializeAverageCurrent( BATTCUR_GetOffsetCalibratedCurrent() ); } //init communication bus T1init(); // Used for SmBus timeout and LED Comm_Init(); // Ready to run - enable interrupts and enter main loop. __enable_interrupt(); /******************************************************************* Main loop: If any of the task flags are set the corresponding task should be run. The following things are done: - Reset watchdog - If a new CCADC result is ready, start a VADC conversion - If the communication interface have a new byte, handle it - and if a whole new command has arrived, handle that - Handle new CCADC result if it's ready - Check new core temperature if ready, and run a fast RC calibration if needed - Check new cell temperature if ready - Check new cell voltage if ready - Set different sleep modes depending on what's running - If in communication or RC calibration (any timer running) can only enter idle mode - If VADC is running, can't go deeper than ADC noise reduction mode - If "nothing" is running, enter power-save - Disable/enable fets depeding on various things - Go to sleep */ while(1) { //Tickle the watchdog every cycle wdt_reset(); if( CCADC_isAccResultReady() ) { // Start a new VADC scan as fast as possible so that all scans hopefully are // ready before the main loop ends, to avoid having to cycle again. #if BATTPARAM_CELLS_IN_SERIES >= 2 // Disable cell balancing if more than one cell BATTVMON_DisableCellBalancing(); #endif // Start a new VADC scan configureVADC(); VADC_StartScan(); taskFlags.newCurrentAvailable = true; } //See if there were any received commands. taskFlags.newSbsCommandAvailable = Comm_Handle( &sbs ); //If complete sbs command has been received: process it if( taskFlags.newSbsCommandAvailable ) { handleSBSCommand(); // If authentication is needed, run. It will use and change the values in sbs, // make sure the communication interrupt does not write directly to it. // Note that this can take long time and communication will not work // during that time. if(taskFlags.doAuthentication) { AUTH_Execute(&sbs); taskFlags.doAuthentication = false; } } /* A new CC-ADC conversion is available. Update momentary current, average current, and calculate new battery capacity. Update discharge_cycle_accumulator (and increment cycle_count if required). */ if( taskFlags.newCurrentAvailable ) { taskFlags.newCurrentAvailable = false; // We use the CCADC interrupt as counter for the RTC runEverySecond(); BATTCUR_StoreCurrent( CCADC_GetAccResult() ); handleNewCCADCResult(); CCGASG_AccumulateCCADCMeasurements( BATTCUR_GetCurrent(), slowRcOscillatorPeriod ); //Set ledstatus SoC_State = GASG_StateOfCharge(BATTCUR_GetAverageCurrent(), battParams_sram.capacityInCCAccumulated); SetLEDs((uint8_t)SoC_State); } /* New core temperature reading is available and should be processed. If temperature has changed set RC_calibration_required flag. */ if( VADC_VTempReady() ) { handleNewCoreTemperature(); } /* RC oscillator requires calibration (new CC_ADC conversion period time should be calculated and stored. */ if( taskFlags.rcCalibrationRequired ) { taskFlags.rcCalibrationRequired = false; RCCAL_StartCalibrateFastRC(); // Calculating slow RC period works on whole kelvins slowRcOscillatorPeriod = RCCAL_CalculateSlowRCperiod( coreTemperature/10 ); } if( RCCAL_GetState() == RCCAL_CALIB_INIT || RCCAL_GetState() == RCCAL_CALIB_WORKING ) { RCCAL_CalibrateFastRCruntime(slowRcOscillatorPeriod); } /* Battery cell temperature is available. Check it and disable FETs if too high/low */ if( VADC_CellTempReady() ) { handleNewCellTemperature(); } /* Check battery voltage cell . Check if critical (high/low voltage) */ if( VADC_Cell1VoltageReady() ) { handleNewCellVoltage(CELL1); } /* Check battery voltage cell . Check if critical (high/low voltage) and misbalance */ #if BATTPARAM_CELLS_IN_SERIES >= 2 if( VADC_Cell2VoltageReady() ) { handleNewCellVoltage(CELL2); } #if BATTPARAM_CELLS_IN_SERIES >= 3 if( VADC_Cell3VoltageReady() ) { handleNewCellVoltage(CELL3); } #if BATTPARAM_CELLS_IN_SERIES >= 4 if( VADC_Cell4VoltageReady() ) { handleNewCellVoltage(CELL4); } #endif #endif #endif // Check what sleep mode we can enter. Needs disable interrupt because otherwise it might // overwrite what interrupts write to SMCR (for example, if external interrupt is triggered and // wants the sleep mode to be no higher than idle, it should be run after all those checks) uint8_t interruptState = __save_interrupt(); __disable_interrupt(); if( Comm_IsIdle() && ! RCCAL_IS_RUNNING() ) { if( VADC_RUNNING == VADC_ScanState() ) { SLEEP_SET_ADC_NR_MODE(); } else { SLEEP_SET_POWER_SAVE_MODE(); } } else { SLEEP_SET_IDLE_MODE(); } __restore_interrupt(interruptState); /* Disable FETs if critical condition have been detected. Enable them if that is okey, depending om various factors like temperature and voltage. */ if( errorFlags.criticalConditionDetected || stateFlags.simulatePowerOff) { FETCTRL_DisableFets(); } else if( ! errorFlags.cellTemperatureTooHigh && ! errorFlags.cellTemperatureTooLow && ! stateFlags.inDUVR) { if( ! errorFlags.voltageTooHigh && ! errorFlags.reoccuringChargeProtection && ! stateFlags.chargingProhibited && ! sbsFlags.forceChargeFETDisabled) { FETCTRL_EnableChargeFet(); } if( ! errorFlags.voltageTooLow && ! stateFlags.dischargingProhibited && ! sbsFlags.forceDischargeFETDisabled) { FETCTRL_EnableDischargeFet(); } } // The reason to do this is that on short-circuit, the cell voltage reading can // be wrong and if that causes both chargingProhibited and dischargingProhibited // to get set, they would never be cleared unless we do this. // If they should be set, they will be set again before the FETs are enabled again // on next cycle. if( stateFlags.chargingProhibited && stateFlags.dischargingProhibited ) { stateFlags.chargingProhibited = false; stateFlags.dischargingProhibited = false; } // Enter sleep if no new byte just have been received on the communication // If a byte is received between the check for Comm_Flag and __sleep is // executed, the sleep function will have no effect as the software communication // interrupt clears sleep mode enable. if( (Comm_Flag() == 0 ) && (ShowLedBusy()==false) ){ __sleep(); } } }
/**************************************************************************** Function: int main(void) Summary: main function Description: main function Precondition: None Parameters: None Return Values: int - exit code for main function Remarks: None ***************************************************************************/ int main(void) { DWORD size = 0; BOOL responseNeeded; BYTE mode = 0; BYTE wasMode = 0; BYTE pushButtonValues = 0xFF; BYTE potPercentage = 0xFF; BOOL buttonsNeedUpdate = FALSE; BOOL potNeedsUpdate = FALSE; BOOL motorON = FALSE; BOOL readyToRead = TRUE; BOOL writeInProgress = FALSE; BYTE tempValue = 0xFF; BYTE errorCode; ACCESSORY_APP_PACKET* command_packet = NULL; CLKDIV = 0; /* set for default clock operations Fcyc = 4MHz */ AD1PCFGL = 0xffff; AD1PCFGH = 0x0003; BOOL connected_to_app = FALSE; BOOL need_to_disconnect_from_app = FALSE; #if defined(__PIC32MX__) InitPIC32(); #endif #if defined(__dsPIC33EP512MU810__) || defined (__PIC24EP512GU810__) // Configure the device PLL to obtain 60 MIPS operation. The crystal // frequency is 8MHz. Divide 8MHz by 2, multiply by 60 and divide by // 2. This results in Fosc of 120MHz. The CPU clock frequency is // Fcy = Fosc/2 = 60MHz. Wait for the Primary PLL to lock and then // configure the auxilliary PLL to provide 48MHz needed for USB // Operation. PLLFBD = 38; /* M = 60 */ CLKDIVbits.PLLPOST = 0; /* N1 = 2 */ CLKDIVbits.PLLPRE = 0; /* N2 = 2 */ OSCTUN = 0; /* Initiate Clock Switch to Primary * Oscillator with PLL (NOSC= 0x3)*/ __builtin_write_OSCCONH(0x03); __builtin_write_OSCCONL(0x01); while (OSCCONbits.COSC != 0x3); // Configuring the auxiliary PLL, since the primary // oscillator provides the source clock to the auxiliary // PLL, the auxiliary oscillator is disabled. Note that // the AUX PLL is enabled. The input 8MHz clock is divided // by 2, multiplied by 24 and then divided by 2. Wait till // the AUX PLL locks. ACLKCON3 = 0x24C1; ACLKDIV3 = 0x7; ACLKCON3bits.ENAPLL = 1; while(ACLKCON3bits.APLLCK != 1); TRISBbits.TRISB5 = 0; LATBbits.LATB5 = 1; #endif USBInitialize(0); AndroidAppStart(&myDeviceInfo); responseNeeded = FALSE; mInitPOT(); InitializeTimer2For_PWM(); PwmInit(); //InitMOTOR(); DEBUG_Init(0); InitAllLEDs(); while(1) { //Keep the USB stack running USBTasks(); //If the device isn't attached yet, if(device_attached == FALSE || mode == 1) { buttonsNeedUpdate = TRUE; potNeedsUpdate = TRUE; need_to_disconnect_from_app = FALSE; connected_to_app = FALSE; size = 0; /**/ BYTE curPush = GetPushbuttons(); if ((curPush == 0x8) || (mode == 1)) { LED0_On(); mode = 1; if (wasMode == 0) { pot2LEDs(); PwmInit(); } tempValue = ReadPOT(); wasMode = 1; //If it is different than the last time we read the pot, then we need // to send it to the Android device if(tempValue != potPercentage) { potNeedsUpdate = TRUE; //setRPM(tempValue); setPWM(); } } if ((curPush == 0x4) || (mode == 0)) { mode = 0; //LED0_Off(); if (wasMode == 1) { SetLEDs(0b00000000); wasMode = 0; setRPM(0); } //Reset the accessory state variables InitAllLEDs(); //Continue to the top of the while loop to start the check over again. continue; } /* //Reset the accessory state variables InitAllLEDs(); //Continue to the top of the while loop to start the check over again. continue; }*/ //} } //If the accessory is ready, then this is where we run all of the demo code if(readyToRead == TRUE && mode == 0) { errorCode = AndroidAppRead(device_handle, (BYTE*)&read_buffer, (DWORD)sizeof(read_buffer)); //If the device is attached, then lets wait for a command from the application if( errorCode != USB_SUCCESS) { //Error DEBUG_PrintString("Error trying to start read"); } else { readyToRead = FALSE; } } size = 0; if(AndroidAppIsReadComplete(device_handle, &errorCode, &size) == TRUE) { //We've received a command over the USB from the Android device. if(errorCode == USB_SUCCESS) { //Maybe process the data here. Maybe process it somewhere else. command_packet = (ACCESSORY_APP_PACKET*)&read_buffer[0]; } else { //Error DEBUG_PrintString("Error trying to complete read request"); } } while(size > 0) { if(connected_to_app == FALSE) { if(command_packet->command == COMMAND_APP_CONNECT) { connected_to_app = TRUE; need_to_disconnect_from_app = FALSE; } } else { switch(command_packet->command) { case COMMAND_SET_LEDS: SetLEDs(command_packet->data); break; case COMMAND_APP_DISCONNECT: need_to_disconnect_from_app = TRUE; break; case COMMAND_SET_PWM: setRPM(command_packet->data); break; default: //Error, unknown command DEBUG_PrintString("Error: unknown command received"); break; } } //All commands in this example are two bytes, so remove that from the queue size -= 2; //And move the pointer to the next packet (this works because // all command packets are 2 bytes. If variable packet size // then need to handle moving the pointer by the size of the // command type that arrived. command_packet++; if(need_to_disconnect_from_app == TRUE) { break; } } if(size == 0) { readyToRead = TRUE; } //Get the current pushbutton settings tempValue = GetPushbuttons(); //If the current button settings are different than the last time // we read the button values, then we need to send an update to the // attached Android device if(tempValue != pushButtonValues) { buttonsNeedUpdate = TRUE; pushButtonValues = tempValue; } //Get the current potentiometer setting tempValue = ReadPOT(); //If it is different than the last time we read the pot, then we need // to send it to the Android device if(tempValue != potPercentage) { potNeedsUpdate = TRUE; potPercentage = tempValue; } //If there is a write already in progress, we need to check its status if( writeInProgress == TRUE ) { if(AndroidAppIsWriteComplete(device_handle, &errorCode, &size) == TRUE) { writeInProgress = FALSE; if(need_to_disconnect_from_app == TRUE) { connected_to_app = FALSE; need_to_disconnect_from_app = FALSE; } if(errorCode != USB_SUCCESS) { //Error DEBUG_PrintString("Error trying to complete write"); } } } if((need_to_disconnect_from_app == TRUE) && (writeInProgress == FALSE)) { outgoing_packet.command = COMMAND_APP_DISCONNECT; outgoing_packet.data = 0; writeInProgress = TRUE; errorCode = AndroidAppWrite(device_handle,(BYTE*)&outgoing_packet, 2); if( errorCode != USB_SUCCESS ) { DEBUG_PrintString("Error trying to send button update"); } } if(connected_to_app == FALSE) { //If the app hasn't told us to start sending data, let's not do anything else. continue; } //If we need up update the button status on the Android device and we aren't // already busy in a write, then we can send the new button data. if((buttonsNeedUpdate == TRUE) && (writeInProgress == FALSE)) { outgoing_packet.command = COMMAND_UPDATE_PUSHBUTTONS; outgoing_packet.data = pushButtonValues; errorCode = AndroidAppWrite(device_handle,(BYTE*)&outgoing_packet, 2); if( errorCode != USB_SUCCESS ) { DEBUG_PrintString("Error trying to send button update"); } buttonsNeedUpdate = FALSE; writeInProgress = TRUE; } //If we need up update the pot status on the Android device and we aren't // already busy in a write, then we can send the new pot data. if((potNeedsUpdate == TRUE) && (writeInProgress == FALSE)) { outgoing_packet.command = COMMAND_UPDATE_POT; outgoing_packet.data = potPercentage; errorCode = AndroidAppWrite(device_handle,(BYTE*)&outgoing_packet, 2); if( errorCode != USB_SUCCESS ) { DEBUG_PrintString("Error trying to send pot update"); } potNeedsUpdate = FALSE; writeInProgress = TRUE; } } //while(1) main loop }
// 这里面的IO操作是经过序列化的。一个挨着一个,所以绝不会发生重入问题。 // VOID CY001Drv::DeviceIoControlSerial(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength, IN ULONG IoControlCode) { NTSTATUS ntStatus = STATUS_SUCCESS; ULONG ulRetLen = 0; size_t size; void* pBufferInput = NULL; void* pBufferOutput = NULL; KDBG(DPFLTR_INFO_LEVEL, "[DeviceIoControlSerial]"); // 取得输入/输出缓冲区 if(InputBufferLength)WdfRequestRetrieveInputBuffer(Request, InputBufferLength, &pBufferInput, &size); if(OutputBufferLength)WdfRequestRetrieveOutputBuffer(Request, OutputBufferLength, &pBufferOutput, &size); switch(IoControlCode) { // 设置数码管 case IOCTL_USB_SET_DIGITRON: { CHAR ch = *(CHAR*)pBufferInput; KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_SET_DIGITRON"); SetDigitron(ch); break; } // 读数码管 case IOCTL_USB_GET_DIGITRON: { UCHAR* pCh = (UCHAR*)pBufferOutput; KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_GET_DIGITRON"); GetDigitron(pCh); ulRetLen = 1; break; } // 设置LED灯(共4盏) case IOCTL_USB_SET_LEDs: { CHAR ch = *(CHAR*)pBufferInput; KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_SET_LEDs"); SetLEDs(ch); break; } // 读取LED灯(共4盏)的当前状态 case IOCTL_USB_GET_LEDs: { UCHAR* pCh = (UCHAR*)pBufferOutput; KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_GET_LEDs"); GetLEDs(pCh); ulRetLen = 1; break; } // 控制命令。 // 分为:USB协议预定义命令、Vendor自定义命令、特殊类(class)命令。 case IOCTL_USB_CTL_REQUEST: { KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_CTL_REQUEST"); ntStatus = UsbControlRequest(Request); if(NT_SUCCESS(ntStatus))return; break; } // 开启中断读 case IOCTL_START_INT_READ: KDBG(DPFLTR_INFO_LEVEL, "IOCTL_START_INT_READ"); ntStatus = InterruptReadStart(); break; // 控制程序发送读请求。它们是被阻塞的,放至Queue中排队,所以不要即可完成他们。 case IOCTL_INT_READ_KEYs: KDBG(DPFLTR_INFO_LEVEL, "IOCTL_INT_READ_KEYs"); ntStatus = WdfRequestForwardToIoQueue(Request, m_hInterruptManualQueue); if(NT_SUCCESS(ntStatus)) return;// 成功,直接返回;异步完成。 break; // 终止中断读 case IOCTL_STOP_INT_READ: KDBG(DPFLTR_INFO_LEVEL, "IOCTL_STOP_INT_READ"); InterruptReadStop(); ntStatus = STATUS_SUCCESS; break; default: // 不应该到这里。 // 对于不能识别的IO控制命令,这里做错误处理。 KDBG(DPFLTR_INFO_LEVEL, "Unknown Request: %08x(%d)!!!", IoControlCode, IoControlCode); ntStatus = STATUS_INVALID_PARAMETER; break; } WdfRequestCompleteWithInformation(Request, ntStatus, ulRetLen); return; }
void main(void) { char cntByte; // Declare your local variables here // Crystal Oscillator division factor: 1 #pragma optsize- CLKPR=0x80; CLKPR=0x00; #ifdef _OPTIMIZE_SIZE_ #pragma optsize+ #endif // Input/Output Ports initialization // Port A initialization // Func7=In Func6=In Func5=Out Func4=Out Func3=In Func2=In Func1=Out Func0=Out // State7=T State6=T State5=0 State4=0 State3=T State2=T State1=0 State0=0 PORTA=0x00; DDRA=0x33; // Port B initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=Out Func1=Out Func0=Out // State7=T State6=T State5=T State4=T State3=T State2=0 State1=0 State0=1 PORTB=0x01; DDRB=0x07; // Port C initialization // Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out // State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0 PORTC=0x00; DDRC=0xFF; // Port D initialization // Func7=In Func6=In Func5=Out Func4=Out Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=0 State4=1 State3=T State2=T State1=T State0=T PORTD=0x10; DDRD=0x30; // Port E initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=Out Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=0 State0=T PORTE=0x00; DDRE=0x02; // Port F initialization // Func7=Out Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=0 State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTF=0x00; DDRF=0x80; // Port G initialization // Func4=In Func3=Out Func2=In Func1=In Func0=In // State4=T State3=0 State2=T State1=T State0=T PORTG=0x00; DDRG=0x08; // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 1000,000 kHz // Mode: CTC top=OCR0 // OC0 output: Disconnected TCCR0A=0x0A; TCNT0=0x00; OCR0A=((OSCILLATOR_FREQUENCY/8)*0.0001)-1; //((OSCILLATOR_FREQUENCY/8)*0.0001)-1 => 100uS // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: Timer 1 Stopped // Mode: Normal top=FFFFh // OC1A output: Discon. // OC1B output: Discon. // OC1C output: Discon. // Noise Canceler: Off // Input Capture on Falling Edge // Timer 1 Overflow Interrupt: Off // Input Capture Interrupt: Off // Compare A Match Interrupt: Off // Compare B Match Interrupt: Off // Compare C Match Interrupt: Off TCCR1A=0x00; TCCR1B=0x00; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; OCR1CH=0x00; OCR1CL=0x00; // Timer/Counter 2 initialization // Clock source: System Clock // Clock value: Timer 2 Stopped // Mode: Normal top=FFh // OC2 output: Disconnected ASSR=0x00; TCCR2A=0x00; TCNT2=0x00; OCR2A=0x00; // Timer/Counter 3 initialization // Clock source: System Clock // Clock value: Timer 3 Stopped // Mode: Normal top=FFFFh // Noise Canceler: Off // Input Capture on Falling Edge // OC3A output: Discon. // OC3B output: Discon. // OC3C output: Discon. // Timer 3 Overflow Interrupt: Off // Input Capture Interrupt: Off // Compare A Match Interrupt: Off // Compare B Match Interrupt: Off // Compare C Match Interrupt: Off TCCR3A=0x00; TCCR3B=0x00; TCNT3H=0x00; TCNT3L=0x00; ICR3H=0x00; ICR3L=0x00; OCR3AH=0x00; OCR3AL=0x00; OCR3BH=0x00; OCR3BL=0x00; OCR3CH=0x00; OCR3CL=0x00; // External Interrupt(s) initialization // INT0: Off // INT1: Off // INT2: Off // INT3: Off // INT4: Off // INT5: Off // INT6: Off // INT7: Off EICRA=0x00; EICRB=0x00; EIMSK=0x00; // Timer/Counter 0 Interrupt(s) initialization TIMSK0=0x02; // Timer/Counter 1 Interrupt(s) initialization TIMSK1=0x00; // Timer/Counter 2 Interrupt(s) initialization TIMSK2=0x00; // Timer/Counter 3 Interrupt(s) initialization TIMSK3=0x00; // Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off ACSR=0x80; ADCSRB=0x00; PORTA |= 0x0F; delay_us(100); HardwareMinorRevision = PINA&0x0F; PORTA &= 0xF0; delay_ms(200); nSS = 1; ReadFPGA(); FPGAFirmwareMajorRevision = FPGAData[8]; FPGAFirmwareMinorRevision = FPGAData[9]; FPGAFirmwareType = (((unsigned int)FPGAData[10])<<8) | FPGAData[11]; // CAN Controller initialization InitializeCAN(); LEDState[0] = 0x00; LEDState[1] = 0x00; LEDState[2] = 0x00; LEDState[3] = 0x00; LEDMode[0] = 0x00; LEDMode[1] = 0x00; LEDMode[2] = 0x00; LEDMode[3] = 0x00; LEDData[0] = 0x01; LEDData[1] = 0x01; LEDData[2] = 0x01; LEDData[3] = 0x01; SetLEDs(); delay_ms(500); LEDData[0] = 0x00; LEDData[1] = 0x00; LEDData[2] = 0x00; LEDData[3] = 0x00; SetLEDs(); for (cntByte=0; cntByte<16; cntByte++) { InputStereoSelect[cntByte] = 0x01<<(cntByte&0x01); InputLevel[cntByte] = 0x00; InputPhase[cntByte] = 0x00; OutputStereoSelect[cntByte] = 0x01<<(cntByte&0x01); OutputLevel[cntByte] = 0x00; OutputDim[cntByte] = 0x00; OutputDimLevel[cntByte] = -10; OutputMute[cntByte] = 0x00; OutputPhase[cntByte] = 0x00; if (cntByte<4) { OutputTalkback[cntByte] = 0x00; } OutputTalkbackLevel[cntByte] = 0x00; OutputTalkbackStereoSelect[cntByte] = 0x00; OutputTalkbackPhase[cntByte] = 0x00; SetRoutingAndLevel(cntByte); } PreviousMilliSecond = 0; RackSlotNr = GetSlotNr(); if (FPGAFirmwareType != DefaultNodeObjects.ProductID) { LEDData[0] = 0; LEDData[1] = 1; LEDData[2] = 0; LEDData[3] = 1; // LEDData[4] = 0; // LEDData[5] = 1; // LEDData[6] = 0; // LEDData[7] = 1; SetLEDs(); } // Global enable interrupts #asm("sei") CheckUniqueIDPerProduct(); while (1) { ProcessCAN(); if (cntMilliSecond - PreviousMilliSecondReservation > 1000) { PreviousMilliSecondReservation = cntMilliSecond; if (LocalCANAddress == 0x00000000) { SendCANReservationRequest(); } else { SendMambaNetReservationInfo(); } } if (cntMilliSecond - PreviousMilliSecond > 40) { //Send track/relative information maximal 25 times per second. PreviousMilliSecond = cntMilliSecond; } if (cntMilliSecond - PreviousLEDBlinkMilliSecond > 250) { //LED Blink 4 times per second. unsigned char cntLED; unsigned char DoSetLEDs; unsigned char cntChannel; DoSetLEDs = 0; for (cntLED=0; cntLED<8; cntLED++) { if (FPGAFirmwareType == DefaultNodeObjects.ProductID) { if (LEDMode[cntLED]) { if (LEDState[cntLED]) { LEDData[cntLED] ^= 0x01; DoSetLEDs = 1; } else if (LEDData[cntLED]) { LEDData[cntLED] = 0; DoSetLEDs = 1; } } } else { //wrong FPGA firmware LEDData[cntLED] ^= 0x01; DoSetLEDs = 1; } } if (DoSetLEDs) { SetLEDs(); } if (AddressValidated) { nACT_LED = cntDebug++&0x04; } else { nACT_LED = cntDebug++&0x01; } //read signal ReadFPGA(); NewInputSignalState = (((unsigned int)FPGAData[2])<<8) | FPGAData[3]; for (cntChannel=0; cntChannel<16; cntChannel++) { unsigned char Mask = 0x01<<cntChannel; if ((InputSignalState^NewInputSignalState)&Mask) { unsigned char TransmitBuffer[1]; TransmitBuffer[0] = 0; if (NewInputSignalState&Mask) { TransmitBuffer[0] = 1; } SendSensorChangeToMambaNet(1037+cntChannel, STATE_DATATYPE, 1, TransmitBuffer); } } InputSignalState = NewInputSignalState; NewOutputSignalState = (((unsigned int)FPGAData[2])<<8) | FPGAData[3]; for (cntChannel=0; cntChannel<16; cntChannel++) { unsigned char Mask = 0x01<<cntChannel; if ((OutputSignalState^NewOutputSignalState)&Mask) { unsigned char TransmitBuffer[1]; TransmitBuffer[0] = 0; if (NewOutputSignalState&Mask) { TransmitBuffer[0] = 1; } SendSensorChangeToMambaNet(1053+cntChannel, STATE_DATATYPE, 1, TransmitBuffer); } } OutputSignalState = NewOutputSignalState; PreviousLEDBlinkMilliSecond = cntMilliSecond; } // ReadSwitches(); } }