diff --git a/lcdController.c b/lcdController.c new file mode 100644 index 0000000000000000000000000000000000000000..0cc751209e21f65c598235bdd7ec91ec265237a2 --- /dev/null +++ b/lcdController.c @@ -0,0 +1,386 @@ +#include <arpa/inet.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <unistd.h> +#include <pthread.h> +#include <wiringPi.h> +#include <wiringPiI2C.h> +#include <wiringPi.h> +#include <stdbool.h> + +#define I2C_ADDR 0x27 // LCD 주소 + +#define LCD_CHR 1 // Mode - Sending data +#define LCD_CMD 0 // Mode - Sending command + +#define LINE1 0x80 // 첫번째 줄 +#define LINE2 0xC0 // 두번째 줄 + +#define LCD_BACKLIGHT 0x08 // On +// LCD_BACKLIGHT = 0x00 # Off + +#define ENABLE 0b00000100 // Enable bit + + +#define MSG_SIZE 1024 + +#define IN 0 +#define OUT 1 +#define PWM 0 + +#define LOW 0 +#define HIGH 1 +#define VALUE_MAX 256 +#define DIRECTION_MAX 256 + + + +void lcd_init(void); +void lcd_byte(int bits, int mode); +void lcd_toggle_enable(int bits); +void lcdLoc(int line); //move cursor +void ClrLcd(void); // clr LCD return home +void typeln(const char *s); +int fd; // seen by all subroutines + +char msg[MSG_SIZE] = {0}; +char tempMsg[MSG_SIZE] = {0}; +static int PWMExport(int pwmnum) { +#define BUFFER_MAX 3 + char buffer[BUFFER_MAX]; + int fd, byte; + + fd = open("/sys/class/pwm/pwmchip0/export", O_WRONLY); + if (-1 == fd) { + fprintf(stderr, "Failed to open export for export!\n"); + return (-1); + } + + byte = snprintf(buffer, BUFFER_MAX, "%d", pwmnum); + write(fd, buffer, byte); + close(fd); + + sleep(1); + + return (0); +} + +static int PWMEnable(int pwmnum) { + static const char s_enable_str[] = "1"; + + char path[DIRECTION_MAX]; + int fd; + + snprintf(path, DIRECTION_MAX, "/sys/class/pwm/pwmchip0/pwm0/enable", pwmnum); + fd = open(path, O_WRONLY); + if (-1 == fd) { + fprintf(stderr, "Failed to open in enable!\n"); + return -1; + } + + write(fd, s_enable_str, strlen(s_enable_str)); + close(fd); + + return (0); +} + +static int PWMWritePeriod(int pwmnum, int value) { + char s_value_str[VALUE_MAX]; + char path[VALUE_MAX]; + int fd, byte; + + snprintf(path, VALUE_MAX, "/sys/class/pwm/pwmchip0/pwm0/period", pwmnum); + fd = open(path, O_WRONLY); + if (-1 == fd) { + fprintf(stderr, "Failed to open in period!\n"); + return (-1); + } + byte = snprintf(s_value_str, VALUE_MAX, "%d", value); + + if (-1 == write(fd, s_value_str, byte)) { + fprintf(stderr, "Failed to write value in period!\n"); + close(fd); + return -1; + } + close(fd); + + return (0); +} + +static int PWMWriteDutyCycle(int pwmnum, int value) { + char s_value_str[VALUE_MAX]; + char path[VALUE_MAX]; + int fd, byte; + + snprintf(path, VALUE_MAX, "/sys/class/pwm/pwmchip0/pwm0/duty_cycle", pwmnum); + fd = open(path, O_WRONLY); + if (-1 == fd) { + fprintf(stderr, "Failed to open in duty cycle!\n"); + return (-1); + } + byte = snprintf(s_value_str, VALUE_MAX, "%d", value); + + if (-1 == write(fd, s_value_str, byte)) { + fprintf(stderr, "Failed to write value in duty cycle!\n"); + close(fd); + return -1; + } + close(fd); + + return (0); +} + +void error_handling(char *message) { + fputs(message, stderr); + fputc('\n', stderr); + exit(1); +} + +//lcd thread +void* lcd( void *data ) { + + + int str_len = 0; + + int sock = *((int*)data); + + bool isS = true; + + if (wiringPiSetup () == -1) exit (1); + + fd = wiringPiI2CSetup(I2C_ADDR); + + lcd_init(); // setup LCD + + char* sleepMode1 = "Sleep Mode On"; + char* sleepMode2 = "Go to dreamland"; + char* wakeUpMode1 = "Wake up !!!"; + char* wakeUpMode2 = "Out of dreamland"; + char* motion1 = "Motion Count"; + char motion2[100] = "Total : "; + + + while(1){ + + + if(strcmp("s", msg) == 0 && isS){ // 수면모드 on + printf("수면모드 on\n"); + ClrLcd(); + lcdLoc(LINE1); + typeln(sleepMode1); + lcdLoc(LINE2); + typeln(sleepMode2); + isS = false; + } + if(strcmp("e", msg) == 0){ // 수면 모드 off + printf("수면모드 off\n"); + ClrLcd(); + lcdLoc(LINE1); + typeln(wakeUpMode1); + lcdLoc(LINE2); + typeln(wakeUpMode2); + + // motion number display + + str_len = read(sock, msg, sizeof(msg)); // 다시 서버로부터 메세지 기다림 + + if (str_len == -1) error_handling("read() error"); + if(str_len == 0) break; + printf("motion num: %s\n", msg); + strcat(motion2, msg); + ClrLcd(); + lcdLoc(LINE1); + typeln(motion1); + lcdLoc(LINE2); + typeln(motion2); + delay(7000); + ClrLcd(); + PWMWriteDutyCycle(PWM, 0); + break; + } + } + + +} + +//led thread +void* led( void *data ) { + + int sock = *((int*)data); + int str_len = 0; + int rsCount = 0; + bool isRs1 = true; + bool isRs2 = true; + bool isS = true; + bool isRe = true; + + + while (1) { + + if(strcmp("rs1", msg) == 0 && isRs1){ // 첫번째 rs + printf("첫번째 rs1\n"); + PWMWriteDutyCycle(PWM, 4500000); + isRs1 = false; + }else if(strcmp("rs2", msg) == 0 && isRs2){ // 두번째 rs + printf("두번째 rs2\n"); + PWMWriteDutyCycle(PWM, 1000000); + isRs2 = false; + } + + if(strcmp("s", msg) == 0 && isS){ //수면모드 + printf("수면모드\n"); + PWMWriteDutyCycle(PWM, 0); + isS = false; + } + + if(strcmp("re", msg) == 0 && isRe){ //기상 준비 + printf("기상준비\n"); + + for (int i = 0; i < 10000; i++) { // 3초동안 불서서히 켜짐 + PWMWriteDutyCycle(PWM, i * 1000); + usleep(300); + } + isRe = false; + } + + if(strcmp("e", msg) == 0){ // 종료 + PWMWriteDutyCycle(PWM, 10000000); + printf("기상\n"); + break; + } + + } + + + + +} + +int main(int argc, char *argv[]) { + pthread_t p_thread[2]; + int thr_id; + int status; + int sock; + struct sockaddr_in serv_addr; + int str_len; + + + PWMExport(PWM); + PWMWritePeriod(PWM, 10000000); + PWMWriteDutyCycle(PWM, 10000000); + PWMEnable(PWM); + if (argc != 3) { + printf("Usage : %s <IP> <port>\n", argv[0]); + exit(1); + } + + // sockt create + sock = socket(PF_INET, SOCK_STREAM, 0); + if (sock == -1) error_handling("socket() error"); + + // config server info + memset(&serv_addr, 0, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = inet_addr(argv[1]); + serv_addr.sin_port = htons(atoi(argv[2])); + + // connect request to server + if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1) + error_handling("connect() error"); + + printf("서버와 연결\n"); + + + //각 기능에 맞게 스레드 형성 + thr_id = pthread_create(&p_thread[0], NULL, led, (void *)&sock); + if (thr_id < 0) { + perror("thread create error : "); + exit(0); + } + thr_id = pthread_create(&p_thread[1], NULL, lcd, (void *)&sock); + if (thr_id < 0) { + perror("thread create error : "); + exit(0); + } + + memset(tempMsg, 0, sizeof(tempMsg)); + memset(msg, 0, sizeof(msg)); + while(1){ + str_len = read(sock, tempMsg, sizeof(tempMsg)); + printf("tempMsg: %s\n", tempMsg); + strcpy(msg, tempMsg); + if (str_len == -1) error_handling("read() error"); + if(str_len == 0) break; // 서버가 닫히면 클라이언트도 종료 + if(strcmp("e", msg) == 0) break; + } + + pthread_join(p_thread[0], (void **)&status); + pthread_join(p_thread[1], (void **)&status); + + + close(sock); + return 0; +} + +// clr lcd go home loc 0x80 +void ClrLcd(void) { + lcd_byte(0x01, LCD_CMD); + lcd_byte(0x02, LCD_CMD); +} + +// go to location on LCD +void lcdLoc(int line) { + lcd_byte(line, LCD_CMD); +} + +// this allows use of any size string +void typeln(const char *s) { + + while ( *s ) lcd_byte(*(s++), LCD_CHR); + +} + +void lcd_byte(int bits, int mode) { + + //Send byte to data pins + // bits = the data + // mode = 1 for data, 0 for command + int bits_high; + int bits_low; + // uses the two half byte writes to LCD + bits_high = mode | (bits & 0xF0) | LCD_BACKLIGHT ; + bits_low = mode | ((bits << 4) & 0xF0) | LCD_BACKLIGHT ; + + // High bits + wiringPiI2CReadReg8(fd, bits_high); + lcd_toggle_enable(bits_high); + + // Low bits + wiringPiI2CReadReg8(fd, bits_low); + lcd_toggle_enable(bits_low); +} + +void lcd_toggle_enable(int bits) { + // Toggle enable pin on LCD display + delayMicroseconds(500); + wiringPiI2CReadReg8(fd, (bits | ENABLE)); + delayMicroseconds(500); + wiringPiI2CReadReg8(fd, (bits & ~ENABLE)); + delayMicroseconds(500); +} + + +void lcd_init() { + // Initialise display + lcd_byte(0x33, LCD_CMD); // Initialise + lcd_byte(0x32, LCD_CMD); // Initialise + lcd_byte(0x06, LCD_CMD); // Cursor move direction + lcd_byte(0x0C, LCD_CMD); // 0x0F On, Blink Off + lcd_byte(0x28, LCD_CMD); // Data length, number of lines, font size + lcd_byte(0x01, LCD_CMD); // Clear display + delayMicroseconds(500); +} \ No newline at end of file