Source Code

/*
 Copyright 2009, Mike Jacobs
 This file is part of Handy Board Interactive C Events (HB-ICE).

 HB-ICE is free software: you can redistribute it and/or modify
 it under the terms of the Lesser GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 HB-ICE is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 Lesser GNU General Public License for more details.

 You should have received a copy of the Lesser GNU General Public License
 along with HB-ICE.  If not, see . 
*/

buttons.ic

#define EVENT_ID_START_BUTTON 0
#define EVENT_ID_STOP_BUTTON 1
#define BUTTON_POLLING_TIME 0.2
#define EVENT_TYPE_BUTTON_RELEASED 0

struct Event buttonEvent_;
struct Event *buttonEvent = &buttonEvent_;

void signalButtonEvent(int id){
    buttonEvent->id = id;
    signalEvent(buttonEvent);
}

void monitorButtons(){
    buttonEvent->type = EVENT_TYPE_BUTTON_RELEASED;
    while(TRUE){
        if(start_button()){
            // button pressed, wait for release
            while(start_button()){}
            signalButtonEvent(EVENT_ID_START_BUTTON);
        }
        if(stop_button()){
            // button pressed, wait for release
            while(stop_button()){}
            signalButtonEvent(EVENT_ID_STOP_BUTTON);
        }
        sleep(BUTTON_POLLING_TIME);
    }
}

PROCESS_ID monitoringButtonsProcess = -1;
BOOLEAN monitoringButtons = FALSE;
void startMonitoringButtons(){
    if(monitoringButtons == FALSE){
        monitoringButtons = TRUE;
        monitoringButtonsProcess = start_process(monitorButtons());
    }
    else {
        tone(300.0, 1.5);
    }
}

handybug.ic

#use "types.ic"
#use "events.ic"
#use "buttons.ic"
#use "digital.ic"
#use "motors.ic"

void initialize(){
    initializeEventQueue();
    intializeDigitalEvents();
    initializeMotors();
    startMonitoringButtons();
}

#define RIGHT_MOTOR 0
#define LEFT_MOTOR 3
#define RIGHT_BUMPER 13
#define LEFT_BUMPER 15

BOOLEAN started = FALSE;
void start(){
    if(!started){
        started = TRUE;
        monitorDigital(RIGHT_BUMPER, TRUE);
        monitorDigital(LEFT_BUMPER, TRUE);
        startMonitoringDigitalInputs();
        printf("running...\n");
        moveForward(0.0);
    }
} 

void handleButtonReleasedEvent(struct Event* event){
    int eventId = event->id;
    switch(eventId) {
        case EVENT_ID_START_BUTTON:
          start();
        break;
        case EVENT_ID_STOP_BUTTON:
          stop();
        break;
    }
}

void moveForward(float duration){
    changeMotorSpeed(RIGHT_MOTOR,100);
    changeMotorSpeed(LEFT_MOTOR,100);
    sleep(duration);
}

void stopMoving(){
    stopAllMotors();
}

void moveBackward(float duration){
    changeMotorSpeed(RIGHT_MOTOR,-100);
    changeMotorSpeed(LEFT_MOTOR,-100);
    sleep(duration);
}

void turnRight(float duration){
    changeMotorSpeed(RIGHT_MOTOR,-100);
    changeMotorSpeed(LEFT_MOTOR,100);
    sleep(duration);
}

void turnLeft(float duration){
    changeMotorSpeed(RIGHT_MOTOR,100);
    changeMotorSpeed(LEFT_MOTOR,-100);
    sleep(duration);
}

void handleDigitalChangedEvent(struct Event* event){
    int port = event->id;
    int value = event->value;
    if(value == CLOSED){
        stopMoving();
        moveBackward(0.5);
        stopMoving();
        if(port == LEFT_BUMPER){
            turnRight(0.2);
        }
        else {
            if(port == RIGHT_BUMPER){
                turnLeft(0.2);
            }
        }
        moveForward(0.0);
    }
}

void handleEvent(struct Event* event){
    int eventType = event->type;
    switch(eventType){
        case EVENT_TYPE_BUTTON_RELEASED:
          handleButtonReleasedEvent(event);
        break;
        case EVENT_TYPE_DIGITAL_CHANGED:
          handleDigitalChangedEvent(event);
        break;
    }
}

// Main event loop program...
BOOLEAN looping = TRUE;

void stop(){
    stopMoving();
    stopMonitoringDigitalInputs();
    started = FALSE;
    looping = FALSE;
}

void main(){
    struct Event* event = NULL;
    initialize();
    printf("press start\n");
    while(looping){
        event = dequeue(eventQueue);
        if(event != NULL){
            handleEvent(event);
        }
    }
    printf("done\n");
}

digital.ic

#define NUM_DIGITAL_INPUTS 9
#define FIRST_DIGITAL_INPUT 7
#define OPEN 0
#define CLOSED 1
#define DIGITAL_POLLING_TIME 0.2
#define EVENT_TYPE_DIGITAL_CHANGED 1

// DIGITAL INPUTS (ports 7:15)
struct Event digitalEvent7_ = {EVENT_TYPE_DIGITAL_CHANGED, 7, 0};
struct Event digitalEvent8_ = {EVENT_TYPE_DIGITAL_CHANGED, 8, 0};
struct Event digitalEvent9_ = {EVENT_TYPE_DIGITAL_CHANGED, 9, 0};
struct Event digitalEvent10_ = {EVENT_TYPE_DIGITAL_CHANGED, 10, 0};
struct Event digitalEvent11_ = {EVENT_TYPE_DIGITAL_CHANGED, 11, 0};
struct Event digitalEvent12_ = {EVENT_TYPE_DIGITAL_CHANGED, 12, 0};
struct Event digitalEvent13_ = {EVENT_TYPE_DIGITAL_CHANGED, 13, 0};
struct Event digitalEvent14_ = {EVENT_TYPE_DIGITAL_CHANGED, 14, 0};
struct Event digitalEvent15_ = {EVENT_TYPE_DIGITAL_CHANGED, 15, 0};
struct Event *digitalEvent7 = &digitalEvent7_;
struct Event *digitalEvent8 = &digitalEvent8_;
struct Event *digitalEvent9 = &digitalEvent9_;
struct Event *digitalEvent10 = &digitalEvent10_;
struct Event *digitalEvent11 = &digitalEvent11_;
struct Event *digitalEvent12 = &digitalEvent12_;
struct Event *digitalEvent13 = &digitalEvent13_;
struct Event *digitalEvent14 = &digitalEvent14_;
struct Event *digitalEvent15 = &digitalEvent15_;
struct Event (*digitalEvents)[NUM_DIGITAL_INPUTS];

void intializeDigitalEvents(){
    digitalEvents[0] = digitalEvent7;
    digitalEvents[1] = digitalEvent8;
    digitalEvents[2] = digitalEvent9;
    digitalEvents[3] = digitalEvent10;
    digitalEvents[4] = digitalEvent11;
    digitalEvents[5] = digitalEvent12;
    digitalEvents[6] = digitalEvent13;
    digitalEvents[7] = digitalEvent14;
    digitalEvents[8] = digitalEvent15;
}

void signalDigitalEvent(int index, int value){
    struct Event* event = digitalEvents[index];
    event->value = value;
    signalEvent(event);
}

int getStoredDigitalPortValue(int index){
    struct Event* event = digitalEvents[index];
    return event->value;
}

BOOLEAN monitoringDigital[] = {FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE};

void monitorDigital(int port, BOOLEAN value){
    monitoringDigital[port-FIRST_DIGITAL_INPUT] = value;
}

void monitorDigitalInputs(){
    int oldPortValue = 0;
    int currentPortValue = 0;
    int port;
    while(TRUE){
        int i;
        for(i = 0; i < NUM_DIGITAL_INPUTS; i++){
            BOOLEAN monitoring = monitoringDigital[i];
            if(monitoring){
                port = i + FIRST_DIGITAL_INPUT;
                oldPortValue = getStoredDigitalPortValue(i);
                currentPortValue = digital(port);
                if(oldPortValue != currentPortValue){
                    signalDigitalEvent(i, currentPortValue);
                }
            }
        }
        sleep(DIGITAL_POLLING_TIME);
    }
}

PROCESS_ID monitoringDigitalInputsProcess = -1;
void startMonitoringDigitalInputs(){
    monitoringDigitalInputsProcess = start_process(monitorDigitalInputs());
}
void stopMonitoringDigitalInputs(){
    kill_process(monitoringDigitalInputsProcess);
}

events.ic

#use "types.ic"

// EVENTS and EVENT QUEUE

struct Event {
    int type;
    int id;
    int value;
    long timestamp;
};

#define MAX_QUEUE_DEPTH 6

struct EventQueue {
    int front;
    int rear;
    int size;
    struct Event (*events)[MAX_QUEUE_DEPTH];
};
struct EventQueue eventQueue_;
struct EventQueue *eventQueue = &eventQueue_;
/*
The event queue is a FIFO queue.
Enqueue requests push elements to the rear of the queue.
Dequeue requests pop elements from the front of the queue.
*/
void initializeEventQueue(){
    eventQueue->front = 1;
    eventQueue->rear = 0;
    eventQueue->size = 0;
}

/*
Increments the rear index with wrap around
and pushes an event to the queue.
*/
BOOLEAN enqueue(struct EventQueue* q, struct Event* event) {
    BOOLEAN answer;
    int i = 0;
    if (q->size == MAX_QUEUE_DEPTH) {
        answer = FALSE;
    }
    else {
        i = (q->rear + 1) % MAX_QUEUE_DEPTH;
        q->rear = i;
        q->events[i] = event;
        q->size = q->size + 1;
        answer = TRUE;
        event->timestamp = mseconds();
    }
    return answer;
}
/*
Pops an event from the front of the queue
and increments the front index with wrap around.
*/
struct Event* dequeue(struct EventQueue* q){
    struct Event* event = NULL;
    int i = 0;
    int size = q->size;
    if(size > 0){
        i = q->front;
        event = q->events[i];
        i++;
        i = i % MAX_QUEUE_DEPTH;
        q->front = i;
        q->size = size - 1;
    }
    return event;
}

void printQueue(struct EventQueue* q){
    int size = q->size;
    int front = q->front;
    int rear = q->rear;
    printf(" size: %d, front: %d, rear: %d \n", size, front, rear);
}

void printEventQueue(){
    printQueue(eventQueue);
}

void signalEvent(struct Event* event){
    BOOLEAN enqueued;
    enqueued = enqueue(eventQueue, event);
}

motors.ic

#define NUMBER_OF_MOTORS 4

int motorSpeeds[NUMBER_OF_MOTORS];

void initializeMotors(){
    int i;
    for(i=0; i<NUMBER_OF_MOTORS; i++){
        motorSpeeds[i] = 0;
    }
}

void changeMotorSpeed(int motorID, int speed){
    int currentSpeed = motorSpeeds[motorID];
    if(currentSpeed != speed){
        motorSpeeds[motorID] = speed;
        motor(motorID, speed);
    }
}

void stopMotor(int motorID){
    changeMotorSpeed(motorID, 0);
}

void stopAllMotors(){
    ao();
}

types.ic

#define BOOLEAN int
#define PROCESS_ID int
#define TRUE 1
#define FALSE 0



Follow

Get every new post delivered to your Inbox.