inline void LED_scan() { // Latency measurement start Latency_start_time( ledLatencyResource ); // Check for current change event if ( LED_currentEvent ) { // Turn LEDs off in low power mode if ( LED_currentEvent < 150 ) { LED_enable_current = 0; // Pause animations and clear display Pixel_setAnimationControl( AnimationControl_WipePause ); } else { LED_enable_current = 1; // Start animations Pixel_setAnimationControl( AnimationControl_Forward ); } LED_currentEvent = 0; } // Check if an LED_pause is set // Some ISSI operations need a clear buffer, but still have the chip running if ( LED_pause ) goto led_finish_scan; // Check enable state if ( LED_enable && LED_enable_current ) { // Disable Hardware shutdown of ISSI chips (pull high) GPIO_Ctrl( hardware_shutdown_pin, GPIO_Type_DriveHigh, GPIO_Config_Pullup ); } // Only write pages to I2C if chip is enabled (i.e. Hardware shutdown is disabled) else { // Enable hardware shutdown GPIO_Ctrl( hardware_shutdown_pin, GPIO_Type_DriveLow, GPIO_Config_Pullup ); goto led_finish_scan; } // Check if any I2C buses have errored // Reset the buses and restart the Frame State if ( i2c_error() ) { i2c_reset(); Pixel_FrameState = FrameState_Update; } // Only start if we haven't already // And if we've finished updating the buffers if ( Pixel_FrameState == FrameState_Sending ) goto led_finish_scan; // Only send frame to ISSI chip if buffers are ready if ( Pixel_FrameState != FrameState_Ready ) goto led_finish_scan; // Adjust frame rate (i.e. delay and do something else for a bit) Time duration = Time_duration( LED_timePrev ); if ( duration.ms < LED_framerate ) goto led_finish_scan; // FPS Display if ( LED_displayFPS ) { // Show frame calculation dbug_msg("1frame/"); printInt32( Time_ms( duration ) ); print("ms + "); printInt32( duration.ticks ); print(" ticks"); // Check if we're not meeting frame rate if ( duration.ms > LED_framerate ) { print(" - Could not meet framerate: "); printInt32( LED_framerate ); } print( NL ); } // Emulated brightness control // Lower brightness by LED_brightness #if ISSI_Chip_31FL3731_define == 1 for ( uint8_t chip = 0; chip < ISSI_Chips_define; chip++ ) { for ( uint8_t ch = 0; ch < LED_EnableBufferLength; ch++ ) { LED_pageBuffer_brightness[ chip ].ledctrl[ ch ] = LED_pageBuffer[ chip ].ledctrl[ ch ]; } for ( uint8_t ch = 0; ch < LED_BufferLength; ch++ ) { // Don't modify is 0 if ( LED_pageBuffer[ chip ].buffer[ ch ] == 0 || LED_brightness == 0 ) { LED_pageBuffer_brightness[ chip ].buffer[ ch ] = 0; continue; } // XXX (HaaTa) Yes, this is a bit slow, but it's pretty accurate LED_pageBuffer_brightness[ chip ].buffer[ ch ] = (LED_pageBuffer[ chip ].buffer[ ch ] * LED_brightness) / 0xFF; } } #endif // Update frame start time LED_timePrev = Time_now(); // Set the page of all the ISSI chips // This way we can easily link the buffers to send the brightnesses in the background for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) { uint8_t bus = LED_ChannelMapping[ ch ].bus; // Page Setup LED_setupPage( bus, LED_ChannelMapping[ ch ].addr, ISSI_LEDPwmPage ); } // Send current set of buffers // Uses interrupts to send to all the ISSI chips // Pixel_FrameState will be updated when complete LED_chipSend = 0; // Start with chip 0 LED_linkedSend(); led_finish_scan: // Latency measurement end Latency_end_time( ledLatencyResource ); }
inline void LED_scan() { // Latency measurement start Latency_start_time( ledLatencyResource ); // Check for current change event if ( LED_currentEvent ) { // Turn LEDs off in low power mode if ( LED_currentEvent < 150 ) { LED_enable = 0; // Pause animations and clear display Pixel_setAnimationControl( AnimationControl_WipePause ); } else { LED_enable = 1; // Start animations Pixel_setAnimationControl( AnimationControl_Forward ); } LED_currentEvent = 0; } // Check if an LED_pause is set // Some ISSI operations need a clear buffer, but still have the chip running if ( LED_pause ) goto led_finish_scan; // Check enable state if ( LED_enable ) { // Disable Hardware shutdown of ISSI chips (pull high) GPIOB_PSOR |= (1<<16); } // Only write pages to I2C if chip is enabled (i.e. Hardware shutdown is disabled) else { // Enable hardware shutdown GPIOB_PCOR |= (1<<16); goto led_finish_scan; } // Only start if we haven't already // And if we've finished updating the buffers if ( Pixel_FrameState == FrameState_Sending ) goto led_finish_scan; // Only send frame to ISSI chip if buffers are ready if ( Pixel_FrameState != FrameState_Ready ) goto led_finish_scan; // Adjust frame rate (i.e. delay and do something else for a bit) Time duration = Time_duration( LED_timePrev ); if ( duration.ms < LED_framerate ) goto led_finish_scan; // FPS Display if ( LED_displayFPS ) { // Show frame calculation dbug_msg("1frame/"); printInt32( Time_ms( duration ) ); print("ms + "); printInt32( duration.ticks ); print(" ticks"); // Check if we're not meeting frame rate if ( duration.ms > LED_framerate ) { print(" - Could not meet framerate: "); printInt32( LED_framerate ); } print( NL ); } // Emulated brightness control // Lower brightness by LED_brightness #if ISSI_Chip_31FL3731_define == 1 uint8_t inverse_brightness = 0xFF - LED_brightness; for ( uint8_t chip = 0; chip < ISSI_Chips_define; chip++ ) { for ( uint8_t ch = 0; ch < LED_BufferLength; ch++ ) { // Don't modify is 0 if ( LED_pageBuffer[ chip ].buffer[ ch ] == 0 ) { LED_pageBuffer_brightness[ chip ].buffer[ ch ] = 0; continue; } LED_pageBuffer_brightness[ chip ].buffer[ ch ] = LED_pageBuffer[ chip ].buffer[ ch ] - inverse_brightness < 0 ? 0x0 : LED_pageBuffer[ chip ].buffer[ ch ] - inverse_brightness; } } #endif // Update frame start time LED_timePrev = Time_now(); // Set the page of all the ISSI chips // This way we can easily link the buffers to send the brightnesses in the background for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) { uint8_t bus = LED_ChannelMapping[ ch ].bus; // Page Setup LED_setupPage( bus, LED_ChannelMapping[ ch ].addr, ISSI_LEDPwmPage ); #if ISSI_Chip_31FL3731_define == 1 || ISSI_Chip_31FL3732_define == 1 // Reset LED enable mask // XXX At high speeds, the IS31FL3732 seems to have random bit flips // To get around this, just re-set the enable mask before each send // XXX Might be sufficient to do this every N frames though while ( i2c_send( bus, (uint16_t*)&LED_ledEnableMask[ ch ], sizeof( LED_EnableBuffer ) / 2 ) == -1 ) delay_us( ISSI_SendDelay ); #endif } // Send current set of buffers // Uses interrupts to send to all the ISSI chips // Pixel_FrameState will be updated when complete LED_chipSend = 0; // Start with chip 0 LED_linkedSend(); led_finish_scan: // Latency measurement end Latency_end_time( ledLatencyResource ); }