DAT290 / kod / Dorrsensor / dorrsensor.c
dorrsensor.c
Raw
#include "misc.h"
#include "stm32f4xx_can.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "SysTick.h"
#include "CAN_interface.h"
#include "CAN_messageTypes.h"
#include "USART_dump.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_NUMBER_OF_DOORS 15

__attribute__((naked)) __attribute__((section (".start_section")) )
void startup ( void )
{
__asm__ volatile(" LDR R0,=0x2001C000\n");		/* set stack */
__asm__ volatile(" MOV SP,R0\n");
__asm__ volatile(" BL main\n");					/* call main */
__asm__ volatile(".L1: B .L1\n");				/* never return */
}

uint16_t auxId;

//is true when the central unit has sent a can message with init info
bool isInited = false;

// queue struct
typedef struct{
    int mainTop;
    int helperTop;
    char * mainQueue[MAX_NUMBER_OF_DOORS];
    char * helperQueue[MAX_NUMBER_OF_DOORS];
} Queue;


uint16_t alarmDelayms;
uint8_t numberOfDoors;

bool activeDoors[MAX_NUMBER_OF_DOORS];
bool alarmsCalled[MAX_NUMBER_OF_DOORS];

Queue alarms;
// the two functions below are defined to create a queue to see who started each timer
void enqueue(char data){
    while(alarms.mainTop > -1){
        alarms.helperTop++;
        alarms.helperQueue[alarms.helperTop] = alarms.mainQueue[alarms.mainTop];
        alarms.mainTop--;
    }
    alarms.mainTop++;
    alarms.mainQueue[alarms.mainTop];
    while(alarms.helperTop > -1){
        alarms.mainTop++;
        alarms.mainQueue[alarms.helperTop] = alarms.helperQueue[alarms.mainTop];
        alarms.helperTop--;
    }
    
}

char dequeue(){
    char data = alarms.mainQueue[alarms.mainTop];
    alarms.mainTop--;
    return data;
}


//sets the door pins to input and pullup
void doorAlarmInit(){
    
    GPIO_InitTypeDef GPIOx_init;
    
    int pinNumber = 1;
    for(int i = 0; i < MAX_NUMBER_OF_DOORS; i++){
        GPIOx_init.GPIO_Pin |= pinNumber;
        pinNumber = 1<<pinNumber;
    }
    GPIOx_init.GPIO_Mode = GPIO_Mode_IN;
    GPIOx_init.GPIO_PuPd = GPIO_PuPd_UP;
    
    GPIO_Init(GPIOD, &GPIOx_init);
}
//sets the lamps pins to output
void lampsInit(){
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
    
    GPIO_InitTypeDef GPIOx_init;
    
    GPIOx_init.GPIO_Pin = GPIO_Pin_All;
    GPIOx_init.GPIO_Mode = GPIO_Mode_OUT;
    GPIOx_init.GPIO_OType = GPIO_OType_PP;
    GPIOx_init.GPIO_Speed = GPIO_Low_Speed;
    GPIOx_init.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOE, &GPIOx_init);
}
//all of the functions below are handlers for diffrent types of can messages
void aux_config_handler(Message message){
    numberOfDoors = message.data[0];
    alarmDelayms = (message.data[1]<<8) || message.data[2];
}

void aux_init_handler(Message message){
    auxId = (message.data[1] << 8) || message.data[2];
    numberOfDoors = message.data[0];
    alarmDelayms = (message.data[3]<<8) || message.data[4];
    isInited = true;
}

void aux_activate_handler(Message message){
    if(message.data[0] == 0xff){
        for(int i = 0; i < numberOfDoors; i++){
            activeDoors[i] = 1;
        }   
    }else{
        activeDoors[message.data[0]] = 1;
    }
}

void aux_deact_handler(Message message){
    if(message.data == 0xff){
        for(int i = 0; i < numberOfDoors; i++){
            activeDoors[i] = 0;
        }   
    }else{
        activeDoors[message.data[0]] = 0;
    }
}

void aux_info_handler(Message message){
    uint8_t* data;
    data[0] = alarmDelayms && 0xff;
    data[1] = alarmDelayms && 0xff00;
    data[2] = numberOfDoors;
    for(int i = 0; i < numberOfDoors; i++){
        if(i < 8){
            data[3] |= activeDoors[i] && (1<<i);
        }else{
            data[4] |= activeDoors[i] && (1<<(i-8));
        }
    }
}
// inits can, gpio and timers and sets necisary local variables, and sends a request to the central unit asking to be inited
void init(){
    SysTick_initTimers();
    lampsInit();
    doorAlarmInit(GPIOD);
    CAN_init(false);
    
    alarms.helperTop = -1;
    alarms.mainTop = -1;
    
     for(int i = 0; i < MAX_NUMBER_OF_DOORS; i++){
        alarmsCalled[i] = 0;
    }
    
    CAN_registerMessageHandler(AUXILIARY_INIT, aux_init_handler);
    CAN_registerMessageHandler(AUX_ACTIVATE, aux_activate_handler);
    CAN_registerMessageHandler(AUX_DEACTIVATE, aux_deact_handler);
    CAN_registerMessageHandler(AUX_CONFIG, aux_config_handler);
    CAN_registerMessageHandler(AUX_INFO, aux_info_handler);
    
    CAN_auxRequestInit(0);
}
// sends an alarm message if a door is still open after a timer runs out
void callAlarm(){
    DUMP("callAlarm");
    int alarmCaller = dequeue(); 
    alarmsCalled[alarmCaller] = 0;
    if(!GPIO_ReadInputDataBit(GPIOD, (alarmCaller<<1)) && activeDoors[alarmCaller]){
        CAN_send(auxId, ALARM, 0,0);
        DUMP("timer finished alarm message sent");
    }else{
        GPIO_WriteBit(GPIOE, GPIO_Pin_15, Bit_RESET);
    }
}

// checks if a door that is open is active and if so calls an alarm by calling a timer and turing on the alarm light
void checkDoors(){
    for(int i = 0; i < numberOfDoors; i++){
        if(activeDoors[i]){
            if(GPIO_ReadInputDataBit(GPIOD, (1<<i)) && !alarmsCalled[i]){
                DUMP("alarm went off, light should be on");
                GPIO_WriteBit(GPIOE, GPIO_Pin_15, Bit_SET);
                enqueue(i);
                SysTick_startTimer(alarmDelayms, callAlarm);
                alarmsCalled[i] = 1;
            }
        }
    }
}
// checks if a door is unlocked and if so turns on the green light
void checkLamps(){
    for(int i = 0; i < numberOfDoors; i++){
        if(activeDoors[i]){
            GPIO_WriteBit(GPIOE, (1<<i), Bit_RESET);
        }else{
            GPIO_WriteBit(GPIOE, (1<<i), Bit_SET);
        }
    }
        
}






void main(void)
{
    // inits the local parts and asks the cental unit to be inited, then it waits for the central unit to send 
    // an init message then starts checking the doors and lights/turns of the lamps accordingly
    init();
    while(!isInited);
    while(1){
        checkDoors();
        checkLamps();
    }
}