412 lines
9.9 KiB
C
412 lines
9.9 KiB
C
/*
|
|
* SPI.c
|
|
*
|
|
* Created on: Apr 19, 2024
|
|
* Author: maxime.rohmer
|
|
*/
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#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);
|
|
}
|
|
}
|
|
}
|