/* * SPI.c * * Created on: Apr 19, 2024 * Author: maxime.rohmer */ #include #include #include "config_LPC1769.h" #include "GPIO.h" #include "SPI.h" #include "init_clk.h" #include "fonts.h" #include "Background_image.h" #include "testChart.h" #include "Ship_1.h" #include "Ship_3.h" const int SCREEN_WIDTH = 240; const int SCREEN_HEIGHT = 320; const int STARS_ODDS = 1; Rectangle viewPort = {{0,0},{240,320}}; void Init_SPI(void){ S0SPCR |= 1 << 5; //Set to Master S0SPCCR = 8; //Set the clock //We change the pin to cable the spi on those ports PINSEL0 |= 0b11 << 30; PINSEL1 |= 0b11 << 2; PINSEL1 |= 0b11 << 4; //Enabling he control of the backlighting FIO1DIR |= 1 << 18; //Enable the control of the CS FIO1DIR |= 1 << 30; //Enable the controll of the CD (The command or data pin) FIO0DIR |= 1 << 16; SystemInit(); } void DC_MODE_DATA() { FIO1PIN |= 1 << 30; } void DC_MODE_COMMAND() { FIO1PIN &= ~(1 << 30); } void CS_UP(){ FIO0SET = 1 << 16; } void CS_DOWN(){ FIO0CLR = 1 << 16; } void Write_Cmd(int command){ CS_DOWN(); DC_MODE_COMMAND(); S0SPDR = command; while(!(S0SPSR >> 7 & 1)){ } CS_UP(); } void Write_Cmd_Data(int data){ CS_DOWN(); DC_MODE_DATA(); S0SPDR = data; while(!(S0SPSR >> 7 & 1)){ } CS_UP(); } void ILI9341_Initial(void) { Init_SPI(); FIO1PIN |= 1 << 18; Write_Cmd(0x01); //software reset DelaiMs(5); Write_Cmd(0x11); DelaiMs(120); Write_Cmd(0xCF); Write_Cmd_Data(0x00); Write_Cmd_Data(0x83); Write_Cmd_Data(0X30); Write_Cmd(0xED); Write_Cmd_Data(0x64); Write_Cmd_Data(0x03); Write_Cmd_Data(0X12); Write_Cmd_Data(0X81); Write_Cmd(0xE8); Write_Cmd_Data(0x85); Write_Cmd_Data(0x01); Write_Cmd_Data(0x79); Write_Cmd(0xCB); Write_Cmd_Data(0x39); Write_Cmd_Data(0x2C); Write_Cmd_Data(0x00); Write_Cmd_Data(0x34); Write_Cmd_Data(0x02); Write_Cmd(0xF7); Write_Cmd_Data(0x20); Write_Cmd(0xEA); Write_Cmd_Data(0x00); Write_Cmd_Data(0x00); Write_Cmd(0xC1); //Power control Write_Cmd_Data(0x11); //SAP[2:0];BT[3:0] Write_Cmd(0xC5); //VCM control 1 Write_Cmd_Data(0x34); Write_Cmd_Data(0x3D); Write_Cmd(0xC7); //VCM control 2 Write_Cmd_Data(0xC0); Write_Cmd(0x36); // Memory Access Control Write_Cmd_Data(0x08); Write_Cmd(0x3A); // Pixel format Write_Cmd_Data(0x55); //16bit Write_Cmd(0xB1); // Frame rate Write_Cmd_Data(0x00); Write_Cmd_Data(0x1D); //65Hz Write_Cmd(0xB6); // Display Function Control Write_Cmd_Data(0x0A); Write_Cmd_Data(0xA2); Write_Cmd_Data(0x27); Write_Cmd_Data(0x00); Write_Cmd(0xb7); //Entry mode Write_Cmd_Data(0x07); Write_Cmd(0xF2); // 3Gamma Function Disable Write_Cmd_Data(0x08); Write_Cmd(0x26); //Gamma curve selected Write_Cmd_Data(0x01); Write_Cmd(0xE0); //positive gamma correction Write_Cmd_Data(0x1f); Write_Cmd_Data(0x1a); Write_Cmd_Data(0x18); Write_Cmd_Data(0x0a); Write_Cmd_Data(0x0f); Write_Cmd_Data(0x06); Write_Cmd_Data(0x45); Write_Cmd_Data(0x87); Write_Cmd_Data(0x32); Write_Cmd_Data(0x0a); Write_Cmd_Data(0x07); Write_Cmd_Data(0x02); Write_Cmd_Data(0x07); Write_Cmd_Data(0x05); Write_Cmd_Data(0x00); Write_Cmd(0xE1); //negamma correction Write_Cmd_Data(0x00); Write_Cmd_Data(0x25); Write_Cmd_Data(0x27); Write_Cmd_Data(0x05); Write_Cmd_Data(0x10); Write_Cmd_Data(0x09); Write_Cmd_Data(0x3a); Write_Cmd_Data(0x78); Write_Cmd_Data(0x4d); Write_Cmd_Data(0x05); Write_Cmd_Data(0x18); Write_Cmd_Data(0x0d); Write_Cmd_Data(0x38); Write_Cmd_Data(0x3a); Write_Cmd_Data(0x1f); Write_Cmd(0x11); //Exit Sleep DelaiMs(120); Write_Cmd(0x29); //Display on DelaiMs(50); } uint8_t Split_Uint8(uint8_t value,int index_of_shift){ uint8_t mask = 0xff << (8 -index_of_shift); uint8_t a = value & mask; return a; } void SendPixel(uint8_t Red, uint8_t Green, uint8_t Blue){ Red = Split_Uint8(Red,5); uint8_t Green1 = Split_Uint8(Green,3) >> 5; uint8_t Green2 = Split_Uint8(Green,6) << 3; Blue=Split_Uint8(Blue,5) >> 3; uint8_t command1 = Red+Green1; uint8_t command2 = Green2+Blue; Write_Cmd_Data(command1); Write_Cmd_Data(command2); } void Resize_Window(Rectangle area){ //Creating Write_Cmd(0x2A); Point startPos = area.Position; Point endPos = {area.Position.X + area.Size.Width,area.Position.Y + area.Size.Height}; int command1 = startPos.X >> 8; int command2 = startPos.X & 0xFF; int command3 = endPos.X >> 8; int command4 = endPos.X & 0xFF; Write_Cmd_Data(command1); Write_Cmd_Data(command2); Write_Cmd_Data(command3); Write_Cmd_Data(command4); Write_Cmd(0x2B); command1 = startPos.Y >> 8; command2 = startPos.Y & 0xFF; command3 = endPos.Y >> 8; command4 = endPos.Y & 0xFF; Write_Cmd_Data(command1); Write_Cmd_Data(command2); Write_Cmd_Data(command3); Write_Cmd_Data(command4); viewPort = area; viewPort.Size.Height += 1; viewPort.Size.Width += 1; } void scroll(uint16_t scroll){ Write_Cmd(0x37); int8_t first_command = scroll >> 8; int8_t second_command = scroll; Write_Cmd_Data(first_command); Write_Cmd_Data(second_command); } void Get_Color_From_Background(Point whereToLook,Color *color){ if(whereToLook.Y < 0) whereToLook.Y = whereToLook.Y % SCREEN_HEIGHT; int index = (whereToLook.Y*SCREEN_WIDTH+whereToLook.X)*3; if(index < 0) index = 1; color->Red = SMPTE.pixel_data[index]; color->Green = SMPTE.pixel_data[index+1]; color->Blue = SMPTE.pixel_data[index+2]; } void Get_Color_From_Sprite(Point whereToLook, Color *color){ int index = ((whereToLook.Y << 5)+whereToLook.X)*3; color->Red = ShipSprite1.pixel_data[index]; color->Green = ShipSprite1.pixel_data[index+1]; color->Blue = ShipSprite1.pixel_data[index+2]; } void auto_screen_roloff(Rectangle area,Point currentPos){ if(currentPos.Y + area.Position.Y == SCREEN_HEIGHT){ Point newPosition = {area.Position.X,0}; Size newSize = {area.Size.Width,area.Size.Height - currentPos.Y}; Rectangle newRect = {newPosition,newSize}; Resize_Window(newRect); Write_Cmd(0x2C); } } void Refresh_Area(Rectangle area){ Resize_Window(area); Write_Cmd(0x2C); for(int y= 0; y < area.Size.Height;y++){ auto_screen_roloff(area,(Point){0,y}); for(int x = 0; x < area.Size.Width+1;x++){ Color color; Get_Color_From_Background((Point){x+area.Position.X,(y+area.Position.Y)%SCREEN_HEIGHT},&color); SendPixel(color.Red,color.Green,color.Blue); } } } int showDebug = 0; void Refresh_Player_Area(Rectangle area,Rectangle Hitbox){ //Sprite_32x32 sprite = ShipSprite1; Resize_Window(area); Write_Cmd(0x2C); Color color; for(int y= 0; y < area.Size.Height;y++){ auto_screen_roloff(area,(Point){0,y}); for(int x = 0; x < area.Size.Width+1;x++){ if(y + area.Position.Y >= Hitbox.Position.Y && y + area.Position.Y < Hitbox.Position.Y + Hitbox.Size.Height && x + area.Position.X >= Hitbox.Position.X && x + area.Position.X < Hitbox.Position.X + Hitbox.Size.Width){ Get_Color_From_Sprite((Point){x-(Hitbox.Position.X - area.Position.X),y-(Hitbox.Position.Y-area.Position.Y)},&color); if(color.Red == 0 && color.Green == 0 && color.Blue == 0) Get_Color_From_Background((Point){area.Position.X+x,(area.Position.Y+y)%SCREEN_HEIGHT},&color); }else{ Get_Color_From_Background((Point){area.Position.X+x,(area.Position.Y+y)%SCREEN_HEIGHT},&color); if(showDebug && (y == 0 || y == area.Size.Height -1 || x == 0 || x == area.Size.Width -1)) color = (Color){255,0,0}; } SendPixel(color.Red,color.Green,color.Blue); } } } void DrawPlayer(Player player, Rectangle areaToDraw){ Sprite_32x32 sprite = ShipSprite1; Color color; Resize_Window(player.Hitbox); Write_Cmd(0x2C); for(int y = 0; y < player.Hitbox.Size.Height;y++){ auto_screen_roloff(player.Hitbox,(Point){0,y}); for(int x = 0; x < (player.Hitbox.Size.Width+1);x++){ if(y >= areaToDraw.Position.Y && y <= areaToDraw.Size.Height && x >= areaToDraw.Position.X && x <= areaToDraw.Size.Width){ Get_Color_From_Sprite((Point){x,y},&color); if(color.Red != 0 && color.Green != 0 && color.Blue != 0){ SendPixel(color.Red,color.Green,color.Blue); }else{ Get_Color_From_Background((Point){x+player.Hitbox.Position.X,(y+player.Hitbox.Position.Y)%SCREEN_HEIGHT},&color); SendPixel(color.Red,color.Green,color.Blue); } } } } } void Draw_stars(){ Write_Cmd(0x2C); for(int y = 0; y < SCREEN_HEIGHT;y++){ for(int x = 0; x < SCREEN_WIDTH; x++){ Color color; Get_Color_From_Background((Point){x,y},&color); SendPixel(color.Red,color.Green,color.Blue); } } } int strLen(char text[]){ int counter = 0; while(text[counter]!= '\0'){ if(counter == 10000) break; counter ++; } return counter; } void DrawChar(char character,Rectangle spriteViewport){ int start_address = (character-32)*12 + 4; Resize_Window(spriteViewport); Write_Cmd(0x2C); int8_t value; for(int y = 0; y < spriteViewport.Size.Height;y++){ value = SmallFont[start_address + y]; auto_screen_roloff(spriteViewport,(Point){0,y}); for(int x = spriteViewport.Size.Width; x >= 0;x--){ if(value & (1 << x)){ SendPixel(0xFF,0xFF,0xFF); }else{ Point whereToLook = {spriteViewport.Position.X+x,(spriteViewport.Position.Y+y) % SCREEN_HEIGHT}; Color color = {0,0,0}; Get_Color_From_Background(whereToLook,&color); SendPixel(color.Red,color.Green,color.Blue); } } } } void DrawText(Point starting_point,char text[],Size charSize){ for(int x = 0;x < strLen(text);x++){ Point char_pos = {starting_point.X + 8*x,starting_point.Y}; Rectangle char_window= {char_pos,charSize}; DrawChar(text[x],char_window); } Resize_Window(viewPort); } void DrawSolidBackground(Color color){ Write_Cmd(0x2C); for(int y = 0; y < SCREEN_HEIGHT;y++){ for(int x = 0; x < SCREEN_WIDTH; x++){ SendPixel(color.Red,color.Green,color.Blue); } } } void Fill_Gradient(Rectangle viewPort){ Write_Cmd(0x2C); float step = 255.0 / (float)viewPort.Size.Height; float value = 0; for(int y= 0; y < viewPort.Size.Height;y++){ value+= step; for(int x = 0; x < viewPort.Size.Width; x++){ SendPixel((int)value,0,0); } } }