wonx/UNIXTimer.c
Hiroaki Sakai c0b964b4f4 Added dummy function of _asm_*().
Set FP_OFF ​(), FP_SEG() for the callback function at interrupt setting in WonderWitch
Adjust appropriately according to the setting method.  (Fit to wwterm)

UNIXTimer.c: UNIXTimer_Unpause()
((unix_timer -> pause == 1) && (unix_timer -> interrupt_in_pause == 0))
Fixed a bug that was not unix_timer-> pause--; when it was.
(It was not unposted when interrupt was not applied during pause)

Serial receive interrupt, keyboard interrupt added.  (corresponding to wwterm, operation confirmed)
Added UNIXSerialPort class.

With this, at WonderWitch,
com_intvector.callback = (void (near *) ()) FP_OFF ​​(com_handler);
com_intvector.cs = _ asm_inline ("\tmov \tax, cs");
com_intvector.ds = _ asm_inline ("\tmov \tax, ds");
sys_interrupt_set_hook (SYS_INT_RECEIVEREADY,
& com_intvector, & com_last_intvector);
Interrupt setting like that shown in Fig.

For warning, add WonX_Warning ().
Move WonX_Error () to WonX.c.

comm_send_string (), text_put_string (), text_put_substring () When executed
Fix output message.

Implement cursor display function.  (Add WWCursor class) (Do not blink. Display only)
When displaying the cursor, text information inside WWDisplay_DrawLCDPanel ()
Since we need to be able to read it, we will discontinue the WonXText class and add the WWText class
I moved to a member of the WWDisplay class.

In palette_get_color (), transparent color is displayed when executing WWPalette_GetMappedColors ()
Since it was not considered to be returned as -1, palette_get_color ()
Fixed a bug where return value was wrong value.

Character color palette, LCD color palette initial value, with WonderWitch
It was made to coincide with the initial value.

As a sample, add wwterm - b 05.  (Add wwterm target to Makefile)

Version 1.1 - from wonx-1.1.tar.gz
2018-03-07 23:07:04 +00:00

316 lines
10 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*****************************************************************************/
/* ここから */
/*****************************************************************************/
#include <unistd.h>
#include <signal.h>
#include "UNIXTimerP.h"
#include "WonX.h"
/*****************************************************************************/
/* メンバ関数の定義 */
/*****************************************************************************/
/*---------------------------------------------------------------------------*/
/* コールバック関数 */
/*---------------------------------------------------------------------------*/
/* pointed_unix_timer の値はいつ変化するかわからないので,最適化を禁止する */
volatile static UNIXTimer pointed_unix_timer = NULL;
static void UNIXTimer_CallBackFunction(int argument)
{
int ret;
/*
* static なフラグを立てて,コールバック関数からコールバック関数が
* 呼ばれたのを検出するのが必要かも.
*/
if (pointed_unix_timer == NULL) return;
if (!pointed_unix_timer->timer_on) return;
if (pointed_unix_timer->pause) {
pointed_unix_timer->interrupt_in_pause++;
} else {
if (pointed_unix_timer->interrupt_in_pause == 0)
pointed_unix_timer->interrupt_in_pause = 1;
while (pointed_unix_timer->interrupt_in_pause > 0) {
pointed_unix_timer->interrupt_in_pause--;
if (pointed_unix_timer->callback != NULL) {
/*
* コールバック関数の中から UNIXTimer_Unpause() などが呼ばれて,
* そこからさらにコールバック関数が呼ばれたりしたときのために,
* ポーズする.
*/
pointed_unix_timer->pause++;
ret = (*pointed_unix_timer->callback)(pointed_unix_timer->parameter);
pointed_unix_timer->pause--;
/*
* コールバック関数の中で UNIXTimer_* 関連の関数が呼び出されると,
* ここで UNIXTimer オブジェクトの状態が変わってしまう可能性がある.
*/
/*
* 以下の処理は同じことを関数の先頭でやっているので,
* 最適化されて削除されないように注意すること.
*/
if (pointed_unix_timer == NULL) return;
if (!pointed_unix_timer->timer_on) return;
if (ret) {
pointed_unix_timer->interrupt_in_pause = 0;
UNIXTimer_OFF(pointed_unix_timer);
return;
}
/*
* コールバック関数中で,ポーズの状態が切り替わってしまった
* ときのため.
* 以下の処理は同じようなことをちょっと前にやっているので,
* 最適化されて削除されないように注意すること.
*/
if (pointed_unix_timer->pause) break;
}
}
}
if (pointed_unix_timer->auto_preset)
UNIXTimer_ON(pointed_unix_timer);
else
UNIXTimer_OFF(pointed_unix_timer);
return;
}
/*---------------------------------------------------------------------------*/
/* タイマの ON, OFF */
/*---------------------------------------------------------------------------*/
/*
* このあたりの処理は,処理中にタイマ割り込みが発生しないかどうかを
* 常に注意すること.でないと不可解なバグの原因になる.
*/
int UNIXTimer_ON(UNIXTimer unix_timer)
{
int t;
unix_timer->timer_on = 1;
pointed_unix_timer = unix_timer;
/*
* SIGALRM を使用するのでsleep() 中にアラームが起きた場合には,
* コールバック関数からの復帰後に sleep() の残り時間は継続されない.
*/
signal(SIGALRM, UNIXTimer_CallBackFunction);
#if 0 /* use ualarm() */
/* ualarm(); の引数に0を用いてはダメなので */
t = unix_timer->interval * 1000;
if (t < 1) t = 1;
ualarm(t, 0);
#else /* use alarm() */
/* alarm(); の引数に0を用いてはダメなので */
t = unix_timer->interval / 1000;
if (t < 1) t = 1;
alarm(t);
#endif
return (0);
}
int UNIXTimer_OFF(UNIXTimer unix_timer)
{
alarm(0); /* タイマを無効にする */
unix_timer->timer_on = 0;
pointed_unix_timer = NULL;
return (0);
}
int UNIXTimer_IsON(UNIXTimer unix_timer)
{ return (unix_timer->timer_on != 0); }
int UNIXTimer_IsOFF(UNIXTimer unix_timer)
{ return (unix_timer->timer_on == 0); }
/*---------------------------------------------------------------------------*/
/* 一時停止 */
/*---------------------------------------------------------------------------*/
/*
* 関数の先頭と末尾を Pause, Unpause でくくるばあいなどは,
* 関数から関数を呼び出したときに,2重 Pause, Unpause が起きるので
* 注意すること.(ただし,ポーズはネストできる)
*/
/*
* ポーズはネストされるのでUNIXTimer_Unpause() を安易に繰り返し呼んだり
* しないように注意すること.
*/
/*
* このあたりの処理は,処理中にタイマ割り込みが発生しないかどうかを
* 常に注意すること.でないと不可解なバグの原因になる.
*/
int UNIXTimer_Pause(UNIXTimer unix_timer)
{
unix_timer->pause++; /* ポーズはネストできる */
return (0);
}
int UNIXTimer_Unpause(UNIXTimer unix_timer)
{
if (unix_timer->pause == 0)
WonX_Error("UNIXTimer_Unpause", "Duplicated unpause.");
if (unix_timer->pause < 0)
WonX_Error("UNIXTimer_Unpause", "Invalid pause.");
if (unix_timer->pause == 1) {
if (unix_timer->interrupt_in_pause > 0) {
/*
* 万が一,ここでタイマ割り込みが発生しても,
* unix_timer->pause は 1 なので,コールバック関数は呼ばれないので,
* 問題無し.
* オートプリセットならば,べつに問題無し.
* オートプリセットでなければ timer_on フラグが落ちるので,問題無い.
*/
/*
* 処理中にタイマ割り込みが発生すると面倒なので,
* タイマをいったん無効にする.
*/
alarm(0);
/*
* 状態値を変更する直前・直後で割り込みが入ると面倒なので,
* 割り込みをOFFにしてからデクリメントする
*/
/* コールバック関数を呼ぶ前にpause フラグを無効にする */
unix_timer->pause--; /* ポーズはネストできる */
/* コールバック関数の呼び出し */
UNIXTimer_CallBackFunction(0);
} else {
if (unix_timer->interrupt_in_pause < 0)
WonX_Error("UNIXTimer_Unpause", "Invalid interrupt_in_pause.");
unix_timer->pause--; /* ポーズはネストできる */
}
} else {
unix_timer->pause--; /* ポーズはネストできる */
}
return (0);
}
int UNIXTimer_IsPause(UNIXTimer unix_timer)
{ return (unix_timer->pause != 0); }
/*---------------------------------------------------------------------------*/
/* オートプリセット */
/*---------------------------------------------------------------------------*/
int UNIXTimer_SetAutoPreset(UNIXTimer unix_timer)
{ return (unix_timer->auto_preset = 1); }
int UNIXTimer_ResetAutoPreset(UNIXTimer unix_timer)
{ return (unix_timer->auto_preset = 0); }
int UNIXTimer_IsAutoPreset(UNIXTimer unix_timer)
{ return (unix_timer->auto_preset != 0); }
/*---------------------------------------------------------------------------*/
/* インターバル */
/*---------------------------------------------------------------------------*/
int UNIXTimer_GetInterval(UNIXTimer unix_timer)
{ return (unix_timer->interval); }
int UNIXTimer_SetInterval(UNIXTimer unix_timer, int interval)
{ return (unix_timer->interval = interval); }
/*---------------------------------------------------------------------------*/
/* コールバック関数の呼び出し時のパラメータ */
/*---------------------------------------------------------------------------*/
void * UNIXTimer_GetParameter(UNIXTimer unix_timer)
{ return (unix_timer->parameter); }
void * UNIXTimer_SetParameter(UNIXTimer unix_timer, void * parameter)
{ return (unix_timer->parameter = parameter); }
/*---------------------------------------------------------------------------*/
/* コールバック関数の取得・登録 */
/*---------------------------------------------------------------------------*/
UNIXTimerCallBack UNIXTimer_GetCallBack(UNIXTimer unix_timer)
{ return (unix_timer->callback); }
UNIXTimerCallBack UNIXTimer_SetCallBack(UNIXTimer unix_timer,
UNIXTimerCallBack callback)
{ return (unix_timer->callback = callback); }
/*---------------------------------------------------------------------------*/
/* オブジェクトの作成 */
/*---------------------------------------------------------------------------*/
UNIXTimer UNIXTimer_Create(int auto_preset, int interval, void * parameter,
UNIXTimerCallBack callback)
{
UNIXTimer unix_timer;
unix_timer = (UNIXTimer)malloc(sizeof(_UNIXTimer));
if (unix_timer == NULL)
WonX_Error("UNIXTimer_Create", "Cannot allocate memory.");
unix_timer->timer_on = 0;
unix_timer->pause = 0;
unix_timer->interrupt_in_pause = 0;
unix_timer->auto_preset = 0;
unix_timer->interval = 0;
unix_timer->parameter = NULL;
unix_timer->callback = NULL;
if (auto_preset) UNIXTimer_SetAutoPreset(unix_timer);
else UNIXTimer_ResetAutoPreset(unix_timer);
UNIXTimer_SetInterval(unix_timer, interval);
UNIXTimer_SetParameter(unix_timer, parameter);
UNIXTimer_SetCallBack(unix_timer, callback);
return (unix_timer);
}
/*---------------------------------------------------------------------------*/
/* オブジェクトの削除 */
/*---------------------------------------------------------------------------*/
/*
* このあたりの処理は,処理中にタイマ割り込みが発生しないかどうかを
* 常に注意すること.でないと不可解なバグの原因になる.
*/
UNIXTimer UNIXTimer_Destroy(UNIXTimer unix_timer)
{
if (unix_timer == NULL)
WonX_Error("UNIXTimer_Destroy", "Object is not created.");
UNIXTimer_OFF(unix_timer);
free(unix_timer);
return (NULL);
}
/*****************************************************************************/
/* ここまで */
/*****************************************************************************/
/*****************************************************************************/
/* End of File. */
/*****************************************************************************/