// #define RCC_IOPENR (*(volatile unsigned int*)0x4002102C)
// #define GPIOA_MODER (*(volatile unsigned int*)0x50000000)
// #define GPIOA_ODR (*(volatile unsigned int*)0x50000014)
// int main()
// {
// // 1. Enable GPIOA clock (bit 0)
// RCC_IOPENR |= (1 << 0);
// // 2. Set PA5 as output
// GPIOA_MODER &= ~(3 << (5 * 2)); // clear bits
// GPIOA_MODER |= (1 << (5 * 2)); // set as output
// while (1)
// {
// // LED ON
// GPIOA_ODR |= (1 << 5);
// for (volatile int i = 0; i < 500000; i++);
// // LED OFF
// GPIOA_ODR &= ~(1 << 5);
// for (volatile int i = 0; i < 500000; i++);
// }
// }
// #define RCC_IOPENR (*(volatile unsigned int*)0x4002102C)
// #define GPIOB_MODER (*(volatile unsigned int*)0x50000400)
// #define GPIOB_ODR (*(volatile unsigned int*)0x50000414)
// // pins
// #define RS 0
// #define EN 1
// #define D4 2
// #define D5 3
// #define D6 4
// #define D7 5
// void delay() {
// for (volatile int i = 0; i < 30000; i++);
// }
// // send 4-bit data
// void send4bit(unsigned char data) {
// GPIOB_ODR &= ~( (1<<D4)|(1<<D5)|(1<<D6)|(1<<D7) );
// if (data & 0x1) GPIOB_ODR |= (1<<D4);
// if (data & 0x2) GPIOB_ODR |= (1<<D5);
// if (data & 0x4) GPIOB_ODR |= (1<<D6);
// if (data & 0x8) GPIOB_ODR |= (1<<D7);
// GPIOB_ODR |= (1<<EN);
// delay();
// GPIOB_ODR &= ~(1<<EN);
// }
// // send command
// void lcd_cmd(unsigned char cmd) {
// GPIOB_ODR &= ~(1<<RS);
// send4bit(cmd >> 4);
// send4bit(cmd & 0x0F);
// delay();
// }
// // send data
// void lcd_data(unsigned char data) {
// GPIOB_ODR |= (1<<RS);
// send4bit(data >> 4);
// send4bit(data & 0x0F);
// delay();
// }
// int main()
// {
// // enable GPIOB
// RCC_IOPENR |= (1<<1);
// // PB0–PB5 output
// for(int i=0;i<6;i++){
// GPIOB_MODER &= ~(3<<(i*2));
// GPIOB_MODER |= (1<<(i*2));
// }
// delay();
// // LCD INIT
// send4bit(0x03);
// delay();
// send4bit(0x03);
// delay();
// send4bit(0x03);
// delay();
// send4bit(0x02); // 4-bit mode
// lcd_cmd(0x28); // 2 line
// lcd_cmd(0x0C); // display ON
// lcd_cmd(0x06); // cursor move
// lcd_cmd(0x01); // clear
// // print HELLO
// char msg[] = "HELLO";
// for(int i=0;i<5;i++){
// lcd_data(msg[i]);
// }
// while(1);
// }
// #define RCC_IOPENR (*(volatile unsigned int*)0x4002102C)
// #define GPIOA_MODER (*(volatile unsigned int*)0x50000000)
// #define GPIOA_IDR (*(volatile unsigned int*)0x50000010)
// #define GPIOA_ODR (*(volatile unsigned int*)0x50000014)
// #define GPIOB_MODER (*(volatile unsigned int*)0x50000400)
// #define GPIOB_ODR (*(volatile unsigned int*)0x50000414)
// // LCD pins
// #define RS 0
// #define EN 1
// #define D4 2
// #define D5 3
// #define D6 4
// #define D7 5
// void delay() {
// for (volatile int i = 0; i < 30000; i++);
// }
// // -------- LCD --------
// void send4bit(unsigned char data) {
// GPIOB_ODR &= ~((1<<D4)|(1<<D5)|(1<<D6)|(1<<D7));
// if (data & 1) GPIOB_ODR |= (1<<D4);
// if (data & 2) GPIOB_ODR |= (1<<D5);
// if (data & 4) GPIOB_ODR |= (1<<D6);
// if (data & 8) GPIOB_ODR |= (1<<D7);
// GPIOB_ODR |= (1<<EN);
// delay();
// GPIOB_ODR &= ~(1<<EN);
// }
// void lcd_cmd(unsigned char cmd) {
// GPIOB_ODR &= ~(1<<RS);
// send4bit(cmd >> 4);
// send4bit(cmd & 0x0F);
// delay();
// }
// void lcd_data(unsigned char data) {
// GPIOB_ODR |= (1<<RS);
// send4bit(data >> 4);
// send4bit(data & 0x0F);
// delay();
// }
// // -------- KEYMAP --------
// char keys[4][4] = {
// {'1','2','3','A'},
// {'4','5','6','B'},
// {'7','8','9','C'},
// {'*','0','#','D'}
// };
// int main()
// {
// // Enable GPIOA + GPIOB
// RCC_IOPENR |= (1<<0); // A
// RCC_IOPENR |= (1<<1); // B
// // ---------- LCD PINS OUTPUT ----------
// for(int i=0;i<6;i++){
// GPIOB_MODER &= ~(3<<(i*2));
// GPIOB_MODER |= (1<<(i*2));
// }
// // ---------- KEYPAD ----------
// // PA0–PA3 OUTPUT (rows)
// for(int i=0;i<4;i++){
// GPIOA_MODER &= ~(3<<(i*2));
// GPIOA_MODER |= (1<<(i*2));
// }
// // PA4–PA7 INPUT (columns)
// for(int i=4;i<8;i++){
// GPIOA_MODER &= ~(3<<(i*2));
// }
// // Enable pull-down for PA4–PA7
// #define GPIOA_PUPDR (*(volatile unsigned int*)0x5000000C)
// for(int i=4;i<8;i++){
// GPIOA_PUPDR &= ~(3<<(i*2));
// GPIOA_PUPDR |= (2<<(i*2)); // pull-down
// }
// delay();
// // ---------- LCD INIT ----------
// send4bit(0x03); delay();
// send4bit(0x03); delay();
// send4bit(0x03); delay();
// send4bit(0x02);
// lcd_cmd(0x28);
// lcd_cmd(0x0C);
// lcd_cmd(0x06);
// lcd_cmd(0x01);
// while (1)
// {
// char key = 0;
// // scan keypad
// for(int row=0; row<4; row++)
// {
// GPIOA_ODR &= ~(0x0F); // all rows LOW
// GPIOA_ODR |= (1<<row); // one row HIGH
// delay();
// for(int col=0; col<4; col++)
// {
// if(GPIOA_IDR & (1<<(col+4)))
// {
// key = keys[row][col];
// }
// }
// }
// // display key
// if(key)
// {
// lcd_cmd(0x01); // clear
// lcd_data('K');
// lcd_data('e');
// lcd_data('y');
// lcd_data(':');
// lcd_data(' ');
// lcd_data(key);
// delay();
// }
// }
// }
// // ---------- RCC ----------
// #define RCC_IOPENR (*(volatile unsigned int*)0x4002102C)
// // ---------- GPIOA (Keypad) ----------
// #define GPIOA_MODER (*(volatile unsigned int*)0x50000000)
// #define GPIOA_IDR (*(volatile unsigned int*)0x50000010)
// #define GPIOA_ODR (*(volatile unsigned int*)0x50000014)
// #define GPIOA_PUPDR (*(volatile unsigned int*)0x5000000C)
// // ---------- GPIOB (LCD) ----------
// #define GPIOB_MODER (*(volatile unsigned int*)0x50000400)
// #define GPIOB_ODR (*(volatile unsigned int*)0x50000414)
// // ---------- LCD PINS ----------
// #define RS 0
// #define EN 1
// #define D4 2
// #define D5 3
// #define D6 4
// #define D7 5
// // ---------- DELAY ----------
// void delay() {
// for (volatile int i = 0; i < 30000; i++);
// }
// // ---------- LCD LOW LEVEL ----------
// void send4bit(unsigned char data) {
// GPIOB_ODR &= ~((1<<D4)|(1<<D5)|(1<<D6)|(1<<D7));
// if (data & 1) GPIOB_ODR |= (1<<D4);
// if (data & 2) GPIOB_ODR |= (1<<D5);
// if (data & 4) GPIOB_ODR |= (1<<D6);
// if (data & 8) GPIOB_ODR |= (1<<D7);
// GPIOB_ODR |= (1<<EN);
// delay();
// GPIOB_ODR &= ~(1<<EN);
// }
// // ---------- LCD COMMAND ----------
// void lcd_cmd(unsigned char cmd) {
// GPIOB_ODR &= ~(1<<RS);
// send4bit(cmd >> 4);
// send4bit(cmd & 0x0F);
// delay();
// }
// // ---------- LCD DATA ----------
// void lcd_data(unsigned char data) {
// GPIOB_ODR |= (1<<RS);
// send4bit(data >> 4);
// send4bit(data & 0x0F);
// delay();
// }
// // ---------- KEYPAD ----------
// char keys[4][4] = {
// {'1','2','3','A'},
// {'4','5','6','B'},
// {'7','8','9','C'},
// {'*','0','#','D'}
// };
// // ---------- LIFT ----------
// typedef struct {
// int current_floor;
// } Lift;
// Lift lifts[4] = {
// {1}, {5}, {8}, {3}
// };
// int abs_val(int x) {
// return x < 0 ? -x : x;
// }
// int find_best_lift(int target) {
// int min = 100, best = 0;
// for (int i = 0; i < 4; i++) {
// int d = abs_val(lifts[i].current_floor - target);
// if (d < min) {
// min = d;
// best = i;
// }
// }
// return best;
// }
// // ---------- MAIN ----------
// int main()
// {
// // Enable GPIOA + GPIOB
// RCC_IOPENR |= (1<<0);
// RCC_IOPENR |= (1<<1);
// // ---------- LCD CONFIG ----------
// for(int i=0;i<6;i++){
// GPIOB_MODER &= ~(3<<(i*2));
// GPIOB_MODER |= (1<<(i*2));
// }
// // ---------- KEYPAD CONFIG ----------
// // Rows PA0–PA3 OUTPUT
// for(int i=0;i<4;i++){
// GPIOA_MODER &= ~(3<<(i*2));
// GPIOA_MODER |= (1<<(i*2));
// }
// // Columns PA4–PA7 INPUT
// for(int i=4;i<8;i++){
// GPIOA_MODER &= ~(3<<(i*2));
// }
// // Pull-down for columns
// for(int i=4;i<8;i++){
// GPIOA_PUPDR &= ~(3<<(i*2));
// GPIOA_PUPDR |= (2<<(i*2));
// }
// delay();
// // ---------- LCD INIT ----------
// send4bit(0x03); delay();
// send4bit(0x03); delay();
// send4bit(0x03); delay();
// send4bit(0x02);
// lcd_cmd(0x28);
// lcd_cmd(0x0C);
// lcd_cmd(0x06);
// lcd_cmd(0x01);
// int floor = 0;
// char key;
// while (1)
// {
// key = 0;
// // ---------- SCAN KEYPAD ----------
// for(int row=0; row<4; row++)
// {
// GPIOA_ODR &= ~(0x0F);
// GPIOA_ODR |= (1<<row);
// delay();
// for(int col=0; col<4; col++)
// {
// if(GPIOA_IDR & (1<<(col+4)))
// {
// key = keys[row][col];
// }
// }
// }
// if(key)
// {
// // ---------- WAIT FOR RELEASE (IMPORTANT FIX) ----------
// int pressed = 1;
// while(pressed)
// {
// pressed = 0;
// for(int row=0; row<4; row++)
// {
// GPIOA_ODR &= ~(0x0F);
// GPIOA_ODR |= (1<<row);
// for(int col=0; col<4; col++)
// {
// if(GPIOA_IDR & (1<<(col+4)))
// {
// pressed = 1; // still pressed
// }
// }
// }
// }
// delay(); // debounce
// // ---------- NUMBER ----------
// if(key >= '0' && key <= '9')
// {
// floor = floor * 10 + (key - '0');
// lcd_cmd(0x01);
// lcd_data('F'); lcd_data('l'); lcd_data('o'); lcd_data('o'); lcd_data('r'); lcd_data(':'); lcd_data(' ');
// if(floor >= 10) {
// lcd_data((floor/10) + '0');
// lcd_data((floor%10) + '0');
// } else {
// lcd_data(floor + '0');
// }
// }
// // ---------- ENTER ----------
// else if(key == '#')
// {
// int lift = find_best_lift(floor);
// lcd_cmd(0x01);
// lcd_data('F'); lcd_data('l'); lcd_data('o'); lcd_data('o'); lcd_data('r'); lcd_data(':'); lcd_data(' ');
// if(floor >= 10) {
// lcd_data((floor/10) + '0');
// lcd_data((floor%10) + '0');
// } else {
// lcd_data(floor + '0');
// }
// lcd_cmd(0xC0);
// lcd_data('L'); lcd_data('i'); lcd_data('f'); lcd_data('t'); lcd_data(':'); lcd_data(' ');
// lcd_data(lift + '1');
// floor = 0;
// }
// // ---------- CLEAR ----------
// else if(key == '*')
// {
// floor = 0;
// lcd_cmd(0x01);
// }
// }
// }
// }
// // ---------- RCC ----------
// #define RCC_IOPENR (*(volatile unsigned int*)0x4002102C)
// // ---------- GPIOB ----------
// #define GPIOB_MODER (*(volatile unsigned int*)0x50000400)
// #define GPIOB_ODR (*(volatile unsigned int*)0x50000414)
// // ---------- LCD2 PINS ----------
// #define RS2 6
// #define EN2 7
// #define D42 8
// #define D52 9
// #define D62 10
// #define D72 11
// // ---------- DELAY ----------
// void delay() {
// for (volatile int i = 0; i < 30000; i++);
// }
// // ---------- SEND 4 BIT ----------
// void send4bit2(unsigned char data)
// {
// GPIOB_ODR &= ~((1<<D42)|(1<<D52)|(1<<D62)|(1<<D72));
// if (data & 1) GPIOB_ODR |= (1<<D42);
// if (data & 2) GPIOB_ODR |= (1<<D52);
// if (data & 4) GPIOB_ODR |= (1<<D62);
// if (data & 8) GPIOB_ODR |= (1<<D72);
// GPIOB_ODR |= (1<<EN2);
// delay();
// GPIOB_ODR &= ~(1<<EN2);
// }
// // ---------- COMMAND ----------
// void lcd2_cmd(unsigned char cmd)
// {
// GPIOB_ODR &= ~(1<<RS2);
// send4bit2(cmd >> 4);
// send4bit2(cmd & 0x0F);
// delay();
// }
// // ---------- DATA ----------
// void lcd2_data(unsigned char data)
// {
// GPIOB_ODR |= (1<<RS2);
// send4bit2(data >> 4);
// send4bit2(data & 0x0F);
// delay();
// }
// // ---------- MAIN ----------
// int main()
// {
// // Enable GPIOB clock
// RCC_IOPENR |= (1<<1);
// // Configure PB6–PB11 as output
// for(int i=6;i<=11;i++){
// GPIOB_MODER &= ~(3<<(i*2));
// GPIOB_MODER |= (1<<(i*2));
// }
// delay();
// // ---------- LCD INIT ----------
// send4bit2(0x03); delay();
// send4bit2(0x03); delay();
// send4bit2(0x03); delay();
// send4bit2(0x02);
// lcd2_cmd(0x28);
// lcd2_cmd(0x0C);
// lcd2_cmd(0x06);
// lcd2_cmd(0x01);
// // ---------- PRINT ----------
// char msg1[] = "LCD2 TEST";
// char msg2[] = "HELLO";
// // line 1
// for(int i=0; msg1[i]; i++){
// lcd2_data(msg1[i]);
// }
// // line 2
// lcd2_cmd(0xC0);
// for(int i=0; msg2[i]; i++){
// lcd2_data(msg2[i]);
// }
// while(1);
// }
// // ================= RCC =================
// #define RCC_IOPENR (*(volatile unsigned int*)0x4002102C)
// // ================= GPIOA (KEYPAD) =================
// #define GPIOA_MODER (*(volatile unsigned int*)0x50000000)
// #define GPIOA_IDR (*(volatile unsigned int*)0x50000010)
// #define GPIOA_ODR (*(volatile unsigned int*)0x50000014)
// #define GPIOA_PUPDR (*(volatile unsigned int*)0x5000000C)
// // ================= GPIOB (LCD1 + LCD2) =================
// #define GPIOB_MODER (*(volatile unsigned int*)0x50000400)
// #define GPIOB_ODR (*(volatile unsigned int*)0x50000414)
// // ================= LCD1 PINS =================
// #define RS 0
// #define EN 1
// #define D4 2
// #define D5 3
// #define D6 4
// #define D7 5
// // ================= LCD2 PINS =================
// #define RS2 6
// #define EN2 7
// #define D42 8
// #define D52 9
// #define D62 10
// #define D72 11
// // ================= DELAY =================
// void delay() {
// for (volatile int i = 0; i < 30000; i++);
// }
// // ================= LCD1 =================
// void send4bit(unsigned char data){
// // clear only LCD1 data pins
// GPIOB_ODR &= ~((1<<D4)|(1<<D5)|(1<<D6)|(1<<D7));
// if(data&1) GPIOB_ODR|=(1<<D4);
// if(data&2) GPIOB_ODR|=(1<<D5);
// if(data&4) GPIOB_ODR|=(1<<D6);
// if(data&8) GPIOB_ODR|=(1<<D7);
// // pulse EN1 ONLY
// GPIOB_ODR |= (1<<EN);
// delay();
// GPIOB_ODR &= ~(1<<EN);
// }
// void lcd_cmd(unsigned char cmd){
// GPIOB_ODR &= ~(1<<RS); // RS1 LOW only
// send4bit(cmd>>4);
// send4bit(cmd&0x0F);
// }
// void lcd_data(unsigned char data){
// GPIOB_ODR |= (1<<RS); // RS1 HIGH only
// send4bit(data>>4);
// send4bit(data&0x0F);
// }
// // ================= LCD2 =================
// void send4bit2(unsigned char data){
// // clear only LCD2 data pins
// GPIOB_ODR &= ~((1<<D42)|(1<<D52)|(1<<D62)|(1<<D72));
// if(data&1) GPIOB_ODR|=(1<<D42);
// if(data&2) GPIOB_ODR|=(1<<D52);
// if(data&4) GPIOB_ODR|=(1<<D62);
// if(data&8) GPIOB_ODR|=(1<<D72);
// // pulse EN2 ONLY
// GPIOB_ODR |= (1<<EN2);
// delay();
// GPIOB_ODR &= ~(1<<EN2);
// }
// void lcd2_cmd(unsigned char cmd){
// GPIOB_ODR &= ~(1<<RS2);
// send4bit2(cmd>>4);
// send4bit2(cmd&0x0F);
// }
// void lcd2_data(unsigned char data){
// GPIOB_ODR |= (1<<RS2);
// send4bit2(data>>4);
// send4bit2(data&0x0F);
// }
// // ================= KEYPAD =================
// char keys[4][4]={
// {'1','2','3','A'},
// {'4','5','6','B'},
// {'7','8','9','C'},
// {'*','0','#','D'}
// };
// // ================= LIFT =================
// typedef struct{
// int current_floor;
// int target_floor;
// }Lift;
// Lift lifts[4]={{1,1},{5,5},{8,8},{3,3}};
// int abs_val(int x){ return x<0?-x:x; }
// int find_best_lift(int target){
// int min=100,best=0;
// for(int i=0;i<4;i++){
// int d=abs_val(lifts[i].current_floor-target);
// if(d<min){ min=d; best=i;}
// }
// return best;
// }
// // ================= DISPLAY ALL LIFTS =================
// void update_lift_display()
// {
// // line 1
// lcd2_cmd(0x80);
// for(int i=0;i<2;i++){
// int f = lifts[i].current_floor;
// char d = (f < lifts[i].target_floor) ? 'U' :
// (f > lifts[i].target_floor) ? 'D' : '-';
// lcd2_data('L'); lcd2_data(i+'1'); lcd2_data(':');
// if(f >= 10){
// lcd2_data((f/10)+'0');
// lcd2_data((f%10)+'0');
// } else {
// lcd2_data(f+'0');
// }
// lcd2_data('('); lcd2_data(d); lcd2_data(')');
// lcd2_data(' ');
// }
// // line 2
// lcd2_cmd(0xC0);
// for(int i=2;i<4;i++){
// int f = lifts[i].current_floor;
// char d = (f < lifts[i].target_floor) ? 'U' :
// (f > lifts[i].target_floor) ? 'D' : '-';
// lcd2_data('L'); lcd2_data(i+'1'); lcd2_data(':');
// if(f >= 10){
// lcd2_data((f/10)+'0');
// lcd2_data((f%10)+'0');
// } else {
// lcd2_data(f+'0');
// }
// lcd2_data('('); lcd2_data(d); lcd2_data(')');
// lcd2_data(' ');
// }
// // reset control lines
// GPIOB_ODR &= ~(1<<RS2);
// GPIOB_ODR &= ~(1<<EN2);
// }
// // ================= MAIN =================
// int main(){
// // Enable GPIOA + GPIOB
// RCC_IOPENR |= (1<<0);
// RCC_IOPENR |= (1<<1);
// // LCD pins
// for(int i=0;i<=11;i++){
// GPIOB_MODER &= ~(3<<(i*2));
// GPIOB_MODER |= (1<<(i*2));
// }
// // KEYPAD
// for(int i=0;i<4;i++){
// GPIOA_MODER &= ~(3<<(i*2));
// GPIOA_MODER |= (1<<(i*2));
// }
// for(int i=4;i<8;i++){
// GPIOA_MODER &= ~(3<<(i*2));
// GPIOA_PUPDR &= ~(3<<(i*2));
// GPIOA_PUPDR |= (2<<(i*2));
// }
// delay();
// // LCD1 init
// send4bit(0x03); delay(); send4bit(0x03); delay(); send4bit(0x03); delay(); send4bit(0x02);
// lcd_cmd(0x28); lcd_cmd(0x0C); lcd_cmd(0x06); lcd_cmd(0x01);
// // LCD2 init
// send4bit2(0x03); delay(); send4bit2(0x03); delay(); send4bit2(0x03); delay(); send4bit2(0x02);
// lcd2_cmd(0x28); lcd2_cmd(0x0C); lcd2_cmd(0x06); lcd2_cmd(0x01);
// int floor=0; char key;
// while(1){
// // ==== MOVE LIFTS ====
// static int move_counter = 0;
// move_counter++;
// if(move_counter > 20) // controls speed
// {
// for(int i=0;i<4;i++){
// if(lifts[i].current_floor < lifts[i].target_floor)
// lifts[i].current_floor++;
// else if(lifts[i].current_floor > lifts[i].target_floor)
// lifts[i].current_floor--;
// }
// move_counter = 0;
// }
// // ==== KEYPAD ====
// key=0;
// for(int r=0;r<4;r++){
// GPIOA_ODR &= ~(0x0F);
// GPIOA_ODR |= (1<<r);
// delay();
// for(int c=0;c<4;c++){
// if(GPIOA_IDR & (1<<(c+4))){
// key=keys[r][c];
// }
// }
// }
// if(key){
// // wait release
// int pressed=1;
// while(pressed){
// pressed=0;
// for(int r=0;r<4;r++){
// GPIOA_ODR &= ~(0x0F);
// GPIOA_ODR |= (1<<r);
// for(int c=0;c<4;c++){
// if(GPIOA_IDR & (1<<(c+4))) pressed=1;
// }
// }
// }
// delay();
// if(key>='0' && key<='9'){
// floor=floor*10+(key-'0');
// lcd_cmd(0x01);
// lcd_data('F');lcd_data('l');lcd_data('o');lcd_data('o');lcd_data('r');lcd_data(':');
// lcd_data(' '); lcd_data(floor+'0');
// }
// else if(key=='#'){
// if(floor<1 || floor>12){
// lcd_cmd(0x01);
// lcd_data('I');lcd_data('n');lcd_data('v');lcd_data('a');lcd_data('l');lcd_data('i');lcd_data('d');
// floor=0; continue;
// }
// int lift=find_best_lift(floor);
// lifts[lift].target_floor=floor;
// lcd_cmd(0x01);
// lcd_data('L');lcd_data('i');lcd_data('f');lcd_data('t');lcd_data(':');
// lcd_data(' '); lcd_data(lift+'1');
// GPIOB_ODR &= ~(1<<RS);
// GPIOB_ODR &= ~(1<<EN);
// floor=0;
// }
// else if(key=='*'){
// floor=0;
// lcd_cmd(0x01);
// }
// }
// // ==== UPDATE LCD2 ====
// static int counter = 0;
// counter++;
// if(counter > 50) // adjust if needed
// {
// update_lift_display();
// counter = 0;
// }
// delay();
// }
// }
// ================= RCC =================
#define RCC_IOPENR (*(volatile unsigned int*)0x4002102C)
// ================= GPIOA =================
#define GPIOA_MODER (*(volatile unsigned int*)0x50000000)
#define GPIOA_IDR (*(volatile unsigned int*)0x50000010)
#define GPIOA_ODR (*(volatile unsigned int*)0x50000014)
#define GPIOA_PUPDR (*(volatile unsigned int*)0x5000000C)
// ================= GPIOB =================
#define GPIOB_MODER (*(volatile unsigned int*)0x50000400)
#define GPIOB_ODR (*(volatile unsigned int*)0x50000414)
// ================= LCD1 =================
#define RS 0
#define EN 1
#define D4 2
#define D5 3
#define D6 4
#define D7 5
// ================= LCD2 =================
#define RS2 6
#define EN2 7
#define D42 8
#define D52 9
#define D62 10
#define D72 11
// ================= DELAY =================
void delay(){ for(volatile int i=0;i<30000;i++); }
// ================= LCD1 =================
void send4bit(unsigned char data){
GPIOB_ODR &= ~((1<<D4)|(1<<D5)|(1<<D6)|(1<<D7));
if(data&1) GPIOB_ODR|=(1<<D4);
if(data&2) GPIOB_ODR|=(1<<D5);
if(data&4) GPIOB_ODR|=(1<<D6);
if(data&8) GPIOB_ODR|=(1<<D7);
GPIOB_ODR |= (1<<EN);
delay();
GPIOB_ODR &= ~(1<<EN);
}
void lcd_cmd(unsigned char cmd){
GPIOB_ODR &= ~(1<<RS);
send4bit(cmd>>4);
send4bit(cmd&0x0F);
}
void lcd_data(unsigned char data){
GPIOB_ODR |= (1<<RS);
send4bit(data>>4);
send4bit(data&0x0F);
}
// ================= LCD2 =================
void send4bit2(unsigned char data){
GPIOB_ODR &= ~((1<<D42)|(1<<D52)|(1<<D62)|(1<<D72));
if(data&1) GPIOB_ODR|=(1<<D42);
if(data&2) GPIOB_ODR|=(1<<D52);
if(data&4) GPIOB_ODR|=(1<<D62);
if(data&8) GPIOB_ODR|=(1<<D72);
GPIOB_ODR |= (1<<EN2);
delay();
GPIOB_ODR &= ~(1<<EN2);
}
void lcd2_cmd(unsigned char cmd){
GPIOB_ODR &= ~(1<<RS2);
send4bit2(cmd>>4);
send4bit2(cmd&0x0F);
}
void lcd2_data(unsigned char data){
GPIOB_ODR |= (1<<RS2);
send4bit2(data>>4);
send4bit2(data&0x0F);
}
// ================= KEYPAD =================
char keys[4][4]={
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
// ================= LIFT =================
typedef struct{
int current_floor;
int target_floor;
}Lift;
Lift lifts[4]={{1,1},{5,5},{8,8},{3,3}};
int abs_val(int x){ return x<0?-x:x; }
int find_best_lift(int target){
int min=100,best=0;
for(int i=0;i<4;i++){
int d=abs_val(lifts[i].current_floor-target);
if(d<min){ min=d; best=i;}
}
return best;
}
// ================= LCD2 DISPLAY =================
void update_lift_display(){
lcd2_cmd(0x80);
for(int i=0;i<2;i++){
int f=lifts[i].current_floor;
char d=(f<lifts[i].target_floor)?'U':(f>lifts[i].target_floor)?'D':'-';
lcd2_data('L'); lcd2_data(i+'1'); lcd2_data(':');
if(f>=10){
lcd2_data((f/10)+'0');
lcd2_data((f%10)+'0');
} else {
lcd2_data(f+'0');
}
lcd2_data('('); lcd2_data(d); lcd2_data(')');
lcd2_data(' ');
}
lcd2_cmd(0xC0);
for(int i=2;i<4;i++){
int f=lifts[i].current_floor;
char d=(f<lifts[i].target_floor)?'U':(f>lifts[i].target_floor)?'D':'-';
lcd2_data('L'); lcd2_data(i+'1'); lcd2_data(':');
if(f>=10){
lcd2_data((f/10)+'0');
lcd2_data((f%10)+'0');
} else {
lcd2_data(f+'0');
}
lcd2_data('('); lcd2_data(d); lcd2_data(')');
lcd2_data(' ');
}
GPIOB_ODR &= ~(1<<RS2);
GPIOB_ODR &= ~(1<<EN2);
}
// ================= MAIN =================
int main(){
RCC_IOPENR |= (1<<0);
RCC_IOPENR |= (1<<1);
for(int i=0;i<=11;i++){
GPIOB_MODER &= ~(3<<(i*2));
GPIOB_MODER |= (1<<(i*2));
}
for(int i=0;i<4;i++){
GPIOA_MODER &= ~(3<<(i*2));
GPIOA_MODER |= (1<<(i*2));
}
for(int i=4;i<8;i++){
GPIOA_MODER &= ~(3<<(i*2));
GPIOA_PUPDR &= ~(3<<(i*2));
GPIOA_PUPDR |= (2<<(i*2));
}
delay();
// LCD1 init
send4bit(0x03); delay(); send4bit(0x03); delay(); send4bit(0x03); delay(); send4bit(0x02);
lcd_cmd(0x28); lcd_cmd(0x0C); lcd_cmd(0x06); lcd_cmd(0x01);
// LCD2 init
send4bit2(0x03); delay(); send4bit2(0x03); delay(); send4bit2(0x03); delay(); send4bit2(0x02);
lcd2_cmd(0x28); lcd2_cmd(0x0C); lcd2_cmd(0x06); lcd2_cmd(0x01);
int floor=0, key;
int move_counter=0;
int display_counter=0;
while(1){
// movement slow
move_counter++;
if(move_counter>20){
for(int i=0;i<4;i++){
if(lifts[i].current_floor < lifts[i].target_floor) lifts[i].current_floor++;
else if(lifts[i].current_floor > lifts[i].target_floor) lifts[i].current_floor--;
}
move_counter=0;
}
// keypad scan
key=0;
for(int r=0;r<4;r++){
GPIOA_ODR &= ~(0x0F);
GPIOA_ODR |= (1<<r);
delay();
for(int c=0;c<4;c++){
if(GPIOA_IDR & (1<<(c+4))){
key=keys[r][c];
}
}
}
if(key){
int pressed=1;
while(pressed){
pressed=0;
for(int r=0;r<4;r++){
GPIOA_ODR &= ~(0x0F);
GPIOA_ODR |= (1<<r);
for(int c=0;c<4;c++){
if(GPIOA_IDR & (1<<(c+4))) pressed=1;
}
}
}
delay();
if(key>='0' && key<='9'){
floor=floor*10+(key-'0');
lcd_cmd(0x01);
lcd_data('F');lcd_data('l');lcd_data('o');lcd_data('o');lcd_data('r');lcd_data(':');lcd_data(' ');
if(floor>=10){
lcd_data((floor/10)+'0');
lcd_data((floor%10)+'0');
} else {
lcd_data(floor+'0');
}
}
else if(key=='#'){
if(floor<1 || floor>12){
lcd_cmd(0x01);
lcd_data('I');lcd_data('n');lcd_data('v');lcd_data('a');lcd_data('l');lcd_data('i');lcd_data('d');
floor=0; continue;
}
int lift=find_best_lift(floor);
lifts[lift].target_floor=floor;
lcd_cmd(0x01);
// line 1
lcd_data('F');lcd_data('l');lcd_data('o');lcd_data('o');lcd_data('r');lcd_data(':');lcd_data(' ');
if(floor>=10){
lcd_data((floor/10)+'0');
lcd_data((floor%10)+'0');
} else {
lcd_data(floor+'0');
}
// line 2
lcd_cmd(0xC0);
lcd_data('L');lcd_data('i');lcd_data('f');lcd_data('t');lcd_data(':');lcd_data(' ');
lcd_data(lift+'1');
GPIOB_ODR &= ~(1<<RS);
GPIOB_ODR &= ~(1<<EN);
floor=0;
}
else if(key=='*'){
floor=0;
lcd_cmd(0x01);
}
}
// LCD2 update slow
display_counter++;
if(display_counter>20){
update_lift_display();
display_counter=0;
}
delay();
}
}