Пример #1
0
// Write address
void LED_writeReg( uint8_t bus, uint8_t addr, uint8_t reg, uint8_t val, uint8_t page )
{
	/*
	info_msg("I2C Write bus(");
	printHex( bus );
	print(")addr(");
	printHex( addr );
	print(")reg(");
	printHex( reg );
	print(")val(");
	printHex( val );
	print(")page(");
	printHex( page );
	print(")" NL);
	*/

	// Reg Write Setup
	uint16_t writeData[] = { addr, reg, val };

	// Setup page
	LED_setupPage( bus, addr, page );

	// Write register
	while ( i2c_send( bus, writeData, sizeof( writeData ) / 2 ) == -1 )
		delay_us( ISSI_SendDelay );

	// Delay until written
	while ( i2c_busy( bus ) )
		delay_us( ISSI_SendDelay );
}
Пример #2
0
// Write register on all ISSI chips
// Prepare pages first, then attempt write register with a minimal delay between chips
void LED_syncReg( uint8_t reg, uint8_t val, uint8_t page )
{
	// Setup each of the pages
	for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ )
	{
		LED_setupPage(
			LED_ChannelMapping[ ch ].bus,
			LED_ChannelMapping[ ch ].addr,
			page
		);
	}

	// Reg Write Setup
	uint16_t writeData[] = { 0, reg, val };

	// Write to all the registers
	for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ )
	{
		writeData[0] = LED_ChannelMapping[ ch ].addr;
		uint8_t bus = LED_ChannelMapping[ ch ].bus;

		// Delay very little to help with synchronization
		while ( i2c_send( bus, writeData, sizeof( writeData ) / 2 ) == -1 )
			delay_us(10);
	}

	// Delay until written
	while ( i2c_any_busy() )
		delay_us( ISSI_SendDelay );
}
Пример #3
0
// Write ISSI page
void LED_sendPage( uint8_t bus, uint8_t addr, uint16_t *buffer, uint32_t len, uint8_t page )
{
	/*
	info_msg("I2C Send Page: bus(");
	printHex( bus );
	print(")addr(");
	printHex( addr );
	print(")len(");
	printHex( len );
	print(")page(");
	printHex( page );
	print(")data[](");
	for ( uint8_t c = 0; c < 9; c++ )
	{
		printHex( buffer[c] );
		print(" ");
	}
	print("..)" NL);
	*/

	// Page Setup
	LED_setupPage( bus, addr, page );

	// Write page to I2C Tx Buffer
	while ( i2c_send( bus, buffer, len ) == -1 )
		delay_us( ISSI_SendDelay );
}
Пример #4
0
// Zero out given ISSI page
void LED_zeroPages( uint8_t bus, uint8_t addr, uint8_t startPage, uint8_t numPages, uint8_t startReg, uint8_t endReg )
{
	// Clear Page
	// Max length of a page + chip id + reg start
	uint16_t clearPage[2 + ISSI_PageLength] = { 0 };
	clearPage[0] = addr;
	clearPage[1] = startReg;

	// Iterate through given pages, zero'ing out the given register regions
	for ( uint8_t page = startPage; page < startPage + numPages; page++ )
	{
		// Page Setup
		LED_setupPage( bus, addr, page );

		// Zero out page
		while ( i2c_send( bus, clearPage, 2 + endReg - startReg ) == -1 )
			delay_us( ISSI_SendDelay );
	}

	// Wait until finished zero'ing
	while ( i2c_busy( bus ) )
		delay_us( ISSI_SendDelay );
}
Пример #5
0
// Read address
uint8_t LED_readReg( uint8_t bus, uint8_t addr, uint8_t reg, uint8_t page )
{
	/*
	info_msg("I2C Read Bus: ");
	printHex( bus );
	print(" Addr: ");
	printHex( addr );
	print(" Reg: ");
	printHex( reg );
	print(" Page: ");
	printHex( page );
	print( NL );
	*/

#if ISSI_Chip_31FL3731_define == 1 || ISSI_Chip_31FL3732_define == 1
	// Software shutdown must be enabled to read registers
	LED_writeReg( bus, addr, 0x0A, 0x00, ISSI_ConfigPage );
#endif

	// Setup page
	LED_setupPage( bus, addr, page );

	// Register Read Command
	uint16_t regReadCmd[] = { addr, reg, I2C_RESTART, addr | 0x1, I2C_READ };
	uint8_t recv_data;

	// Request single register byte
	while ( i2c_read( bus, regReadCmd, sizeof( regReadCmd ) / 2, &recv_data ) == -1 )
		delay_us( ISSI_SendDelay );

#if ISSI_Chip_31FL3731_define == 1 || ISSI_Chip_31FL3732_define == 1
	// Disable software shutdown
	LED_writeReg( bus, addr, 0x0A, 0x01, ISSI_ConfigPage );
#endif

	return recv_data;
}
Пример #6
0
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 );
}
Пример #7
0
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 );
}