Robin HerrmannYAKINDU Statechart Tools
Published © LGPL

Finite State Machine on a MSP430

How to program a MSP430G2 Launchpad with Finite State Machines (FSM) using YAKINDU Statechart Tools in your Code Composer Studio.

IntermediateFull instructions provided1 hour1,131
Finite State Machine on a MSP430

Things used in this project

Story

Read more

Code

main.c

C/C++
The main file, which calls the state machine
#include <msp430.h> 
#include "src-gen/BlinkyStateMachine.h"
#include "src/sc_timer_service.h"

BlinkyStateMachine blinky;

//! As we make use of time triggers (after & every) we make use of a generic timer implementation and need a defined number of timers.
#define MAX_TIMERS 4

//! We allocate the desired array of timers.
static sc_timer_t timers[MAX_TIMERS];

//! The timers are managed by a timer service. */
static sc_timer_service_t timer_service;

//! callback implementation for the setting up time events
extern void blinkyStateMachine_setTimer(BlinkyStateMachine* handle, const sc_eventid evid, const sc_integer time_ms, const sc_boolean periodic)
{
    sc_timer_start(&timer_service, handle, evid, time_ms, periodic);
}

//! callback implementation for canceling time events.
extern void blinkyStateMachine_unsetTimer(BlinkyStateMachine* handle, const sc_eventid evid)
{
    sc_timer_cancel(&timer_service, evid);
}

//! defining operations
extern void blinkyStateMachineInternal_init(const BlinkyStateMachine* handle)
{
    WDTCTL = WDT_MDLY_32;
    IE1 |= WDTIE;
    P1DIR |= BIT0;
}

extern void blinkyStateMachineInternal_redOn(const BlinkyStateMachine* handle)
{
    P1OUT |= BIT0;
}

extern void blinkyStateMachineInternal_redOff(const BlinkyStateMachine* handle)
{
    P1OUT &= ~BIT0;
}

void main(void) {
    WDTCTL = WDTPW | WDTHOLD;   // Stop watchdog timer

    // Init timer and state machine
    sc_timer_service_init(&timer_service, timers, MAX_TIMERS,
                (sc_raise_time_event_fp) &blinkyStateMachine_raiseTimeEvent);
    blinkyStateMachine_init(&blinky);
    blinkyStateMachine_enter(&blinky);

    while (1)
    {
        // call state machine every 32 ms
        blinkyStateMachine_runCycle(&blinky);
        __bis_SR_register(LPM0_bits + GIE);
        sc_timer_service_proceed(&timer_service, 32);
    }
}

// WDT ISR
#pragma vector=WDT_VECTOR
__interrupt void watchdog_timer(void)
{
    __bic_SR_register_on_exit(LPM0_bits + GIE);
}

sc_timer_service.c

C/C++
Handles the time events of the state machine
/*
 * sc_timer_service.c
 *
 *  Created on: 13.04.2016
 *      Author: korsinski, terfloth
 */

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

#include "sc_timer_service.h"

/*! \file Implementation of YAKINDU SCT timer functionality based on POSIX threads. */


/*! Callback that is called when a timer fires. */
static void sc_timer_fired(sc_timer_t *timer) {

	timer->service->raise_event(timer->handle, timer->pt_evid);
}



/*! Starts a timer with the specified parameters. */
void sc_timer_start(sc_timer_service_t *this, void* handle, const sc_eventid evid,
		const sc_integer time_ms, const sc_boolean periodic) {


	/* go through all timers ... */
    unsigned int i;
    for(i = this->timer_count; i; i--) {

		/* ... and find an unused one. */
		if (this->timers[i-1].pt_evid == NULL) {

			/* set timer properties */
			this->timers[i-1].pt_evid = evid;
			this->timers[i-1].time_ms = time_ms;
			this->timers[i-1].periodic = periodic;
			this->timers[i-1].handle = handle;
			this->timers[i-1].service = this;

			// reset the elapsed time ...
			this->timers[i-1].elapsed_time_ms = 0;

			break;
		}
	}

}


/*! Cancels a timer for the specified time event. */
void sc_timer_cancel(sc_timer_service_t *this, const sc_eventid evid) {

	unsigned int i;
	 for(i = this->timer_count; i; i--) {
		if (this->timers[i-1].pt_evid == evid) {

			this->timers[i-1].pt_evid = NULL;
			this->timers[i-1].handle = NULL;

			break;
		}
	}
}


/*! Initializes a timer service with a set of timers. */
void sc_timer_service_init(sc_timer_service_t *tservice,
	sc_timer_t *timers,
	sc_integer count,
	sc_raise_time_event_fp raise_event) {

	tservice->timers = timers;
	tservice->timer_count = count;

	unsigned int i;
	for(i = tservice->timer_count; i; i--) {
		tservice->timers->pt_evid = NULL;
		tservice->timers->service = tservice;
	}

	tservice->raise_event = raise_event;
}


void sc_timer_service_proceed(sc_timer_service_t *this, const sc_integer time_ms) {

	/* go through all timers ... */
    unsigned int i;
    for(i = this->timer_count; i; i--) {

		/* ... and process all used. */
		if (this->timers[i-1].pt_evid != NULL) {

			if (this->timers[i-1].elapsed_time_ms < this->timers[i-1].time_ms) {
				this->timers[i-1].elapsed_time_ms += time_ms;

				if (this->timers[i-1].elapsed_time_ms >= this->timers[i-1].time_ms) {
					sc_timer_fired(&(this->timers[i-1]));
					if (this->timers[i-1].periodic) {
						this->timers[i-1].elapsed_time_ms -= this->timers[i-1].time_ms;
					}
				}
			}
		}
	}

}

sc_timer_service.h

C/C++
Handles the time events of the state machine
/*
 * sc_timer.h
 *
 *  Created on: 13.04.2016
 *      Author: korsisnki, terfloth
 */

#ifndef SC_TIMER_SERCICE_H_
#define SC_TIMER_SERCICE_H_

#include "sc_types.h"

#ifdef __cplusplus
extern "C" {
#endif

/*! file/ Interface definition of a POSIX thread based timer service for YAKINDU SCT stet machines. */

struct sc_timer_service;

/* internal arguments of a timer pthread */
typedef struct {
	sc_integer time_ms;
	sc_boolean periodic;
	sc_integer elapsed_time_ms;
	sc_eventid pt_evid;
	void* handle;
	struct sc_timer_service *service;
} sc_timer_t;


/*! Function pointer type for state machines runCycle function. */
typedef void (*sc_raise_time_event_fp)(void *handle, sc_eventid evid);


typedef struct sc_timer_service {
	sc_integer timer_count;
	sc_timer_t *timers;
	sc_raise_time_event_fp raise_event;
} sc_timer_service_t;


/*! Initializes a timer service with a set of timers. */
extern void sc_timer_service_init(sc_timer_service_t *tservice,
		sc_timer_t *timers,
		sc_integer count,
		sc_raise_time_event_fp raise_event);

extern void sc_timer_service_proceed(sc_timer_service_t *timer_service, const sc_integer time_ms);



/*! Starts a timer with the specified parameters. */
extern void sc_timer_start (
		sc_timer_service_t *timer_service,
		void* handle,
		const sc_eventid evid,
		const sc_integer time_ms,
		const sc_boolean periodic);


/*! Cancels a timer for the specified time event. */
extern void sc_timer_cancel(sc_timer_service_t *timer_service, const sc_eventid evid);


#ifdef __cplusplus
}
#endif


#endif /* SC_TIMER_SERCICE_H_ */

Credits

Robin Herrmann

Robin Herrmann

8 projects • 16 followers
Software Engineer - Doing a lot of stuff with state machines.
YAKINDU Statechart Tools

YAKINDU Statechart Tools

1 project • 1 follower
With YAKINDU Statechart Tools, you can easily create complex systems in a visual way.

Comments