![]() |
![]() |
![]() 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 ![]()
![]() |