Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Author: nosilent@esdblog.org
- * Date: 9.10.2014
- * Project: STM32F429I-DISCO LED Matrix Hub Controller
- */
- #define USE_USB_OTG_HS //enable USB
- #define OE 0//define if oe is high active=1 or low active=0
- //max. tested resolutions: WIDTH 32*8, HEIGHT 16, recommended MODULES<=6 with HEIGHT=16 and WIDTH=32
- #define MODULES 6
- #define WIDTH 32*MODULES//HUB08 type:64, HUB75 type:32
- #define HEIGHT 16//HUB08 type:32, HUB75 type:16
- #define BRIGHTNESS 8 //in Bit, ex. 8 bit=2^8=256 steps
- #include "tm_stm32f4_usb_vcp.h"
- #include "tm_stm32f4_disco.h"
- #include "tm_stm32f4_delay.h"
- #include "defines.h"
- #include "stm32f4xx_tim.h"
- #include "stm32f4xx_dma.h"
- #include "fonts.h"
- #include "stm32f4xx_usart.h"
- #include "stm32f4xx_spi.h"
- //the pixel image in RGB
- struct color{
- uint8_t R;
- uint8_t G;
- uint8_t B;
- };
- volatile struct color image[HEIGHT][WIDTH];//width height with each rgb
- //temp variables
- volatile uint32_t pwm = 0, height=0, led_data_size=0, rgb_data=0, width=0,prescaler_size=0;
- volatile uint16_t abcd=0;
- //calculate led data array/size
- #define PRESCALER_SIZE WIDTH*BRIGHTNESS
- #define LED_DATA_SIZE PRESCALER_SIZE*(HEIGHT/2)
- volatile uint16_t led_data[LED_DATA_SIZE];
- volatile uint16_t prescaler[PRESCALER_SIZE];
- struct color foreground_color;
- struct color background_color;
- volatile uint8_t color_correction[256];
- void calcColorCorrection(void){
- for(pwm=0;pwm<256;pwm++){
- color_correction[pwm]=pwm;
- }
- }
- void calcPrescaler(void){
- #if BRIGHTNESS>1
- uint32_t prescaler_width,prescaler_brightness;
- uint32_t prescaler_data[BRIGHTNESS];
- prescaler_data[0]=0;
- for(prescaler_width=0;prescaler_width<BRIGHTNESS-1;prescaler_width++){
- prescaler_data[prescaler_width+1]=1<<prescaler_width;
- }
- for(prescaler_width=0;prescaler_width<MODULES;prescaler_width++){
- prescaler[prescaler_size++]=prescaler_data[BRIGHTNESS-2];
- }
- for(prescaler_width=0;prescaler_width<WIDTH;prescaler_width++){
- prescaler[prescaler_size++]=prescaler_data[BRIGHTNESS-1];
- }
- for(prescaler_brightness=0;prescaler_brightness<BRIGHTNESS-2;prescaler_brightness++){
- for(prescaler_width=0;prescaler_width<WIDTH;prescaler_width++){
- prescaler[prescaler_size++]=prescaler_data[prescaler_brightness];
- }
- }
- for(prescaler_width=0;prescaler_width<WIDTH-MODULES;prescaler_width++){
- prescaler[prescaler_size++]=prescaler_data[BRIGHTNESS-2];
- }
- #endif
- }
- void DMA2_Stream1_IRQHandler(void){
- if (DMA_GetITStatus(DMA2_Stream1, DMA_IT_TCIF1)){
- DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_TCIF1);
- DMA_Cmd(DMA2_Stream2, DISABLE);
- DMA_SetCurrDataCounter(DMA2_Stream2,prescaler_size);
- DMA_Cmd(DMA2_Stream2, ENABLE);
- }
- }
- void initLEDdata(void){
- TIM_OCInitTypeDef TIM_OCInitStructure;
- GPIO_InitTypeDef GPIO_InitStructure;
- DMA_InitTypeDef DMA_InitStructure;
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
- //pre calculate color correction
- calcColorCorrection();
- //pre calculate the prescaler values
- calcPrescaler();
- //set the gpios to output
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|/*GPIO_Pin_9|*/GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
- GPIO_Init(GPIOC, &GPIO_InitStructure);
- //clk
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
- GPIO_Init(GPIOC, &GPIO_InitStructure);
- GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_TIM8);
- //DMA related stuff
- /* Enable the DMA clock */
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
- /* Configure the DMA Stream */
- DMA_Cmd(DMA2_Stream1, DISABLE);
- DMA_DeInit(DMA2_Stream1);
- /* Set the parameters to be configured */
- DMA_InitStructure.DMA_Channel = DMA_Channel_7;
- DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&GPIOC->ODR;
- DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&led_data[0];
- DMA_InitStructure.DMA_BufferSize = led_data_size;
- DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
- DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
- DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
- DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
- DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_3QuartersFull;
- DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
- DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
- DMA_Init(DMA2_Stream1, &DMA_InitStructure);
- //DMA_DoubleBufferModeConfig(DMA2_Stream1,(uint32_t)&led_data[0],DMA_Memory_0);
- //DMA_DoubleBufferModeCmd(DMA2_Stream1, ENABLE);
- DMA_ITConfig(DMA2_Stream1,DMA_IT_TC, ENABLE);
- /* Configure and enable DMA interrupt */
- NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream1_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- DMA_Cmd(DMA2_Stream1, ENABLE);//enable the dma (led_data->gpio)
- //enable the timer for the dma requests
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE); /* TIM8 clock enable */
- TIM_Cmd(TIM8, DISABLE);
- TIM_DeInit(TIM8);
- TIM_TimeBaseStructure.TIM_Period = 9;
- TIM_TimeBaseStructure.TIM_Prescaler = 0;
- TIM_TimeBaseStructure.TIM_ClockDivision = 0;
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
- TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure); /* Time base configuration */
- TIM_ARRPreloadConfig(TIM8, ENABLE); /* Enable the time autoreload register */
- /* TIM PWM1 Mode configuration */
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
- TIM_OCInitStructure.TIM_Pulse = 5;
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
- TIM_OC4Init(TIM8, &TIM_OCInitStructure);
- TIM_OC4PreloadConfig(TIM8, TIM_OCPreload_Enable);
- /* TIM8 Main Output Enable */
- TIM_CtrlPWMOutputs(TIM8, ENABLE);
- /* configure DMA */
- DMA_DeInit(DMA2_Stream2);
- DMA_InitStructure.DMA_Channel = DMA_Channel_7;
- DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)TIM8_BASE+ 0x28; // physical address of Timer 8 + 14.4.11 TIM1&TIM8 prescaler (TIMx_PSC)
- DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)prescaler;
- DMA_InitStructure.DMA_BufferSize = prescaler_size;
- DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
- DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
- DMA_InitStructure.DMA_Priority = DMA_Priority_High;
- DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
- DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_3QuartersFull;
- DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
- DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
- DMA_Init(DMA2_Stream2, &DMA_InitStructure);
- //DMA_DoubleBufferModeConfig(DMA2_Stream2,(uint32_t)&prescaler[0],DMA_Memory_0);
- //DMA_DoubleBufferModeCmd(DMA2_Stream2, ENABLE);
- DMA_Cmd(DMA2_Stream2, ENABLE);//enable the prescaler dma (prescaler_data->timer)
- TIM_DMACmd(TIM8, TIM_DMA_CC1, ENABLE);
- TIM_DMACmd(TIM8, TIM_DMA_Update, ENABLE); /* Enable TIM8_UP DMA Requests, enable the timer update requests (tim->dma->gpio) */
- TIM_Cmd(TIM8, ENABLE); /* TIM enable counter (timer->dma) */
- }
- void calculateLEDdata(void){
- rgb_data=0;height=0;led_data_size=0;pwm=0;
- //GPIO Pin configuration: 3=B2,4=G2,5=R2,6=B1,7=G1,8=R1,9=CLK,10=LAT,11=OE,12=A,13=B,14=C,15=D
- for(height=0;height<(HEIGHT/2);height++){
- //check row line arrangement (for 16 we need 3bits, so only ABC is used, for 32 we use ABCD)
- #if HEIGHT<=16
- abcd=(((15+height)&0xf)<<12)&0x7000;//No D
- #elif HEIGHT<=32
- abcd=(((15+height)&0xf)<<12);
- #endif
- //pwm
- for(pwm=0;pwm<BRIGHTNESS;pwm++){
- for(width=0;width<(WIDTH-1);width++){
- //change image[height][width].R and so on to according led pixel color of your display (this is RBG)
- rgb_data=(((color_correction[image[height][width].R]>>pwm)&0x1)<<8)|(((color_correction[image[height][width].B]>>pwm)&0x1)<<7)|(((color_correction[image[height][width].G]>>pwm)&0x1)<<6)|(((color_correction[image[height+(HEIGHT/2)][width].R]>>pwm)&0x1)<<5)|(((color_correction[image[height+(HEIGHT/2)][width].B]>>pwm)&0x1)<<4)|(((color_correction[image[height+(HEIGHT/2)][width].G]>>pwm)&0x1)<<3);
- #if OE==1
- led_data[led_data_size++]=0x800|abcd|rgb_data;//ABCD,OE=1,LAT=0,CLK=0,R1=0,G1=0,B1=0,R2=0,G2=0,B2=0,NC,NC,NC
- #elif OE==0
- led_data[led_data_size++]=abcd|rgb_data;//0x800|abcd|e;//ABCD,OE=0,LAT=0,CLK=0,R1=0,G1=0,B1=0,R2=0,G2=0,B2=0,NC,NC,NC
- #endif
- }
- //last data line with latch
- abcd=(height<<12);
- //change image[height][width].R and so on to according led pixel color of your display (this is RBG)
- rgb_data=(((color_correction[image[height][width].R]>>pwm)&0x1)<<8)|(((color_correction[image[height][width].B]>>pwm)&0x1)<<7)|(((color_correction[image[height][width].G]>>pwm)&0x1)<<6)|(((color_correction[image[height+(HEIGHT/2)][width].R]>>pwm)&0x1)<<5)|(((color_correction[image[height+(HEIGHT/2)][width].B]>>pwm)&0x1)<<4)|(((color_correction[image[height+(HEIGHT/2)][width].G]>>pwm)&0x1)<<3);
- #if OE==1
- led_data[led_data_size++]=0x400|abcd|rgb_data;//ABCD,OE=0,LAT=1,CLK=0,R1=0,G1=0,B1=0,R2=0,G2=0,B2=0,NC,NC,NC
- #elif OE==0
- led_data[led_data_size++]=0xC00|abcd|rgb_data;//ABCD,OE=1,LAT=1,CLK=0,R1=0,G1=0,B1=0,R2=0,G2=0,B2=0,NC,NC,NC
- #endif
- }
- }
- }
- void calculateTestLEDData(void){
- uint32_t height,width;
- static uint32_t offset=0;
- static uint8_t brightness=0;
- for(height=0;height<HEIGHT;height++){
- for(width=0;width<WIDTH;width++){
- switch(offset){
- default:
- case 0:
- image[height][width].R=brightness;
- image[height][width].G=0x0;
- image[height][width].B=0x0;
- break;
- case 1:
- image[height][width].R=0x0;
- image[height][width].G=brightness;
- image[height][width].B=0x0;
- break;
- case 2:
- image[height][width].R=0x0;
- image[height][width].G=0x0;
- image[height][width].B=brightness;
- break;
- }
- offset=(offset+1)%3;
- }
- }
- brightness++;
- }
- void calculateLEDString(char *s, int32_t x, int32_t y, sFONT font){
- int32_t i,l,j;
- while(*s){
- for(i=0;i<font.Height;i++){
- l=font.table[((*s)-32)*(font.Height)+i];
- for(j=0;j<font.Width;j++){
- if(WIDTH>x+(font.Width-1-j) && x+(font.Width-1-j)>=0){//check width
- if((l>>j)&0x1){
- image[y+i][x+(font.Width-1-j)].R=foreground_color.R;
- image[y+i][x+(font.Width-1-j)].G=foreground_color.G;
- image[y+i][x+(font.Width-1-j)].B=foreground_color.B;
- }else{
- image[y+i][x+(font.Width-1-j)].R=background_color.R;
- image[y+i][x+(font.Width-1-j)].G=background_color.G;
- image[y+i][x+(font.Width-1-j)].B=background_color.B;
- }
- }
- }
- }
- x+=font.Width;
- s++;
- }
- }
- void calculateLine(uint32_t x, uint32_t y, uint32_t width, uint32_t height, struct color line_color){
- for(;x<width;x++){
- for(;y<height;y++){
- image[y][x].R=line_color.R;
- image[y][x].G=line_color.G;
- image[y][x].B=line_color.B;
- }
- }
- }
- void calculateRectangle(uint32_t x, uint32_t y, uint32_t width, uint32_t height, struct color frame_color, struct color fill_color){
- //fill
- for(;x<width;x++){
- for(;y<height;y++){
- image[y][x].R=fill_color.R;
- image[y][x].G=fill_color.G;
- image[y][x].B=fill_color.B;
- }
- }
- //lines
- calculateLine(x,y,width,y+1,frame_color);
- calculateLine(x,y,x+1,height,frame_color);
- calculateLine(width,y,width+1,height,frame_color);
- calculateLine(x,height,width,height+1,frame_color);
- }
- void calculateClearImage(void){
- for(height=0;height<HEIGHT;height++){
- for(width=0;width<WIDTH;width++){
- image[height][width].R=0x0;
- image[height][width].G=0x0;
- image[height][width].B=0x0;
- }
- }
- }
- void calculateScrollChar(char s, sFONT font){
- char str[1];
- static uint32_t x=WIDTH-8;
- if(x<1){
- calculateLEDString(" ",0,0,font);
- x=WIDTH-8;
- }
- str[0]=s;
- calculateLEDString(str,x,0,font);
- x--;
- }
- void calculateScrollText(char *s, sFONT font, uint8_t textlength, uint8_t y, int32_t *x){
- if((*x)<textlength*-8){
- (*x)=WIDTH+8*textlength;
- for(;textlength>0;textlength--){
- calculateLEDString(" ",textlength*8,y,font);
- }
- calculateLEDString(" ",textlength*-8,y,font);
- }
- calculateLEDString(s,(*x),y,font);
- (*x)--;
- }
- void updateLEDData(void){
- calculateLEDdata();
- TIM_Cmd(TIM8, DISABLE);
- DMA_Cmd(DMA2_Stream1, DISABLE);
- DMA_Cmd(DMA2_Stream2, DISABLE);
- DMA_SetCurrDataCounter(DMA2_Stream1,led_data_size);
- DMA_SetCurrDataCounter(DMA2_Stream2,prescaler_size);
- DMA_Cmd(DMA2_Stream1, ENABLE);
- DMA_Cmd(DMA2_Stream2, ENABLE);
- TIM_Cmd(TIM8, ENABLE);
- }
- void invertForeBackgroundColor(void){
- struct color temp_color;
- temp_color=foreground_color;
- foreground_color=background_color;
- background_color=temp_color;
- }
- int main(void) {
- int32_t scroll1=0,scroll2=0;
- uint32_t image_width_index=0,image_height_index=0,image_rgb_index=0;
- uint8_t c;
- /* System Init */
- SystemInit();
- //Initialize delay Systick timer
- TM_DELAY_Init();
- /* Initialize LED's and Button. Make sure to check settings for your board in tm_stm32f4_disco.h file */
- TM_DISCO_LedInit();
- TM_DISCO_ButtonInit();
- /* Initialize USB VCP */
- TM_USB_VCP_Init();
- //define used colors for some additional functionality
- foreground_color.R=0xff;
- foreground_color.G=0xff;
- foreground_color.B=0xff;
- background_color.R=0x1;
- background_color.G=0x1;
- background_color.B=0x0;
- //initialize the led driving (gpios,dma,timer)
- initLEDdata();
- //clear image
- calculateClearImage();
- updateLEDData();
- //some test to display
- calculateLEDString("ESD ",WIDTH-32,0,Font8x8);
- calculateLEDString("Blog",WIDTH-32,8,Font8x8);
- //calculateLine(5,5,10,10,foreground_color);
- //calculateRectangle(1,2,10,10,foreground_color,background_color);
- calculateLEDdata();
- Delayms(1000);
- while (1) {
- //calculateTestLEDData();
- //calculateScrollChar('A',Font8x8);
- calculateScrollText("ELECTRONICS iT and many more",Font8x8,28,0,&scroll1);
- if(c>20){
- invertForeBackgroundColor();
- }
- calculateLEDString(" TODAY ",0,8,Font8x8);
- if(c>20){
- invertForeBackgroundColor();
- }
- #if HEIGHT>16
- calculateScrollText("www.esdblog.org",Font8x8,15,16,&scroll2);
- if(c>20){
- invertForeBackgroundColor();
- }
- calculateLEDString(" NEW ",0,24,Font8x8);
- if(c>20){
- invertForeBackgroundColor();
- }
- #endif
- calculateLEDdata();
- c=(c+1)%40;
- Delayms(25);
- //check if button pressed->enter usb mode
- if(TM_DISCO_ButtonPressed()){
- while(1){
- /* USB configured OK, drivers OK */
- if (TM_USB_VCP_GetStatus() == TM_USB_VCP_CONNECTED) {
- /* Turn off RED led */
- //TM_DISCO_LedOff(LED_RED);
- /* If something arrived at VCP */
- while (TM_USB_VCP_Getc(&c) == TM_USB_VCP_DATA_OK) {
- /* Return data back */
- //TM_USB_VCP_Putc(c);
- //write to temp image
- switch(image_rgb_index){
- default:
- case 0:
- image[image_height_index][image_width_index].R=c;
- break;
- case 1:
- image[image_height_index][image_width_index].G=c;
- break;
- case 2:
- image[image_height_index][image_width_index].B=c;
- break;
- }
- image_rgb_index++;
- if(image_rgb_index>=3){
- image_rgb_index=0;
- image_width_index++;
- if(image_width_index>=WIDTH){
- image_width_index=0;
- image_height_index++;
- if(image_height_index>=HEIGHT){
- image_height_index=0;
- image_height_index=0;image_width_index=0;image_rgb_index=0;
- calculateLEDdata();
- }
- }
- }
- }
- } else {
- /* USB not OK */
- //TM_DISCO_LedOn(LED_RED);
- }
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement