Skip to content
image_generator.c 7.88 KiB
Newer Older
laurentc's avatar
laurentc committed
/* Includes ------------------------------------------------------------------*/
#include "stm32f3xx_hal.h"


/* USER CODE BEGIN Includes */
#include "led_driver.h"
#include "globals.h"
#include <string.h>
laurentc's avatar
laurentc committed
#include <math.h>
#include <stdlib.h>
laurentc's avatar
laurentc committed

/* USER CODE END Includes */

inline uint32_t getRawOffset(uint32_t column,uint32_t line)
{
	return 3*(column+line*NB_COLUMNS);
}



__attribute__((section("ccmram")))

uint8_t generatePlasma(uint8_t *raw,float u_time, uint8_t plasma_type, uint8_t intensity)
{
	uint32_t raw_offset;
	uint32_t line, column;
	float u_k[2];
  float v_coords[2];
  float v;
	float c[2];
	static uint8_t firstCall = 1;
	uint8_t x;
	uint8_t s1,s2,s4,c1;
	
	if (firstCall)
	{
laurentc's avatar
laurentc committed
		firstCall = 0;
	}
	
	u_time = u_time/10;

	u_k[0] = u_k[1] = 4;
	
	for (line=0;line<NB_LINES;line++)
	{
		v_coords[1] = 1.0f*line/NB_LINES;
		
		for (column=0;column<NB_COLUMNS;column++)
		{
				v_coords[0] = 1.0f*column/NB_COLUMNS;
			
				raw_offset = getRawOffset(column, line);

				c[0] = u_k[0]*(v_coords[0] - 0.5f);
				c[1] = u_k[1]*(v_coords[1] - 0.5f);

				v = sinfsm( c[0]+u_time);
				v += sinfsm((c[1]+u_time)*0.5f);
				v += sinfsm((c[0]+c[1]+u_time)*0.5f);
				c[0] += u_k[0]*0.5f * sinfsm(u_time*0.33333f);
				c[1] += u_k[1]*0.5f * cosfsm(u_time*0.5f);
				v += sinfsm(sqrt(c[0]*c[0]+c[1]*c[1]+1.0f)+u_time);
laurentc's avatar
laurentc committed
				v = v*0.5f;

				switch(plasma_type)
				{
					// type RGB
					case 1:
					case 11:
					case 6:
					case 4:
					case 19:
					case 20:
										s1 = 127.5f*sinfsm(M_PI*v)+127.5f;
										s2 = 127.5f*sinfsm(M_PI*v+2.0f/3.0f*M_PI)+127.5f;
										s4 = 127.5f*sinfsm(M_PI*v+4.0f/3.0f*M_PI)+127.5f;		
laurentc's avatar
laurentc committed
					break;
					// type 2 couleurs pures	
					case 2:
					case 16:
					case 18:
					// type 2 couleurs white
					case 3:
					case 12:
					case 17:
					case 14:
										s1 = 127.5f*sinfsm(M_PI*v)+127.5f;
										c1 = 127.5f*cosfsm(M_PI*v)+127.5f;
laurentc's avatar
laurentc committed
					break;

					case 13:
					case 15:
										c[0] = 0.5f+0.5f*sinfsm(M_PI*v+4.0f/3.0f*M_PI);
laurentc's avatar
laurentc committed
					break;


	// 5

					default :
					break;
				}
				
				switch(plasma_type)
				{
// RGB Type					
					case 1:
					case 6:
					case 11:
					// RGB Type
					raw[raw_offset++] = (s1*intensity)>>8;
					raw[raw_offset++] = (s2*intensity)>>8;
					raw[raw_offset++] = (s4*intensity)>>8;		
					break;
					
					case 19:
					// RGB Type 2
					raw[raw_offset++] = (s2*intensity)>>8;
					raw[raw_offset++] = (s1*intensity)>>8;
					raw[raw_offset++] = (s4*intensity)>>8;		
					break;

					case 20:
					// RGB Type 3
					raw[raw_offset++] = (s4*intensity)>>8;		
					raw[raw_offset++] = (s2*intensity)>>8;
					raw[raw_offset++] = (s1*intensity)>>8;
					break;
// Yellow 
					case 4:
					// White Yellow Type
					raw[raw_offset++] = intensity; //(0.5f+0.5f*sinfsm(M_PI*v))*255;
					raw[raw_offset++] = intensity; //(0.5f+0.5f*sinfsm(M_PI*v+2.0f/3.0f*M_PI))*255;
laurentc's avatar
laurentc committed
					raw[raw_offset++] = (s4*intensity)>>8;		
					break;
					
// 2 Couleurs	pures				
					case 2:
					// RED GREEN TYPE
					raw[raw_offset++] = (s1*intensity)>>8;
					raw[raw_offset++] = (c1*intensity)>>8;
					raw[raw_offset++] = 0;						
					break;
					
					case 16:
					// VERT / BLEU
					raw[raw_offset++] = 0;
					raw[raw_offset++] = (c1*intensity)>>8;
					raw[raw_offset++] = (s1*intensity)>>8;
					break;

					case 18:
					// ROUGE / BLEU
					raw[raw_offset++] = (s1*intensity)>>8;
					raw[raw_offset++] = 0;
					raw[raw_offset++] = (c1*intensity)>>8;
					break;						
// Mix White
					case 3:
					// YELLOW/MAGENTA/PINK/WHITE TYPE
					raw[raw_offset++] = intensity;
					raw[raw_offset++] = (c1*intensity)>>8;
					raw[raw_offset++] = (s1*intensity)>>8;
					break;
					
					case 12:
					// CYAN/YELLOW/WHITE TYPE
					raw[raw_offset++] = (s1*intensity)>>8;
					raw[raw_offset++] = intensity;
					raw[raw_offset++] = (c1*intensity)>>8;
					break;						

					case 17:
					// MAGENTA/CYAN/WHITE
					raw[raw_offset++] = (s1*intensity)>>8;
					raw[raw_offset++] = (c1*intensity)>>8;
					raw[raw_offset++] = intensity;						
					break;
//
					case 14:
					// MAGENTA TYPE
					raw[raw_offset++] = intensity;
					raw[raw_offset++] = (s1*intensity)>>8;
					raw[raw_offset++] = intensity;
					break;

					case 5:
					// BLACK AND WHITE
					x = 127.5f*sinfsm(M_PI*4.0f*v)+127.5f;
laurentc's avatar
laurentc committed
					raw[raw_offset++] = (x*intensity)>>8;
					raw[raw_offset++] = (x*intensity)>>8;
					raw[raw_offset++] = (x*intensity)>>8;	
					break;					
					
					case 13:
					// CYAN TYPE
					raw[raw_offset++] = (c[0]*c[0])*intensity;
					raw[raw_offset++] = intensity;
					raw[raw_offset++] = intensity;
					break;

					case 15:
					// MAGENTA TYPE DEEP
					raw[raw_offset++] = intensity;
					raw[raw_offset++] = (c[0]*c[0])*intensity;
					raw[raw_offset++] = intensity;
					break;

					default :
					raw[raw_offset++] = (0x80*intensity)>>8;
					raw[raw_offset++] = (0x80*intensity)>>8;
					raw[raw_offset++] = (0x80*intensity)>>8;
					break;
			}
		}
	}
	return 1;
	
}


uint8_t generateUniformColor(uint8_t *raw,uint8_t *color)
{
	uint32_t p=0;
	
	while (p<NB_PIXELS)
	{
		*raw++=color[0];
		*raw++=color[1];
		*raw++=color[2];
		p++;
	}
	return 0;
}

uint8_t generateBlack(uint8_t *raw)
{
	memset(raw,0,RAW_SIZE);	
	return 0;
}


uint8_t generateWhite(uint8_t *raw, uint8_t intensity)
{
	memset(raw,intensity,RAW_SIZE);	
	return 0;
}

uint8_t generateYellow(uint8_t *raw, uint8_t intensity)
{
	uint8_t color[3];
	
	color[0] = color[1] = intensity;
	color[2] = intensity>>2;
	generateUniformColor(raw,color);	

	return 0;
}

uint8_t generatePink(uint8_t *raw, uint8_t intensity)
{
	uint8_t color[3];
	
	color[0] = color[2] = intensity;
	color[1] = intensity>>2;
	generateUniformColor(raw,color);	

	return 0;
}

// 40/3 = 1.333
uint8_t generateRGB(uint8_t *raw, uint8_t intensity)
{
	int raw_offset;
	
	generateBlack(raw);

	// R
	raw_offset = getRawOffset(0, 0);
	raw[raw_offset] = intensity;
  raw_offset+=3;
	raw[raw_offset] = intensity;
	
	// G
	raw_offset = getRawOffset(13, 0);
	raw_offset++;
	raw[raw_offset] = intensity;
  raw_offset+=3;
	raw[raw_offset] = intensity;

	// B
	raw_offset = getRawOffset(27, 0);
	raw_offset++;
	raw_offset++;
	raw[raw_offset] = intensity;
  raw_offset+=3;
	raw[raw_offset] = intensity;
	
	return 0;
}

// POWER LIMITER CODE START
//#define MAX_LEDTUBE_LINE_POWER (NB_COLUMNS*3*POWER_LIMIT)

void powerLimiter(uint8_t *raw, uint8_t intensity)
{
	int line, column, i;
	uint8_t *p;
	uint16_t linePower;
	uint16_t maxLinePower;
	uint16_t ipowerReduction;
	int max_ledtube_line_power;
	
	p = raw;
	maxLinePower = 0;
	
	for (line=0;line<NB_LINES;line++)
	{
		linePower = 0;
		for (column=0;column<NB_COLUMNS;column++)
		{
			linePower+= p[0] + p[1] + p[2];
			p+=3;
		}
		if (linePower>maxLinePower)
			maxLinePower = linePower;
	}
	
//	if (intensity<POWER_LIMIT)
//		intensity = POWER_LIMIT;
	
	max_ledtube_line_power = (NB_COLUMNS*3*intensity);
	
	if (maxLinePower>max_ledtube_line_power)
	{
		ipowerReduction = (uint16_t) (256.0f*max_ledtube_line_power/maxLinePower);
		p=raw;
		
		i=RAW_SIZE;
		do
		{
			*p = ((*p)*ipowerReduction) >> 8;
			p++;
		} while(--i);
	}
}
// POWER LIMITER CODE END

uint8_t imageGenerator(uint32_t currentMode, uint8_t *raw, float time, uint8_t intensity)
{
	uint8_t dynamic;
	switch(currentMode)
	{
		case  1:
		case  2:
		case  3:
		case  4:
		case  5: dynamic = generatePlasma(raw,time,(uint8_t) currentMode, intensity); break;
		case  7: dynamic = generatePink(raw, intensity); break;
		case  8: dynamic = generateWhite(raw, intensity); break;
		case  9: dynamic = generateYellow(raw, intensity); break;
		case 10: dynamic = generateRGB(raw,intensity); break;
		case	6: 
	  case 11:
		case 12: 
		case 13:
		case 14:
		case 15:
		case 16:
		case 17:
		case 18:			
		case 19:			
		case 20: dynamic = generatePlasma(raw,time,(uint8_t) currentMode, intensity); break;
		case 21: dynamic = generateBlack(raw); break;
		default:return 0;
	}
#ifdef POWER_LIMITER
	powerLimiter(raw,intensity);
#endif
	return dynamic;
}