tcdemo.c


/*

/*

* Thermal Control Demonstration - POSIX Threads Version

*

* Copyright (c) 1997, ESTEC

*

* Written by Marizio Martignano, ESTEC

* Changes for POSIX Threads Version by Chris Nettleton

*/

#include <pthread.h>

#include <stddef.h>

#include <assert.h>

#include <time.h>

#ifndef M_1750

#include <fcntl.h>

#include <sched.h>

#endif

#define TM_DELAY 1

#define T1_LC 10

#define T1_LW 15

#define T1_HW 25

#define T1_HC 30

#define T1_DELAY 4

#define T1_STEP 2

#define T2_LC 0

#define T2_LW 10

#define T2_HW 40

#define T2_HC 50

#define T2_DELAY 3

#define T2_STEP 3

#define T3_LC 6

#define T3_LW 10

#define T3_HW 16

#define T3_HC 30

#define T3_DELAY 2

#define T3_STEP 1

#define TMIN 0

#define TMAX 60

#define BLEN 256

static int istat;

void

delay (void)

{

time_t now;

time_t wakeup;

now = time(NULL);

wakeup = now;

#ifdef M_1750

while (1) {

now = time(NULL);

if (now != wakeup) {

break;

}

sched_yield();

}

#else

sleep (secs);

#endif

}

/*

* Global data, each object protected by a mutex

*/

static struct tc

{

pthread_mutex_t m;

int temp;

int automatic;

int on;

int lw;

int hw;

int step;

int period;

}

t1, t2, t3;

char timebuf [BLEN + 1];

pthread_mutex_t timebuf_m;

char inputline [BLEN + 1];

pthread_mutex_t inputline_m;

int p_tele = 1;

pthread_mutex_t p_tele_m;

void

tc_init (struct tc *t, int low, int high, int _step, int _period)

{

pthread_mutex_init (&t->m, NULL);

t->temp = 0;

t->automatic = 0;

t->on = 0;

t->lw = low;

t->hw = high;

t->step = _step;

t->period = _period;

}

// Set the standard input,

// when needed

int

set_input (void)

{

#ifndef M_1750

int stat;

stat = fcntl (0, F_GETFL);

fcntl (0, F_SETFL, O_NDELAY);

return stat;

#else

return 0;

#endif

}

// Reset the standard input,

// when needed

void

reset_input (int stat)

{

#ifndef M_1750

fcntl (0, F_SETFL, stat);

#endif

}

/*

* Get a character from the standard input,

* without suspending

*/

int

nodelay_getchar (void)

{

int res;

char ch;

#ifndef M_1750

res = read (0, &ch, 1);

if (res)

{

return (int) ch;

}

else

{

return 0;

}

#endif

#ifdef M_1750

asm volatile ("xio %0,0x8501":"=r" (res));

if (res & 0x02)

{

asm volatile ("xio %0,0x8500":"=r" (ch));

return ch & 0xff;

}

else

return 0;

#endif

}

/*

* Body of the telemetry thread

* Print telemetry every TM_DELAY seconds

*/

void *

telemetry_body (void *arg)

{

for (;;)

{

int i, temp, automatic, on;

for (i = 0; i < TM_DELAY; i++) {

delay();

}

pthread_mutex_lock (&t1.m);

temp = t1.temp;

automatic = t1.automatic;

on = t1.on;

pthread_mutex_unlock (&t1.m);

printf ("T1:%d:%d:%d\n", temp, automatic, on);

pthread_mutex_lock (&t2.m);

temp = t2.temp;

automatic = t2.automatic;

on = t2.on;

pthread_mutex_unlock (&t2.m);

printf ("T2:%d:%d:%d\n", temp, automatic, on);

pthread_mutex_lock (&t3.m);

temp = t3.temp;

automatic = t3.automatic;

on = t3.on;

pthread_mutex_unlock (&t3.m);

printf ("T3:%d:%d:%d\n", temp, automatic, on);

pthread_mutex_lock (&timebuf_m);

printf ("TIME:%s\n", timebuf);

pthread_mutex_unlock (&timebuf_m);

pthread_mutex_lock (&inputline_m);

printf ("INPUT:%s\n", inputline);

pthread_mutex_unlock (&inputline_m);

}

}

/*

* Body for Thermal_control Threads:

*/

void *

thermal_control_body (void *tc_ptr)

{

struct tc *t = (struct tc *) tc_ptr;

for (;;) {

int i;

for (i = 0; i < t->period; i++) {

delay();

}

/****

printf("l = %d, h = %d, a = %d, s = %d, o = %d, t = %d\n",

t->lw, t->hw, t->automatic, t->step, t->on, t->temp);

****/

if (t->automatic) {

if (t->temp < t->lw) {

if (t->on == 0) {

t->on = 1;

continue;

}

}

if (t->temp > t->hw) {

if (t->on == 1) {

t->on = 0;

continue;

}

}

}

if (t->on) {

t->temp += t->step;

if (t->temp > TMAX) {

t->temp = TMAX;

}

} else {

t->temp -= t->step;

if (t->temp < TMIN) {

t->temp = TMIN;

}

}

}

}

// Body for command interpreter thread

//

void *

reader_body (void *arg)

{

int pos = 0;

char ch;

for (;;)

{

// Get character

ch = nodelay_getchar ();

// Process character

if (ch)

{

// Exit program, if requested

if (ch == '~')

{

// Reset standard input

reset_input (istat);

// Gracefully exit

exit (0);

}

if ((ch != '\n') && (ch != '\r') && (pos < BLEN))

{

// Store character in input buffer

pthread_mutex_lock (&inputline_m);

inputline[pos++] = ch;

inputline[pos] = '\0';

pthread_mutex_unlock (&inputline_m);

}

else if ((ch == '\n') || (ch == '\r'))

{

pos = 0;

pthread_mutex_lock (&inputline_m);

/* act on command */

// If there's some input

if (strlen (inputline))

{

// Activate automatic control

if (strcmp (inputline, "T1_AUTO") == 0)

{

if (t1.automatic == 0)

{

t1.automatic = 1;

t1.on = 0;

}

}

if (strcmp (inputline, "T2_AUTO") == 0)

{

if (t2.automatic == 0)

{

t2.automatic = 1;

t2.on = 0;

}

}

if (strcmp (inputline, "T3_AUTO") == 0)

{

if (t3.automatic == 0)

{

t3.automatic = 1;

t3.on = 0;

}

}

// Activate manual control

if (strcmp (inputline, "T1_MAN") == 0)

{

if (t1.automatic == 1)

{

t1.automatic = 0;

t1.on = 0;

}

}

if (strcmp (inputline, "T2_MAN") == 0)

{

if (t2.automatic == 1)

{

t2.automatic = 0;

t2.on = 0;

}

}

if (strcmp (inputline, "T3_MAN") == 0)

{

if (t3.automatic == 1)

{

t3.automatic = 0;

t3.on = 0;

}

}

// Heater on

if (strcmp (inputline, "T1_ON") == 0)

{

if (t1.automatic == 0)

{

t1.on = 1;

}

}

if (strcmp (inputline, "T2_ON") == 0)

{

if (t2.automatic == 0)

{

t2.on = 1;

}

}

if (strcmp (inputline, "T3_ON") == 0)

{

if (t3.automatic == 0)

{

t3.on = 1;

}

}

// Heater off

if (strcmp (inputline, "T1_OFF") == 0)

{

if (t1.automatic == 0)

{

t1.on = 0;

}

}

if (strcmp (inputline, "T2_OFF") == 0)

{

if (t2.automatic == 0)

{

t2.on = 0;

}

}

if (strcmp (inputline, "T3_OFF") == 0)

{

if (t3.automatic == 0)

{

t3.on = 0;

}

}

}

pthread_mutex_unlock (&inputline_m);

}

}

sched_yield ();

}

}

/*

* Clock_task:

* Update the time buffer once a second

*/

void *

clock_task (void *arg)

{

static short hour = 0;

static short min = 0;

static short sec = 1;

time_t t, ot = 0;

for (;;)

{

t = time(NULL);

if (t != ot) {

ot = t;

} else {

sched_yield();

continue;

}

sprintf (timebuf, "%02d:%02d:%02d", hour, min, sec);

sec++;

if (sec > 59)

{

sec = 0;

min++;

if (min > 59)

{

min = 0;

hour++;

}

}

}

}

void

main ()

{

int ans;

pthread_t telemetry_thread;

pthread_t t1_control;

pthread_t t2_control;

pthread_t t3_control;

pthread_t reader_thread;

pthread_t clock_thread;

int status;

#ifdef M_1750

pthread_init ();

#endif

/* intitialize global data */

tc_init (&t1, T1_LW, T1_HW, T1_STEP, T1_DELAY);

tc_init (&t2, T2_LW, T2_HW, T2_STEP, T2_DELAY);

tc_init (&t3, T3_LW, T3_HW, T3_STEP, T3_DELAY);

pthread_mutex_init (&timebuf_m, NULL);

sprintf (timebuf, "00:00:00");

pthread_mutex_init (&inputline_m, NULL);

strcpy (inputline, "");

printf ("\nThermal Control Demo\n");

printf ("M. Martignano - ESA/ESTEC/WME\n");

printf ("Copyright (C) 1997 ESTEC - ESA\n\n");

printf ("Strike '~' to exit...\n");

istat = set_input ();

/* create the threads */

ans = pthread_create (&telemetry_thread, NULL, telemetry_body, NULL);

assert (ans >= 0);

ans = pthread_create (&t1_control, NULL, thermal_control_body, (void *) &t1);

assert (ans >= 0);

ans = pthread_create (&t2_control, NULL, thermal_control_body, (void *) &t2);

assert (ans >= 0);

ans = pthread_create (&t3_control, NULL, thermal_control_body, (void *) &t3);

assert (ans >= 0);

ans = pthread_create (&reader_thread, NULL, reader_body, NULL);

assert (ans >= 0);

ans = pthread_create (&clock_thread, NULL, clock_task, NULL);

assert (ans >= 0);

pthread_join (telemetry_thread, (void *) &status);

}


 
 
 
Last update: 2 August 2006