/* * Copyright (c) 2001 Tommy Bohlin * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* tekram.c */ #include /********************************************************************** * Constants **********************************************************************/ static const char id_tekram[]="tekram"; #define TEKRAM_PW 0x10 #define TEKRAM_115200 (TEKRAM_PW|0x00) #define TEKRAM_57600 (TEKRAM_PW|0x01) #define TEKRAM_38400 (TEKRAM_PW|0x02) #define TEKRAM_19200 (TEKRAM_PW|0x03) #define TEKRAM_9600 (TEKRAM_PW|0x04) #define TEKRAM_2400 (TEKRAM_PW|0x08) #define TEKRAM_TV (TEKRAM_PW|0x05) /********************************************************************** * Data structures **********************************************************************/ typedef struct Tekram { SerialDevice sd; SerialPort* sp; int state; int speed; } Tekram; /********************************************************************** * Tekram control **********************************************************************/ static int encodeSpeed(int speed) { switch(speed) { case 115200: return TEKRAM_115200; case 57600: return TEKRAM_57600; case 38400: return TEKRAM_38400; case 19200: return TEKRAM_19200; case 2400: return TEKRAM_2400; default: return TEKRAM_9600; } } static void speedTimer(void* sd) { Tekram* tek=(Tekram*)sd; SerialPort* sp=tek->sp; switch(tek->state) { case 1: sp->setLine(sp,LINE_RTS); tek->state=2; evtSetTimer(1,speedTimer,tek); break; case 2: sp->setLine(sp,LINE_DTR|LINE_RTS); tek->state=3; evtSetTimer(1,speedTimer,tek); /* At least 50us */ break; case 3: sp->setLine(sp,LINE_DTR); tek->state=4; evtSetTimer(1,speedTimer,tek); /* At least 7us */ break; case 4: sp->putChar(sp,encodeSpeed(tek->speed)); tek->state=5; evtSetTimer(100,speedTimer,tek); break; case 5: sp->setLine(sp,LINE_DTR|LINE_RTS); if(tek->speed!=9600) sp->setSpeed(sp,tek->speed); tek->state=0; /* Wait at least 50us before using */ break; } } /********************************************************************** * Methods **********************************************************************/ static int tekSetSpeed(SerialDevice* sd, int speed) { Tekram* tek=(Tekram*)sd; SerialPort* sp=tek->sp; tek->state=1; tek->speed=speed; sp->setSpeed(sp,9600); sp->setLine(sp,0); evtSetTimer(50,speedTimer,tek); /* Conservative estimate */ return 200; } static int tekGetSpeedMask(SerialDevice* sd) { Tekram* tek=(Tekram*)sd; return tek->sp->getSpeedMask(tek->sp)& (SPEED_2400|SPEED_9600|SPEED_19200|SPEED_38400|SPEED_57600|SPEED_115200); } static int tekGetMinTurnaroundMask(SerialDevice* sd) { return MIN_TA_10ms; } static int tekGetChar(SerialDevice* sd) { Tekram* tek=(Tekram*)sd; return tek->sp->getChar(tek->sp); } static void tekPutChar(SerialDevice* sd, int c) { Tekram* tek=(Tekram*)sd; if(tek->state==0) tek->sp->putChar(tek->sp,c); } static void tekClose(SerialDevice* sd) { Tekram* tek=(Tekram*)sd; SerialPort* sp=tek->sp; evtCancelTimer(speedTimer,tek); sp->setLine(sp,0); sp->handle=0; sp->status=0; freeMem(tek); } static void tekStatus(SerialPort* sp, int event) { Tekram* tek=(Tekram*)sp->handle; if(tek->sd.status) tek->sd.status(&tek->sd,event); } /********************************************************************** * External interface **********************************************************************/ SerialDevice* createTekram210Device(SerialPort* sp) { Tekram* tek=allocMem(id_tekram,sizeof(Tekram)); tek->sd.close=tekClose; tek->sd.setSpeed=tekSetSpeed; tek->sd.getSpeedMask=tekGetSpeedMask; tek->sd.getMinTurnaroundMask=tekGetMinTurnaroundMask; tek->sd.getChar=tekGetChar; tek->sd.putChar=tekPutChar; tek->sd.handle=0; tek->sd.status=0; tek->sp=sp; tek->state=0; tek->speed=0; sp->handle=tek; sp->status=tekStatus; return &tek->sd; }