This is the instruction to share a printer which is served by a Linux running CUPS server to Windows clients.
Assume the class name of the printer (as defined in CUPS) is HP_LaserJet_1020, and the Linux server's IP address is 192.168.0.11.
Add a network printer and in URI box, add: http://%3cip-address/ of cups server>/classes/<classname>
or, in this example:
http://192.168.0.11/classes/HP_LaserJet_1020
Thursday, January 28, 2010
Thursday, December 17, 2009
LOGVECT.C
/* RESET AND INTERRUPT VECTORS
Modified-version of COSMIC-France's vector.c
(c) M. Lutfi Shahab
First creation : 8-Jan-1995
Modifications :
- Bugs found in Whitesmiths's vector.c (vector 9 contains Division
by Zero).
- RESET: Whitesmith always defined zk and sk by zero, but in this
file, user can modified it.
- exception handler now can only be a near address (appropiate use
for EVB under MCX16 kernel operation).
*/
#define _WSC_
#include "mcx16.h"
extern SYSTABLE SysTable;
extern @port void _stext(void); /* startup routine */
extern @port void SCITrmIsr(void); /* SCI transmit interrupt handler */
extern @port void SCIRcvIsr(void); /* SCI receive interrupt handler */
extern @port void _BerrIsr(void);
extern @port void DivZero(void);
extern @port void IllegalOpcode(void);
extern @port void _default(void);
static @port void _dummit(void);
const struct reset {
@far @port void (*rst)(void); /* reset + code extension */
unsigned int isp; /* initial stack pointer */
unsigned int dpp; /* direct page pointer */
@port void (*vector[58])(void); /* interrupt vectors */
} _reset = {
/*0000:*/ /* vector 0: (ixksk) = $0110
bank 0, stack at $1xxxx
start address :
[15:12] = reserved
[11:8] = initial ZK
[7:4] = initial SK
[3:0] = initial PK
*/
/*0002: */ _stext, /* vector 1, initial PC */
/*0004: */ 0x002E, /* vector 2, Stack Pointer, [15:0] = initial SP */
/*0006:*/ 0x0000, /* vector 3, direct page pointer,
initial IZ (Direct Page Pointer) */
/* BEGIN VECTORS */
/*000A:*/ _dummit, /* vector 5, Bus Error (BERR) */
/*0008:*/ _dummit, /* vector 4, Breakpoint (BKPT) */
/*000C:*/ (@port void *)0x02FA, /* vector 6, Software Interrupt (SWI) to call MCX16 services */
/*000E:*/ _default, /* vector 7, Illegal Instruction */
/*0010:*/ _default, /* vector 8, Divide by Zero */
/*0012:*/ _dummit, /* vector 9, Unassigned, Reserved */
/*0014:*/ _dummit, /* vector A, Unassigned, Reserved */
/*0016:*/ _dummit, /* vector B, Unassigned, , Reserved */
/*0018:*/ _dummit, /* vector C, Unassigned, Reserved */
/*001A:*/ _dummit, /* vector D, Unassigned, Reserved */
/*001C:*/ _dummit, /* vector E, Unassigned, Reserved */
/*001E:*/ _dummit, /* vector F, Uninitialized Interrupt */
/*0020:*/ _dummit, /* vector 10, Unassigned, Reserved */
/*0022:*/ _dummit, /* vector 11, Level 1 Interrupt Autovector */
/*0024:*/ _dummit, /* Vector 12, Level 2 Interrupt Autovector */
/*0026:*/ _dummit, /* Vector 13, Level 3 Interrupt Autovector */
/*0028:*/ _dummit, /* Vector 14, Level 4 Interrupt Autovector */
/*002A:*/ _dummit, /* Vector 15, Level 5 Interrupt Autovector */
/*002C:*/ _dummit, /* Vector 16, Level 6 Interrupt Autovector */
/*002E:*/ _dummit, /* Vector 17, Level 7 Interrupt Autovector */
/*0030:*/ _dummit, /* Vector 18, Spurious Interrupt */
/*0032:*/ _dummit, /* vector 19 user-defined interrupt */
/*0034:*/ _dummit, /* vector 1A user-defined interrupt */
/*0036:*/ _dummit, /* vector 1B user-defined interrupt */
/*0038:*/ _dummit, /* vector 1C user-defined interrupt */
/*003A:*/ _dummit, /* vector 1E user-defined interrupt */
/*003C:*/ _dummit, /* vector 1E user-defined interrupt */
/*003E:*/ _dummit, /* vector 1F user-defined interrupt */
/*0040:*/ _dummit, /* vector 20 user-defined interrupt */
/*0042:*/ _dummit, /* vector 21 user-defined interrupt */
/*0044:*/ _dummit, /* vector 22 user-defined interrupt */
/*0046:*/ _dummit, /* vector 23 user-defined interrupt */
/*0048:*/ _dummit, /* vector 24 user-defined interrupt */
/*004A:*/ _dummit, /* vector 25 user-defined interrupt */
/*004C:*/ _dummit, /* vector 26 user-defined interrupt */
/*004E:*/ _dummit, /* vector 27 user-defined interrupt */
/*0050:*/ _dummit, /* vector 28 user-defined interrupt */
/*0052:*/ _dummit, /* vector 29 user-defined interrupt */
/*0054:*/ _dummit, /* vector 2A user-defined interrupt */
/*0056:*/ _dummit, /* vector 2B user-defined interrupt */
/*0058:*/ _dummit, /* vector 2C user-defined interrupt */
/*005A:*/ _dummit, /* vector 2D user-defined interrupt */
/*005C:*/ _dummit, /* vector 2E user-defined interrupt */
/*005E:*/ _dummit, /* vector 2F user-defined interrupt */
/*0060:*/ _dummit, /* vector 30 user-defined interrupt */
/*0062:*/ _dummit, /* vector 31 user-defined interrupt */
/*0064:*/ _dummit, /* vector 32 user-defined interrupt */
/*0066:*/ _dummit, /* vector 33 user-defined interrupt */
/*0068:*/ _dummit, /* vector 34 user-defined interrupt */
/*006A:*/ _dummit, /* vector 35 user-defined interrupt */
/*006C:*/ _dummit, /* vector 36 user-defined interrupt */
/*006E:*/ _dummit, /* vector 37 user-defined interrupt */
/*0070:*/ (@port void *)&SysTable, /* vector 38 points to SysTable address */
/*0072:*/ (@port void *)0x81E, /* vector 39 as a null task */
/*0074:*/ SCIIsr, /* Vector 3A, Interrupt Service Routine SCI */
};
/* empty function to receive an undefined interrupt
*/
static @port void _dummit(void) /* just contains rti */
{
/* enter background debug mode */
_asm("BGND\n");
_asm("nop\n");
}
Modified-version of COSMIC-France's vector.c
(c) M. Lutfi Shahab
First creation : 8-Jan-1995
Modifications :
- Bugs found in Whitesmiths's vector.c (vector 9 contains Division
by Zero).
- RESET: Whitesmith always defined zk and sk by zero, but in this
file, user can modified it.
- exception handler now can only be a near address (appropiate use
for EVB under MCX16 kernel operation).
*/
#define _WSC_
#include "mcx16.h"
extern SYSTABLE SysTable;
extern @port void _stext(void); /* startup routine */
extern @port void SCITrmIsr(void); /* SCI transmit interrupt handler */
extern @port void SCIRcvIsr(void); /* SCI receive interrupt handler */
extern @port void _BerrIsr(void);
extern @port void DivZero(void);
extern @port void IllegalOpcode(void);
extern @port void _default(void);
static @port void _dummit(void);
const struct reset {
@far @port void (*rst)(void); /* reset + code extension */
unsigned int isp; /* initial stack pointer */
unsigned int dpp; /* direct page pointer */
@port void (*vector[58])(void); /* interrupt vectors */
} _reset = {
/*0000:*/ /* vector 0: (ixksk) = $0110
bank 0, stack at $1xxxx
start address :
[15:12] = reserved
[11:8] = initial ZK
[7:4] = initial SK
[3:0] = initial PK
*/
/*0002: */ _stext, /* vector 1, initial PC */
/*0004: */ 0x002E, /* vector 2, Stack Pointer, [15:0] = initial SP */
/*0006:*/ 0x0000, /* vector 3, direct page pointer,
initial IZ (Direct Page Pointer) */
/* BEGIN VECTORS */
/*000A:*/ _dummit, /* vector 5, Bus Error (BERR) */
/*0008:*/ _dummit, /* vector 4, Breakpoint (BKPT) */
/*000C:*/ (@port void *)0x02FA, /* vector 6, Software Interrupt (SWI) to call MCX16 services */
/*000E:*/ _default, /* vector 7, Illegal Instruction */
/*0010:*/ _default, /* vector 8, Divide by Zero */
/*0012:*/ _dummit, /* vector 9, Unassigned, Reserved */
/*0014:*/ _dummit, /* vector A, Unassigned, Reserved */
/*0016:*/ _dummit, /* vector B, Unassigned, , Reserved */
/*0018:*/ _dummit, /* vector C, Unassigned, Reserved */
/*001A:*/ _dummit, /* vector D, Unassigned, Reserved */
/*001C:*/ _dummit, /* vector E, Unassigned, Reserved */
/*001E:*/ _dummit, /* vector F, Uninitialized Interrupt */
/*0020:*/ _dummit, /* vector 10, Unassigned, Reserved */
/*0022:*/ _dummit, /* vector 11, Level 1 Interrupt Autovector */
/*0024:*/ _dummit, /* Vector 12, Level 2 Interrupt Autovector */
/*0026:*/ _dummit, /* Vector 13, Level 3 Interrupt Autovector */
/*0028:*/ _dummit, /* Vector 14, Level 4 Interrupt Autovector */
/*002A:*/ _dummit, /* Vector 15, Level 5 Interrupt Autovector */
/*002C:*/ _dummit, /* Vector 16, Level 6 Interrupt Autovector */
/*002E:*/ _dummit, /* Vector 17, Level 7 Interrupt Autovector */
/*0030:*/ _dummit, /* Vector 18, Spurious Interrupt */
/*0032:*/ _dummit, /* vector 19 user-defined interrupt */
/*0034:*/ _dummit, /* vector 1A user-defined interrupt */
/*0036:*/ _dummit, /* vector 1B user-defined interrupt */
/*0038:*/ _dummit, /* vector 1C user-defined interrupt */
/*003A:*/ _dummit, /* vector 1E user-defined interrupt */
/*003C:*/ _dummit, /* vector 1E user-defined interrupt */
/*003E:*/ _dummit, /* vector 1F user-defined interrupt */
/*0040:*/ _dummit, /* vector 20 user-defined interrupt */
/*0042:*/ _dummit, /* vector 21 user-defined interrupt */
/*0044:*/ _dummit, /* vector 22 user-defined interrupt */
/*0046:*/ _dummit, /* vector 23 user-defined interrupt */
/*0048:*/ _dummit, /* vector 24 user-defined interrupt */
/*004A:*/ _dummit, /* vector 25 user-defined interrupt */
/*004C:*/ _dummit, /* vector 26 user-defined interrupt */
/*004E:*/ _dummit, /* vector 27 user-defined interrupt */
/*0050:*/ _dummit, /* vector 28 user-defined interrupt */
/*0052:*/ _dummit, /* vector 29 user-defined interrupt */
/*0054:*/ _dummit, /* vector 2A user-defined interrupt */
/*0056:*/ _dummit, /* vector 2B user-defined interrupt */
/*0058:*/ _dummit, /* vector 2C user-defined interrupt */
/*005A:*/ _dummit, /* vector 2D user-defined interrupt */
/*005C:*/ _dummit, /* vector 2E user-defined interrupt */
/*005E:*/ _dummit, /* vector 2F user-defined interrupt */
/*0060:*/ _dummit, /* vector 30 user-defined interrupt */
/*0062:*/ _dummit, /* vector 31 user-defined interrupt */
/*0064:*/ _dummit, /* vector 32 user-defined interrupt */
/*0066:*/ _dummit, /* vector 33 user-defined interrupt */
/*0068:*/ _dummit, /* vector 34 user-defined interrupt */
/*006A:*/ _dummit, /* vector 35 user-defined interrupt */
/*006C:*/ _dummit, /* vector 36 user-defined interrupt */
/*006E:*/ _dummit, /* vector 37 user-defined interrupt */
/*0070:*/ (@port void *)&SysTable, /* vector 38 points to SysTable address */
/*0072:*/ (@port void *)0x81E, /* vector 39 as a null task */
/*0074:*/ SCIIsr, /* Vector 3A, Interrupt Service Routine SCI */
};
/* empty function to receive an undefined interrupt
*/
static @port void _dummit(void) /* just contains rti */
{
/* enter background debug mode */
_asm("BGND\n");
_asm("nop\n");
}
ADCTASK.C
/******************************************************************************
�����������������������������������������������������������������������������
� �
� ANALOG-TO-DIGITAL CONVERTING TASK �
� �
� Copyright (c) June, 1995 �
� by Lutfi Shahab �
� Instrumentation and Controls Laboratory �
� Dept. of Engineering Physics �
� Faculty of Industrial Technology �
� Institut Teknologi Bandung �
� �
� Date: 20/11/94 �
� �
� Platform : Motorola 68HC16 Microcontroller �
� Compiler : Whitesmith HC16 Compiler �
� Target : EPROM-targeted binary code �
� �
� Description: -Task and routines to access ADC-module of 68HC16 �
� �
� Functions: �
� �
� Summary: �
� The ADC module is mapped into 32 words of address space. Five words are �
� control/status registers, one word is digital port data, and 24 words �
� provide access to the results of ADC conversion (eight addresses for each �
� type of converted data). Two words are reserved for expansion. �
� The ADC module base address is determined by the value of the MODMAP bit �
� int the system integration module configuration register (SIMMCR). �
� The base address is normaly $FFF700 in the MC68HC16Z1. �
� Internally, the ADC has both a differential data bus and a buffered �
� IMB data bus. Registers not directly associated with AD conversion �
� functions, such as the MCR, the MTR, and the PDR, reside on the bufferd �
� bus, while conversion registers and result registers reside on the �
� differential bus. �
� �
� Registers that must be set prior operation: �
� ADMCR: �
� STOP = 0 (normal operation) �
� FRZ = 0 �
� SUPV = 1 (supervisory mode) �
� ADCTL0: �
� PRS = 1 (ADC clock = system clock/4 = 16.667 MHz/4) �
� STS = 0 (4 A/D clock periods in the sample time) �
� RES10 = 1 (10-bit conversion) �
� ADCTL1: �
� SCAN = 1 (continuous conversion) �
� MULT = 1 (sequential conversion of four or eight channels �
� selected by [CD:CA]) �
� S8CM = 1 (eight-conversion sequence) �
� CD = 0 (measured data at each channel stored into his register) �
� �
�����������������������������������������������������������������������������;
******************************************************************************/
#define _FAR_
#include <wslxa.h>
#include "_adc.h"
#include "mcx16.h"
#include "sysdef.h"
#define CLICK_T (16.256E-3) /* 1 clock tick = 16.256 mS */
#define TICK1 (1000/16) /* 1 second */
#define TICK2 (1000/16)
/*
It's difficult to find out how time constant of thermocouple is,
but for bare thermocouple, however, extensive reseach and testing
have provided semi-empirical formulas that allow calculation of the time
constant with fair accuracy. One such relation useful for temperatures
from 160 - 1600 F, wire diameter 0.016 - 0.051 in, mass velocity 3 - 50
lbm/(ft3.s), and static pressure of 1 atm is:
t = (3500*rho*c*d^1.25 * pow(G, -15.8* sqrt(T)))/T, where
rho = mass density of two thermocouple materials, lbm/ft3
c = average specific heat of two thermocouple materials, Btu/(lbm.F)
d = wire diameter (in)
G = flow mass velocity, lbm/(ft2.s)
T = stagnation temperature, R
(adapted from Doebelin, MEASUREMENT SYSTEMS,...)
*/
/*********
THIS JUST FOR CLARITY !
ADC has been initialized by STARTUP.S
*******/
/*****
void ADC_init(void)
{
admcr.reg = ADMCR_SUPV;
admcr.reg = 0x0010;
adctl0.reg = 0x0083;
adctl1.reg = 0x0077;
}
******/
WORD adcdata[N_ADC_CHANNELS];
void ADC_Task(void)
{
int i;
_mcx_timer(TICK1, TICK2, SAMP_SEMA); /* install timer */
FOREVER
{
/* wait until sample period begin */
_mcx_wait(SAMP_SEMA);
/* SCF is cleared when ADCTL1 is written and a conversion sequence begin */
adctl1.reg = 0x0077;
do {
} while (adstat.w.ccf==0); /* all channels completely converted ? */
/*******
if last channel scanned
send data to mailbox if polling has reached last channel.
signalling other task with ADC_SEMA
rescan ADC channels, starting from first channel
*******/
for(i=ADC_1; i<=N_ADC_CHANNELS; i++)
adcdata[i] = ur_adc_rslt[i];
_mcx_send_mbx(ADC_MBX, &adcdata, ADC_SEMA);
}
}
�����������������������������������������������������������������������������
� �
� ANALOG-TO-DIGITAL CONVERTING TASK �
� �
� Copyright (c) June, 1995 �
� by Lutfi Shahab �
� Instrumentation and Controls Laboratory �
� Dept. of Engineering Physics �
� Faculty of Industrial Technology �
� Institut Teknologi Bandung �
� �
� Date: 20/11/94 �
� �
� Platform : Motorola 68HC16 Microcontroller �
� Compiler : Whitesmith HC16 Compiler �
� Target : EPROM-targeted binary code �
� �
� Description: -Task and routines to access ADC-module of 68HC16 �
� �
� Functions: �
� �
� Summary: �
� The ADC module is mapped into 32 words of address space. Five words are �
� control/status registers, one word is digital port data, and 24 words �
� provide access to the results of ADC conversion (eight addresses for each �
� type of converted data). Two words are reserved for expansion. �
� The ADC module base address is determined by the value of the MODMAP bit �
� int the system integration module configuration register (SIMMCR). �
� The base address is normaly $FFF700 in the MC68HC16Z1. �
� Internally, the ADC has both a differential data bus and a buffered �
� IMB data bus. Registers not directly associated with AD conversion �
� functions, such as the MCR, the MTR, and the PDR, reside on the bufferd �
� bus, while conversion registers and result registers reside on the �
� differential bus. �
� �
� Registers that must be set prior operation: �
� ADMCR: �
� STOP = 0 (normal operation) �
� FRZ = 0 �
� SUPV = 1 (supervisory mode) �
� ADCTL0: �
� PRS = 1 (ADC clock = system clock/4 = 16.667 MHz/4) �
� STS = 0 (4 A/D clock periods in the sample time) �
� RES10 = 1 (10-bit conversion) �
� ADCTL1: �
� SCAN = 1 (continuous conversion) �
� MULT = 1 (sequential conversion of four or eight channels �
� selected by [CD:CA]) �
� S8CM = 1 (eight-conversion sequence) �
� CD = 0 (measured data at each channel stored into his register) �
� �
�����������������������������������������������������������������������������;
******************************************************************************/
#define _FAR_
#include <wslxa.h>
#include "_adc.h"
#include "mcx16.h"
#include "sysdef.h"
#define CLICK_T (16.256E-3) /* 1 clock tick = 16.256 mS */
#define TICK1 (1000/16) /* 1 second */
#define TICK2 (1000/16)
/*
It's difficult to find out how time constant of thermocouple is,
but for bare thermocouple, however, extensive reseach and testing
have provided semi-empirical formulas that allow calculation of the time
constant with fair accuracy. One such relation useful for temperatures
from 160 - 1600 F, wire diameter 0.016 - 0.051 in, mass velocity 3 - 50
lbm/(ft3.s), and static pressure of 1 atm is:
t = (3500*rho*c*d^1.25 * pow(G, -15.8* sqrt(T)))/T, where
rho = mass density of two thermocouple materials, lbm/ft3
c = average specific heat of two thermocouple materials, Btu/(lbm.F)
d = wire diameter (in)
G = flow mass velocity, lbm/(ft2.s)
T = stagnation temperature, R
(adapted from Doebelin, MEASUREMENT SYSTEMS,...)
*/
/*********
THIS JUST FOR CLARITY !
ADC has been initialized by STARTUP.S
*******/
/*****
void ADC_init(void)
{
admcr.reg = ADMCR_SUPV;
admcr.reg = 0x0010;
adctl0.reg = 0x0083;
adctl1.reg = 0x0077;
}
******/
WORD adcdata[N_ADC_CHANNELS];
void ADC_Task(void)
{
int i;
_mcx_timer(TICK1, TICK2, SAMP_SEMA); /* install timer */
FOREVER
{
/* wait until sample period begin */
_mcx_wait(SAMP_SEMA);
/* SCF is cleared when ADCTL1 is written and a conversion sequence begin */
adctl1.reg = 0x0077;
do {
} while (adstat.w.ccf==0); /* all channels completely converted ? */
/*******
if last channel scanned
send data to mailbox if polling has reached last channel.
signalling other task with ADC_SEMA
rescan ADC channels, starting from first channel
*******/
for(i=ADC_1; i<=N_ADC_CHANNELS; i++)
adcdata[i] = ur_adc_rslt[i];
_mcx_send_mbx(ADC_MBX, &adcdata, ADC_SEMA);
}
}
COMTASK.C
/*****************************************************************************
COMMUNICATION TASK FOR 68HC16-BASED TERMO-LOGGER
WITH
SLIP PROTOCOL AS DATA-LINK LAYER
(c) June 1995
by M. Lutfi
Engineering Physics Dept
Faculty of Industrial Technology
Institut Teknologi Bandung
=======================================================
Each received character is copied into a queue by the interrupt
routine and each character will be send by SCI_trm_task
periodically then gives a semaphore to other tasks via SCI_SEMA.
Before data copied to other segment/buffer, data must be
depacketized. ComTask always calls Depacketizer routine when
he receives data. MCX16 manages timing each period.
We don't need interrupt handler, because we don't use it.
To transmitting a character, just put it into SCI_TRM_QUEUE
If needed, QSPI routines can be added as request.
(c) M. Lutfi, 1995
Last updated: 5-June-1995 at MKN, Suropati 231
******************************************************************************/
#define _WSC_
#include "mcx16.h"
#include "sysdef.h"
#define SCI_IV 0x3A /* interrupt vector number */
#define IL_QSPI 1 /* QSPI has lowest priority */
#define IL_SCI 7 /* SCI has highest priority */
#define SIZE 512 /* buffer size */
#define TDRE 0x100 /* transmit ready bit */
#define SYS_CLOCK 16780000L /* HC16EVB's system clock */
#define BAUD_RATE(bps) (SYS_CLOCK/(bps*32))
/*
SLIP special character codes
*/
#define FR_END 0xC0 /* indicates end of packet */
#define FR_ESC 0xDB /* indicates byte stuffing */
#define T_FR_END 0xDC /* FR_ESC T_FR_END means END data byte */
#define T_FR_ESC 0xDD /* FR_ESC T_FR_ESC means ESC data byte */
#ifdef _WSC_ /* if WSC compiler */
#include <wslxa.h>
#include "_qsm.h"
#include "sysdef.h"
#else /* this not for WSC compiler */
#include <dos.h>
#include <stdio.h>
#define FOREVER for(;;)
int scsr;
int scdr;
int qmcr;
int qilr;
int qilr_ilqspi;
int qilr_ilsci;
int qivr;
int sccr0;
int sccr1, sccr1_pe, sccr1_m, sccr1_te, sccr1_re;
#endif
/* below are values for SCBR baud rates */
#define BPS_110 1748
#define BPS_600 874
#define BPS_1200 437
#define BPS_2400 218
#define BPS_4800 109
#define BPS_9600 55
#define BPS_19200 27
#define BPS_32768 16
#define BPS_38400 14
#define BPS_500000 1
/**************************** GLOBAL VARIABLES *******************************
char in_char;
char out_char;
******************************************************************************/
/******************************************************************************
SEND_PACKET:
sends a packet of length "len", starting at location "p"
******************************************************************************/
void send_packet(void *data, int len)
{
/* send an initial END character to flush out any data (garbage) that
* have accumulated in the receiver due to line noise
*/
char *p;
p = (char *)data;
send_char(FR_END);
/* for each byte in the packet, send the appropriate character
* sequence
*/
while (len--) {
if (*p==FR_END) {
send_char(FR_ESC);
send_char(T_FR_END);
}
else
if (*p==FR_ESC) {
send_char(FR_ESC);
send_char(T_FR_ESC);
}
else /* otherwise, we just send the character */
send_char(*p);
p++;
}
/* tell the receiver that we're done sending the packet */
send_char(FR_END);
}
/***************************** RECV_PACKET ***********************************
receive a packet into the queue located at "p".
* If more than len bytes are received, the packet will be
* truncated.
* Returns the number of bytes stored in the buffer.
*****************************************************************************/
int recv_packet(void *p, int len)
{
char c;
int received = 0;
/* sit in a loop reading bytes until we put together a whole packet.
* Make sure not to copy them into the packet if we run out of room.
*/
while (1) {
/* get a character to process */
c = get_char();
/* handle bytestuffing if necessary */
if (c==FR_END) {
/* a minor optimization: if there is no data in the packet,
* ignore it. This is meant to avoid bothering IP with all
* the empty packets generated by the duplicate FR_END char-
* racters which are in turn sent to try to detect line noise.
*/
if (received)
return (received);
}
else
if (c==FR_ESC) {
c = get_char();
/* if "c" is not and FR_ESC character, wait and get another
* character and then figure out what to store in the packet
* based on that.
*/
if (c==T_FR_END)
c = FR_END;
else
if (c==T_FR_ESC)
c = FR_ESC;
goto STORE;
}
else {
STORE:
/* here we fall into the default handler and let it store
* the charater for us
*/
if (received < len)
p[received++] = c;
}
}
_mcx_signal(SCI_RCV_SEMA);
}
/****************************************************************************
SCI driver Initialization
> Sets up the ACIA and starts an infinite loop of receive transmit
> QSM configuration summary:
* After reset, the QSM remains in an idle state, requiring initialization
of several registers before any serial operations may begin execution.
* The type of serial frame (8 or 9 bit) and the use of partiy must be
determined by M. PE and PT.
* For receive operation, WAKE, RWU, ILT, ILIE must be considered.
The receiver must be enabled (RE) and, usually, RIE should be set.
* For transmit operation, the transmitter must be enabled (TE) and,
usually, TIE should be set. The use of wired-OR mode (WOMS) must also
be decided. Once the transmitter is configured, data is not sent
until TDRE and TC are cleared. To clear TDRE and TC, the SCSR read
must be followed by a write to SCDR (either the lower byte or the
entire word).
* QIVR should be programmed to one of the user-defined vectors ($40-$FF)
during initialization of the QSM.
After reset, QIVR determines which two vectors in the exception vector
table are to be used for QSM interrupts. The QSPI and SCI submodules
have separate interrupt vectors adjacent to each other.
Both submodules use the same interrupt vector which LSB:
1: interrupt generated by QSPI
0: interrupt generated by QSCI
> Detail Configurations in QSM:
* QMCR:
STOP = 0 (Normal QSM clock operation)
FRZ1 = 0 (Ignore the FREEZE signal on the IMB)
SUPV = 1 (supervisor access)
IARB = $A (priority = 10; $F = highest priority, used by timer)
* QILR:
ILQSPI = 1 (lowest priority)
ILSCI = 7 (highest priority)
QIVR = set to SCI interrupt handler's address
****************************************************************************/
COMMUNICATION TASK FOR 68HC16-BASED TERMO-LOGGER
WITH
SLIP PROTOCOL AS DATA-LINK LAYER
(c) June 1995
by M. Lutfi
Engineering Physics Dept
Faculty of Industrial Technology
Institut Teknologi Bandung
=======================================================
Each received character is copied into a queue by the interrupt
routine and each character will be send by SCI_trm_task
periodically then gives a semaphore to other tasks via SCI_SEMA.
Before data copied to other segment/buffer, data must be
depacketized. ComTask always calls Depacketizer routine when
he receives data. MCX16 manages timing each period.
We don't need interrupt handler, because we don't use it.
To transmitting a character, just put it into SCI_TRM_QUEUE
If needed, QSPI routines can be added as request.
(c) M. Lutfi, 1995
Last updated: 5-June-1995 at MKN, Suropati 231
******************************************************************************/
#define _WSC_
#include "mcx16.h"
#include "sysdef.h"
#define SCI_IV 0x3A /* interrupt vector number */
#define IL_QSPI 1 /* QSPI has lowest priority */
#define IL_SCI 7 /* SCI has highest priority */
#define SIZE 512 /* buffer size */
#define TDRE 0x100 /* transmit ready bit */
#define SYS_CLOCK 16780000L /* HC16EVB's system clock */
#define BAUD_RATE(bps) (SYS_CLOCK/(bps*32))
/*
SLIP special character codes
*/
#define FR_END 0xC0 /* indicates end of packet */
#define FR_ESC 0xDB /* indicates byte stuffing */
#define T_FR_END 0xDC /* FR_ESC T_FR_END means END data byte */
#define T_FR_ESC 0xDD /* FR_ESC T_FR_ESC means ESC data byte */
#ifdef _WSC_ /* if WSC compiler */
#include <wslxa.h>
#include "_qsm.h"
#include "sysdef.h"
#else /* this not for WSC compiler */
#include <dos.h>
#include <stdio.h>
#define FOREVER for(;;)
int scsr;
int scdr;
int qmcr;
int qilr;
int qilr_ilqspi;
int qilr_ilsci;
int qivr;
int sccr0;
int sccr1, sccr1_pe, sccr1_m, sccr1_te, sccr1_re;
#endif
/* below are values for SCBR baud rates */
#define BPS_110 1748
#define BPS_600 874
#define BPS_1200 437
#define BPS_2400 218
#define BPS_4800 109
#define BPS_9600 55
#define BPS_19200 27
#define BPS_32768 16
#define BPS_38400 14
#define BPS_500000 1
/**************************** GLOBAL VARIABLES *******************************
char in_char;
char out_char;
******************************************************************************/
/******************************************************************************
SEND_PACKET:
sends a packet of length "len", starting at location "p"
******************************************************************************/
void send_packet(void *data, int len)
{
/* send an initial END character to flush out any data (garbage) that
* have accumulated in the receiver due to line noise
*/
char *p;
p = (char *)data;
send_char(FR_END);
/* for each byte in the packet, send the appropriate character
* sequence
*/
while (len--) {
if (*p==FR_END) {
send_char(FR_ESC);
send_char(T_FR_END);
}
else
if (*p==FR_ESC) {
send_char(FR_ESC);
send_char(T_FR_ESC);
}
else /* otherwise, we just send the character */
send_char(*p);
p++;
}
/* tell the receiver that we're done sending the packet */
send_char(FR_END);
}
/***************************** RECV_PACKET ***********************************
receive a packet into the queue located at "p".
* If more than len bytes are received, the packet will be
* truncated.
* Returns the number of bytes stored in the buffer.
*****************************************************************************/
int recv_packet(void *p, int len)
{
char c;
int received = 0;
/* sit in a loop reading bytes until we put together a whole packet.
* Make sure not to copy them into the packet if we run out of room.
*/
while (1) {
/* get a character to process */
c = get_char();
/* handle bytestuffing if necessary */
if (c==FR_END) {
/* a minor optimization: if there is no data in the packet,
* ignore it. This is meant to avoid bothering IP with all
* the empty packets generated by the duplicate FR_END char-
* racters which are in turn sent to try to detect line noise.
*/
if (received)
return (received);
}
else
if (c==FR_ESC) {
c = get_char();
/* if "c" is not and FR_ESC character, wait and get another
* character and then figure out what to store in the packet
* based on that.
*/
if (c==T_FR_END)
c = FR_END;
else
if (c==T_FR_ESC)
c = FR_ESC;
goto STORE;
}
else {
STORE:
/* here we fall into the default handler and let it store
* the charater for us
*/
if (received < len)
p[received++] = c;
}
}
_mcx_signal(SCI_RCV_SEMA);
}
/****************************************************************************
SCI driver Initialization
> Sets up the ACIA and starts an infinite loop of receive transmit
> QSM configuration summary:
* After reset, the QSM remains in an idle state, requiring initialization
of several registers before any serial operations may begin execution.
* The type of serial frame (8 or 9 bit) and the use of partiy must be
determined by M. PE and PT.
* For receive operation, WAKE, RWU, ILT, ILIE must be considered.
The receiver must be enabled (RE) and, usually, RIE should be set.
* For transmit operation, the transmitter must be enabled (TE) and,
usually, TIE should be set. The use of wired-OR mode (WOMS) must also
be decided. Once the transmitter is configured, data is not sent
until TDRE and TC are cleared. To clear TDRE and TC, the SCSR read
must be followed by a write to SCDR (either the lower byte or the
entire word).
* QIVR should be programmed to one of the user-defined vectors ($40-$FF)
during initialization of the QSM.
After reset, QIVR determines which two vectors in the exception vector
table are to be used for QSM interrupts. The QSPI and SCI submodules
have separate interrupt vectors adjacent to each other.
Both submodules use the same interrupt vector which LSB:
1: interrupt generated by QSPI
0: interrupt generated by QSCI
> Detail Configurations in QSM:
* QMCR:
STOP = 0 (Normal QSM clock operation)
FRZ1 = 0 (Ignore the FREEZE signal on the IMB)
SUPV = 1 (supervisor access)
IARB = $A (priority = 10; $F = highest priority, used by timer)
* QILR:
ILQSPI = 1 (lowest priority)
ILSCI = 7 (highest priority)
QIVR = set to SCI interrupt handler's address
****************************************************************************/
TCTASK.C
/*
���������������������������������������������������������������������������
� �
� THERMOCOUPLE TASK �
� �
� Copyright (c) 1994 �
� by Lutfi Shahab �
� Instrumentation and Controls Laboratory �
� Dept. of Engineering Physics �
� Institut Teknologi Bandung �
� �
� Date: 20/11/94 �
� �
� Platform : Motorola 68HC16 Microcontroller �
� running mcx16 multitasking kernel �
� Compiler : Whitesmith HC16 Compiler �
� Target : EPROM-targeted binary code �
� �
� Description: �
� This module contains routines for Thermocouple Linearization using �
� polynomial curvefitting. Only thermocouple type K can be calculated. �
� Temperature adjusted to Celcius. �
� �
���������������������������������������������������������������������������;
*/
#define _WSC_
#define _FAR_
#ifdef _WSC_
#include <wslxa.h>
#else
enum {ADC_1, ADC_2, ADC_3, ADC_4, ADC_5,ADC_6, ADC_7, ADC_8, N_ADC_CHANNELS};
#endif
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <stdio.h>
#ifdef _WSC_
#include "mcxapi.h"
#include "sysdef.h"
#endif
#define VREF_PLUS +2500.0 /* mV */
#define VREF_MIN -2500.0 /* mV */
#define RESOLUTION 10 /* bits */
#define KELVIN_TO_C 273.20 /* based on IPTS-68 */
#define LM335_VT 10.00 /* mV per Kelvin degree */
#define TC_GAIN_AMP (10000/40) /* gain of TC op-amp; uV/uV */
#define DIGIT_TO_MILLIVOLT(d) (((d)*scale)+VREF_MIN) /* mV */
/* seebeck coefficients for all TC types */
#define SEEBECK_COEF_K 40.01 /* uV/K */
#define SEEBECK_COEF_TC 5.20
#define SEEBECK_COEF_BN 18.05
#define SEEBECK_COEF_E 59.80
#define SEEBECK_COEF_JT 51.08
#define SEEBECK_COEF_JP 17.94
#define SEEBECK_COEF_JN 33.10
#define SEEBECK_COEF_K 40.01
#define SEEBECK_COEF_KP 26.47
#define SEEBECK_COEF_KN 13.54
#define SEEBECK_COEF_R 5.62
#define SEEBECK_COEF_S 5.70
#define SEEBECK_COEF_T 39.67
#define SEEBECK_COEF_TP 6.33
#define SEEBECK_COEF_TN 33.32
#define SEEBECK_COEF SEEBECK_COEF_K
/* number of linearization polynomial equations as T(V) */
#define NUMEQN_V 5
/* number of linearization polynomial equations as V(T) */
#define NUMEQN_T 2
#define ORDE_T 10
#define ORDE_V 4
#define TC_VOLT_MIN tc_table.v_range[0].min
#define TC_VOLT_MAX tc_table.v_range[NUMEQN_V-1].max
typedef struct {
double min, max;
}RANGE;
typedef struct {
RANGE t_range[NUMEQN_T]; /* temperature range */
RANGE v_range[NUMEQN_V]; /* voltage range */
double coef_t[NUMEQN_T][ORDE_T+1]; /* polynomial coefficients for every equation of V(T) */
double coef_v[NUMEQN_V][ORDE_V+1]; /* polynomial coefficients for every equation of T(V) */
} TCRECTYPE;
TCRECTYPE tc_table = {
/* Temperature ranges (in C) for each polynomial equation of type K */
{
{-270.00, 0.00},
{ 0.00, 1372.00},
},
/* Voltage ranges in microvolts */
{
{-6.457816e+03, -6.441148e+03},
{-6.441148e+03, -5.891361e+03},
{-5.891361e+03, 1.853306e+01},
{ 1.853306e+01, 8.136555e+03},
{ 8.136555e+03, 5.487490e+04}
},
{
/* Coefficients for each polynomial equation V(T) */
{
0.0000000000E+00, 3.9475433139E+01, 2.7465251138E-02,
-1.6565406716E-04,-1.5190912392E-06,-2.4581670924E-08,
-2.4757917816E-10,-1.5585276173E-12,-5.9729921255E-0015,
-1.2688801216E-17,-1.1382797374E-20
},
{
-1.8533063273E+01, 3.8918344612E+01, 1.6645154356E-02,
-7.8702374448E-05, 2.2835785557E-07,-3.5700231258E-10,
2.9932909136E-13,-1.2849848798E-16, 2.2239974336E-20,
0.00, 0.00
}
},
/* Coefficients for each polynomial equation T(V) in C */
{
{-8.887677e+05,-2.054743e+02, 1.307316e-02, 5.611858e-06, 3.034392e-10},
{-1.215521e+06,-7.993152e+02,-1.971155e-01,-2.160351e-05,-8.879453e-10},
{0.0000000e+00, 2.382475e-02,-2.372981e-06,-6.567714e-10,-9.208444e-14},
{0.0000000e+00, 2.548081e-02,-5.270562e-07, 7.989244e-11,-3.520933e-15},
{-1.035821e+01, 2.712314e-02,-1.781781e-07, 3.243000e-12,-1.166816e-17}
}
};
double scale; /* transformation scale */
/* calculate seebeck voltage value for a given temperature and TC */
/*
double calc_seebeck(double tempin)
{
return (SEEBECK_COEF * tempin);
}
*/
/* calculate TC temperature given volts using polynomial equations */
double volt2temp_poly(double voltin) /* input voltage */
{
int pi; /* index to appropriate polynom */
int i;
double yout;
if (voltin < TC_VOLT_MIN) /* check to see if voltage in valid range */
{
voltin = TC_VOLT_MIN;
}
else if (voltin > TC_VOLT_MAX)
{
voltin = TC_VOLT_MAX;
}
pi = 0;
/* search through breakpoint list looking for proper interval */
while ( (pi < NUMEQN_V) &&
!((voltin >= tc_table.v_range[pi].min) &&
(voltin <= tc_table.v_range[pi].max)))
{
pi++;
}
/* calculate TC temperature as a function of volts */
yout = tc_table.coef_v[pi][ORDE_V];
for (i=ORDE_V-1; i<=0; i--)
{
/* efficient, nested polynomial calculation */
yout = yout*voltin+tc_table.coef_v[pi][i];
}
return (yout);
}
/******************************************************************************
CONVERTS TC VOLTS TO TEMPERATURE
--------------------------------
Reference temperature sensored by IC LM335Z, which has output
characteristic: 10 mV/K. Scale has been stated 5/1023 = 4.9 mV/LSB,
so if we have vi (in integer), it must be multiplied by scale to convert
to voltage temperature, and divided it by resolution of sensor to get
real temperature. ref_scale = scale/LM335_VT = (4.9 mV/LSB)/(10 mV/K) =
0.49 K/LSB. Increasing vi in its LSB will increase temperature by 0.49 K.
When calibrate (T=25 C), LM335 generate 2.982 volts (273.2+25) according
to his current temperature. In Differential op-amp, this temperature-based
voltage used to compute temperature reference. We don't need to compute it
in MCU.
All of 'kerumitan' has been handled by op-amps.
*******************************************************************************/
void tc_converter(unsigned int *vi, /* measured TC volts */
double *temp) /* linearized temperature */
/* return: error code, 0 = no error */
{
int i;
double v;
for (i=ADC_1; i<=ADC_8; i++)
{
v = DIGIT_TO_MILLIVOLT(vi[i])/TC_GAIN_AMP*1000; /* unit in microvolts !*/
temp[i] = volt2temp_poly(&v);
}
}
double lin_t[N_ADC_CHANNELS]; /* linearized temperature */
void TC_Task(void)
{
unsigned int *mbx;
/* ADC resolution */
scale = (double)(VREF_PLUS-VREF_MIN)/(double)((1<<RESOLUTION)-1); /* mV/bit */
#ifdef _WSC_
FOREVER
{
mbx = _mcx_receive_w(CNV_SEMA);
tc_converter((mbx, (double *)lin_t);
_mcx_send_mbx_w(TC_MBX, lin_t, CNV_FINISH_SEMA);
_mcx_msg_done(mbx);
}
#endif
}
���������������������������������������������������������������������������
� �
� THERMOCOUPLE TASK �
� �
� Copyright (c) 1994 �
� by Lutfi Shahab �
� Instrumentation and Controls Laboratory �
� Dept. of Engineering Physics �
� Institut Teknologi Bandung �
� �
� Date: 20/11/94 �
� �
� Platform : Motorola 68HC16 Microcontroller �
� running mcx16 multitasking kernel �
� Compiler : Whitesmith HC16 Compiler �
� Target : EPROM-targeted binary code �
� �
� Description: �
� This module contains routines for Thermocouple Linearization using �
� polynomial curvefitting. Only thermocouple type K can be calculated. �
� Temperature adjusted to Celcius. �
� �
���������������������������������������������������������������������������;
*/
#define _WSC_
#define _FAR_
#ifdef _WSC_
#include <wslxa.h>
#else
enum {ADC_1, ADC_2, ADC_3, ADC_4, ADC_5,ADC_6, ADC_7, ADC_8, N_ADC_CHANNELS};
#endif
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <stdio.h>
#ifdef _WSC_
#include "mcxapi.h"
#include "sysdef.h"
#endif
#define VREF_PLUS +2500.0 /* mV */
#define VREF_MIN -2500.0 /* mV */
#define RESOLUTION 10 /* bits */
#define KELVIN_TO_C 273.20 /* based on IPTS-68 */
#define LM335_VT 10.00 /* mV per Kelvin degree */
#define TC_GAIN_AMP (10000/40) /* gain of TC op-amp; uV/uV */
#define DIGIT_TO_MILLIVOLT(d) (((d)*scale)+VREF_MIN) /* mV */
/* seebeck coefficients for all TC types */
#define SEEBECK_COEF_K 40.01 /* uV/K */
#define SEEBECK_COEF_TC 5.20
#define SEEBECK_COEF_BN 18.05
#define SEEBECK_COEF_E 59.80
#define SEEBECK_COEF_JT 51.08
#define SEEBECK_COEF_JP 17.94
#define SEEBECK_COEF_JN 33.10
#define SEEBECK_COEF_K 40.01
#define SEEBECK_COEF_KP 26.47
#define SEEBECK_COEF_KN 13.54
#define SEEBECK_COEF_R 5.62
#define SEEBECK_COEF_S 5.70
#define SEEBECK_COEF_T 39.67
#define SEEBECK_COEF_TP 6.33
#define SEEBECK_COEF_TN 33.32
#define SEEBECK_COEF SEEBECK_COEF_K
/* number of linearization polynomial equations as T(V) */
#define NUMEQN_V 5
/* number of linearization polynomial equations as V(T) */
#define NUMEQN_T 2
#define ORDE_T 10
#define ORDE_V 4
#define TC_VOLT_MIN tc_table.v_range[0].min
#define TC_VOLT_MAX tc_table.v_range[NUMEQN_V-1].max
typedef struct {
double min, max;
}RANGE;
typedef struct {
RANGE t_range[NUMEQN_T]; /* temperature range */
RANGE v_range[NUMEQN_V]; /* voltage range */
double coef_t[NUMEQN_T][ORDE_T+1]; /* polynomial coefficients for every equation of V(T) */
double coef_v[NUMEQN_V][ORDE_V+1]; /* polynomial coefficients for every equation of T(V) */
} TCRECTYPE;
TCRECTYPE tc_table = {
/* Temperature ranges (in C) for each polynomial equation of type K */
{
{-270.00, 0.00},
{ 0.00, 1372.00},
},
/* Voltage ranges in microvolts */
{
{-6.457816e+03, -6.441148e+03},
{-6.441148e+03, -5.891361e+03},
{-5.891361e+03, 1.853306e+01},
{ 1.853306e+01, 8.136555e+03},
{ 8.136555e+03, 5.487490e+04}
},
{
/* Coefficients for each polynomial equation V(T) */
{
0.0000000000E+00, 3.9475433139E+01, 2.7465251138E-02,
-1.6565406716E-04,-1.5190912392E-06,-2.4581670924E-08,
-2.4757917816E-10,-1.5585276173E-12,-5.9729921255E-0015,
-1.2688801216E-17,-1.1382797374E-20
},
{
-1.8533063273E+01, 3.8918344612E+01, 1.6645154356E-02,
-7.8702374448E-05, 2.2835785557E-07,-3.5700231258E-10,
2.9932909136E-13,-1.2849848798E-16, 2.2239974336E-20,
0.00, 0.00
}
},
/* Coefficients for each polynomial equation T(V) in C */
{
{-8.887677e+05,-2.054743e+02, 1.307316e-02, 5.611858e-06, 3.034392e-10},
{-1.215521e+06,-7.993152e+02,-1.971155e-01,-2.160351e-05,-8.879453e-10},
{0.0000000e+00, 2.382475e-02,-2.372981e-06,-6.567714e-10,-9.208444e-14},
{0.0000000e+00, 2.548081e-02,-5.270562e-07, 7.989244e-11,-3.520933e-15},
{-1.035821e+01, 2.712314e-02,-1.781781e-07, 3.243000e-12,-1.166816e-17}
}
};
double scale; /* transformation scale */
/* calculate seebeck voltage value for a given temperature and TC */
/*
double calc_seebeck(double tempin)
{
return (SEEBECK_COEF * tempin);
}
*/
/* calculate TC temperature given volts using polynomial equations */
double volt2temp_poly(double voltin) /* input voltage */
{
int pi; /* index to appropriate polynom */
int i;
double yout;
if (voltin < TC_VOLT_MIN) /* check to see if voltage in valid range */
{
voltin = TC_VOLT_MIN;
}
else if (voltin > TC_VOLT_MAX)
{
voltin = TC_VOLT_MAX;
}
pi = 0;
/* search through breakpoint list looking for proper interval */
while ( (pi < NUMEQN_V) &&
!((voltin >= tc_table.v_range[pi].min) &&
(voltin <= tc_table.v_range[pi].max)))
{
pi++;
}
/* calculate TC temperature as a function of volts */
yout = tc_table.coef_v[pi][ORDE_V];
for (i=ORDE_V-1; i<=0; i--)
{
/* efficient, nested polynomial calculation */
yout = yout*voltin+tc_table.coef_v[pi][i];
}
return (yout);
}
/******************************************************************************
CONVERTS TC VOLTS TO TEMPERATURE
--------------------------------
Reference temperature sensored by IC LM335Z, which has output
characteristic: 10 mV/K. Scale has been stated 5/1023 = 4.9 mV/LSB,
so if we have vi (in integer), it must be multiplied by scale to convert
to voltage temperature, and divided it by resolution of sensor to get
real temperature. ref_scale = scale/LM335_VT = (4.9 mV/LSB)/(10 mV/K) =
0.49 K/LSB. Increasing vi in its LSB will increase temperature by 0.49 K.
When calibrate (T=25 C), LM335 generate 2.982 volts (273.2+25) according
to his current temperature. In Differential op-amp, this temperature-based
voltage used to compute temperature reference. We don't need to compute it
in MCU.
All of 'kerumitan' has been handled by op-amps.
*******************************************************************************/
void tc_converter(unsigned int *vi, /* measured TC volts */
double *temp) /* linearized temperature */
/* return: error code, 0 = no error */
{
int i;
double v;
for (i=ADC_1; i<=ADC_8; i++)
{
v = DIGIT_TO_MILLIVOLT(vi[i])/TC_GAIN_AMP*1000; /* unit in microvolts !*/
temp[i] = volt2temp_poly(&v);
}
}
double lin_t[N_ADC_CHANNELS]; /* linearized temperature */
void TC_Task(void)
{
unsigned int *mbx;
/* ADC resolution */
scale = (double)(VREF_PLUS-VREF_MIN)/(double)((1<<RESOLUTION)-1); /* mV/bit */
#ifdef _WSC_
FOREVER
{
mbx = _mcx_receive_w(CNV_SEMA);
tc_converter((mbx, (double *)lin_t);
_mcx_send_mbx_w(TC_MBX, lin_t, CNV_FINISH_SEMA);
_mcx_msg_done(mbx);
}
#endif
}
SLIISR.S
;����������������������������������������������������������������������������Ŀ
;� SLIP PROTOCOL �
;� INTERRUPT HANDLER �
;� for 68HC16Z1 Microcontroller running MCX-16 �
;� �
;� compiled with Whitesmiths C compiler �
;� �
;� (c) June 1995 �
;� M. Lutfi �
;� Engineering Physics Dept. �
;� Faculty of Industrial Tech. �
;� Institut Technologi Bandung �
;� �
;������������������������������������������������������������������������������
.PROCESSOR M68HC16
.TITLE "Thesis Project : SLIP - communication handler"
.INCLUDE "hc16regs.mac"
.INCLUDE "mcx16.mac"
.INCLUDE "lgrset.mac"
;*******************************************************************************
;* SCI DRIVER DATA VARIABLES *
;*******************************************************************************
.PUBLIC _in_char, _out_char
.psect _data
_in_char: .BYTE (1)
_out_char: .BYTE (1)
_dest_temp: .BYTE (1)
_src_temp: .BYTE (1)
.psect _text
.even
.LIST + .MACRO
;*******************************************************************************
;* *
;* S C I I N P U T D R I V E R *
;* *
;*******************************************************************************
.PUBLIC _sciidrv
_sciidrv:
rdclr: ldd SCSR ; Get current status of SCI
bitb #RDRF ; See if receive data ready
beq scirdy ; if not SCI is a
ldab SCDR ; Read input data
bra rdclr ; Loop until clear
scirdy: andp #0FF1Fh ; Turn interrupts on again
inloop: ldab #1 ; bank 1
tbek ; EK = 1
tbxk ; XK = 1 (K=$11xx)
ldab #SCI_RCV_SEMA
ldaa #MCX_WAIT_ ; Wait for input character
swi
ldaa _in_char ; Get input character captured by isr
ldx #_src_temp ; Move it to safe place
staa 0,x
ldab #SCI_RCV_Q ; Then move the character into SCIIQ
ldaa #MCX_ENQUEUE_W_
swi
bra inloop ; Loop forever
;*******************************************************************************
;* *
;* S C I O U T P U T D R I V E R *
;* *
;*******************************************************************************
sciodrv: ldab #0Fh
tbek ; EK=F (K=$Fxxx)
ldab #1
tbxk ; XK=1 (K=$F1xx)
scioloop:
ldx #_dest_temp
ldab #SCI_TRM_Q ; Get next character from SCI_TRM_Q and put it into
ldaa #MCX_DEQUEUE_W_ ; _dest_temp as temporary location
swi
ldab 0,x ; Get the character
cmpb #0Ah ; New Line?
bne notnl ; Branch if not "\n"
ldd SCSR ; Get SCI status
ldaa #0Dh
staa SCDR+1 ; Output a "\r"
ldd #RIE+RE+TE+TIE
std SCCR1 ; Enable transmitter interrupts
; ldab #RIE+RE+TE+TIE
; stab SCCR1+1 ; Enable transmitter interrupts
ldab #SCI_TRM_SEMA ; Wait for it to be output completely
ldaa #MCX_WAIT_
swi
notnl: ldd SCSR ; Read status
ldaa 0,x ; Get character to output
staa SCDR+1 ; Output it
ldd #RIE+RE+TE+TIE
std SCCR1 ; Enable transmitter interrupts
; ldab #RIE+RE+TE+TIE
; stab SCCR1+1 ; Enable transmitter interrupts
ldab #SCI_TRM_SEMA ; Wait for it to be output completely
ldaa #MCX_WAIT_
swi
bra scioloop ; Loop forever
;*******************************************************************************
;* *
;* S C I I N T E R R U P T S E R V I C E R O U T I N E *
;* *
;*******************************************************************************
sciisr: orp #INTS_OFF ; Save the interrupt context
pshm d,e,x,y,z,k
ldab #1
tbek ; EK=1 (K=$1xxx)
tbyk ; YK=1 (K=$1x1x)
tbzk ; ZK=1 (K=$1x11)
clrb
tbxk ; XK=0 (K=$1011)
ldx 0000h ; x = [$10000]
tst 000Ah
bne notlvl0
ldy 0004h ; y = [$10004]
sts 8,y ; [y+8] = SP
lds 14h,x ; SP = [X+20]
notlvl0: inc 000Ah ; [$1000A] = [$1000A]+1
andp #SCIINTON ; Interrupts back on
ldz 12h,x
ldab #0Fh ; EK = F (K=$Fx11)
tbek
ldab #1
tbxk ; XK = 1 (K=$F111)
ldx #0000 ;h
ldy #_in_char ; y = &inchar
ldd SCCR1 ; If TDRE is set, see if SCCR1 has TIE set
bitb #TIE
beq notout ; If not, this is not an output interrupt
ldd SCSR ; Check SCI status register for TDRE
bita #TDRE
beq chkrd ; TDRE not set
ldd #RIE+RE+TE ; If so, this is a transmitter interrupt, turn
; TIE off now that the character is out
std SCCR1 ; Update SCCR1. That takes care of the output side
ldd SCSR ; Now treat a possible input interrupt that is
; simultaneous with the output. Reread the status
bitb #RDRF ; Check for RDRF set
beq noin ; Branch if no input occurred
ldd SCDR ; Yes it did. Read the input character
andb #7Fh ; Strip it to 7 bits
stab 0,y ; Store in temporary location (inchar)
PSHSEMA SCI_TRM_SEMA ; Put SCI_TRM_SEMA into Signal List
noin: ldaa #SCI_TRM_SEMA ; Now signal the SCI output semaphore
jmp isrrtn
notout:
ldd SCSR ; Read status again
chkrd:
bitb #RDRF ; See if this is an input interrupt. Check RDRF
beq notin ; It is not an input interrupt. So what was it?
ldd SCDR ; If it was an input interrupt, get the character
stab 0,y ; Store in temporary location (inchar)
; That takes care of the input. Now see if there
; was a simultaneous output interrupt
ldd SCSR ; Check SCI status register for TDRE
bita #TDRE
beq noout ; TDRE not set
ldd SCCR1 ; If TDRE is set, see if SCCR1 has TIE set
bitb #TIE
beq noout ; If not, this cannot be an output interrupt
ldd #RIE+RE+TE ; If so, this is a transmitter interrupt, turn
; TIE off now that the character is out
std SCCR1 ; Update SCCR1
PSHSEMA SCI_TRM_SEMA ; Signal SCI Output Semaphore
noout: ldaa #SCI_RCV_SEMA ; Now signal the input semaphore
jmp isrrtn
notin: clra ; This wasn't a recognizable SCI interrupt
jmp isrrtn
;*******************************************************************************
;* SCI VECTOR *
;*******************************************************************************
.END
;� SLIP PROTOCOL �
;� INTERRUPT HANDLER �
;� for 68HC16Z1 Microcontroller running MCX-16 �
;� �
;� compiled with Whitesmiths C compiler �
;� �
;� (c) June 1995 �
;� M. Lutfi �
;� Engineering Physics Dept. �
;� Faculty of Industrial Tech. �
;� Institut Technologi Bandung �
;� �
;������������������������������������������������������������������������������
.PROCESSOR M68HC16
.TITLE "Thesis Project : SLIP - communication handler"
.INCLUDE "hc16regs.mac"
.INCLUDE "mcx16.mac"
.INCLUDE "lgrset.mac"
;*******************************************************************************
;* SCI DRIVER DATA VARIABLES *
;*******************************************************************************
.PUBLIC _in_char, _out_char
.psect _data
_in_char: .BYTE (1)
_out_char: .BYTE (1)
_dest_temp: .BYTE (1)
_src_temp: .BYTE (1)
.psect _text
.even
.LIST + .MACRO
;*******************************************************************************
;* *
;* S C I I N P U T D R I V E R *
;* *
;*******************************************************************************
.PUBLIC _sciidrv
_sciidrv:
rdclr: ldd SCSR ; Get current status of SCI
bitb #RDRF ; See if receive data ready
beq scirdy ; if not SCI is a
ldab SCDR ; Read input data
bra rdclr ; Loop until clear
scirdy: andp #0FF1Fh ; Turn interrupts on again
inloop: ldab #1 ; bank 1
tbek ; EK = 1
tbxk ; XK = 1 (K=$11xx)
ldab #SCI_RCV_SEMA
ldaa #MCX_WAIT_ ; Wait for input character
swi
ldaa _in_char ; Get input character captured by isr
ldx #_src_temp ; Move it to safe place
staa 0,x
ldab #SCI_RCV_Q ; Then move the character into SCIIQ
ldaa #MCX_ENQUEUE_W_
swi
bra inloop ; Loop forever
;*******************************************************************************
;* *
;* S C I O U T P U T D R I V E R *
;* *
;*******************************************************************************
sciodrv: ldab #0Fh
tbek ; EK=F (K=$Fxxx)
ldab #1
tbxk ; XK=1 (K=$F1xx)
scioloop:
ldx #_dest_temp
ldab #SCI_TRM_Q ; Get next character from SCI_TRM_Q and put it into
ldaa #MCX_DEQUEUE_W_ ; _dest_temp as temporary location
swi
ldab 0,x ; Get the character
cmpb #0Ah ; New Line?
bne notnl ; Branch if not "\n"
ldd SCSR ; Get SCI status
ldaa #0Dh
staa SCDR+1 ; Output a "\r"
ldd #RIE+RE+TE+TIE
std SCCR1 ; Enable transmitter interrupts
; ldab #RIE+RE+TE+TIE
; stab SCCR1+1 ; Enable transmitter interrupts
ldab #SCI_TRM_SEMA ; Wait for it to be output completely
ldaa #MCX_WAIT_
swi
notnl: ldd SCSR ; Read status
ldaa 0,x ; Get character to output
staa SCDR+1 ; Output it
ldd #RIE+RE+TE+TIE
std SCCR1 ; Enable transmitter interrupts
; ldab #RIE+RE+TE+TIE
; stab SCCR1+1 ; Enable transmitter interrupts
ldab #SCI_TRM_SEMA ; Wait for it to be output completely
ldaa #MCX_WAIT_
swi
bra scioloop ; Loop forever
;*******************************************************************************
;* *
;* S C I I N T E R R U P T S E R V I C E R O U T I N E *
;* *
;*******************************************************************************
sciisr: orp #INTS_OFF ; Save the interrupt context
pshm d,e,x,y,z,k
ldab #1
tbek ; EK=1 (K=$1xxx)
tbyk ; YK=1 (K=$1x1x)
tbzk ; ZK=1 (K=$1x11)
clrb
tbxk ; XK=0 (K=$1011)
ldx 0000h ; x = [$10000]
tst 000Ah
bne notlvl0
ldy 0004h ; y = [$10004]
sts 8,y ; [y+8] = SP
lds 14h,x ; SP = [X+20]
notlvl0: inc 000Ah ; [$1000A] = [$1000A]+1
andp #SCIINTON ; Interrupts back on
ldz 12h,x
ldab #0Fh ; EK = F (K=$Fx11)
tbek
ldab #1
tbxk ; XK = 1 (K=$F111)
ldx #0000 ;h
ldy #_in_char ; y = &inchar
ldd SCCR1 ; If TDRE is set, see if SCCR1 has TIE set
bitb #TIE
beq notout ; If not, this is not an output interrupt
ldd SCSR ; Check SCI status register for TDRE
bita #TDRE
beq chkrd ; TDRE not set
ldd #RIE+RE+TE ; If so, this is a transmitter interrupt, turn
; TIE off now that the character is out
std SCCR1 ; Update SCCR1. That takes care of the output side
ldd SCSR ; Now treat a possible input interrupt that is
; simultaneous with the output. Reread the status
bitb #RDRF ; Check for RDRF set
beq noin ; Branch if no input occurred
ldd SCDR ; Yes it did. Read the input character
andb #7Fh ; Strip it to 7 bits
stab 0,y ; Store in temporary location (inchar)
PSHSEMA SCI_TRM_SEMA ; Put SCI_TRM_SEMA into Signal List
noin: ldaa #SCI_TRM_SEMA ; Now signal the SCI output semaphore
jmp isrrtn
notout:
ldd SCSR ; Read status again
chkrd:
bitb #RDRF ; See if this is an input interrupt. Check RDRF
beq notin ; It is not an input interrupt. So what was it?
ldd SCDR ; If it was an input interrupt, get the character
stab 0,y ; Store in temporary location (inchar)
; That takes care of the input. Now see if there
; was a simultaneous output interrupt
ldd SCSR ; Check SCI status register for TDRE
bita #TDRE
beq noout ; TDRE not set
ldd SCCR1 ; If TDRE is set, see if SCCR1 has TIE set
bitb #TIE
beq noout ; If not, this cannot be an output interrupt
ldd #RIE+RE+TE ; If so, this is a transmitter interrupt, turn
; TIE off now that the character is out
std SCCR1 ; Update SCCR1
PSHSEMA SCI_TRM_SEMA ; Signal SCI Output Semaphore
noout: ldaa #SCI_RCV_SEMA ; Now signal the input semaphore
jmp isrrtn
notin: clra ; This wasn't a recognizable SCI interrupt
jmp isrrtn
;*******************************************************************************
;* SCI VECTOR *
;*******************************************************************************
.END
Subscribe to:
Posts (Atom)