📄 dapa.c
字号:
/* DAPA.C Direct AVR Parallel Access (c) 1999 Originally written by Sergey Larin. Corrected by Denis Chertykov, Uros Platise and Marek Michalkiewicz*/#ifndef NO_DAPA//#define DEBUG#include <stdio.h>#include <stdlib.h>#include <errno.h>#ifndef NO_DIRECT_IO/* Linux and FreeBSD differ in the order of outb() arguments. XXX any other OS/architectures with PC-style parallel ports? XXX how about the other *BSDs? */#if defined(__linux__) && defined(__i386__)#include <sys/io.h>#define ioport_read(port) inb(port)#define ioport_write(port, val) outb(val, port)#define ioport_enable(port, num) ioperm(port, num, 1)#define ioport_disable(port, num) ioperm(port, num, 0)#elif defined(__CYGWIN__)#include "cygwinp.h"#define ioport_read(port) inb(port)#define ioport_write(port, val) outb(val, port)#define ioport_enable(port, num) ioperm(port, num, 1)#define ioport_disable(port, num) ioperm(port, num, 0)#elif defined(__FreeBSD__) && defined(__i386__)#include <sys/fcntl.h>#include <machine/cpufunc.h>#include <machine/sysarch.h>#define ioport_read(port) inb(port)#define ioport_write(port, val) outb(port, val)#define ioport_enable(port, num) i386_set_ioperm(port, num, 1)#define ioport_disable(port, num) i386_set_ioperm(port, num, 0)#else/* Direct I/O port access not supported - ppdev/ppi kernel driver required for parallel port support to work at all. Only likely to work on PC-style parallel ports (all signals implemented) anyway. The only lines believed to be implemented in all parallel ports are: D0-D6 outputs (long long ago I heard of some non-PC machine with D7 hardwired to GND - don't remember what it was) BUSY input So far, only the dt006 interface happens to use a subset of the above. STROBE output might be pulsed by hardware and not be writable ACK input might only trigger an interrupt and not be readable Future designers of these "dongles" might want to keep this in mind. */#define ioport_read(port) (0xFF)#define ioport_write(port, val)#define ioport_enable(port, num) (-1)#define ioport_disable(port, num) (0)#endif#endif /* NO_DIRECT_IO */#include <unistd.h>#include <signal.h>#include "timeradd.h"#include <sys/ioctl.h>#include <fcntl.h>#include "parport.h"/* These should work on any architecture, not just i386. */#if defined(__linux__)#include "ppdev.h"#define par_claim(fd) ioctl(fd, PPCLAIM, 0)#define par_read_status(fd, ptr) ioctl(fd, PPRSTATUS, ptr)#define par_write_data(fd, ptr) ioctl(fd, PPWDATA, ptr)#define par_write_ctrl(fd, ptr) ioctl(fd, PPWCONTROL, ptr)#define par_set_dir(fd, ptr) ioctl(fd, PPDATADIR, ptr)#define par_release(fd) ioctl(fd, PPRELEASE, 0)#elif defined(__FreeBSD__)#include </sys/dev/ppbus/ppi.h>#define par_claim(fd) (0)#define par_read_status(fd, ptr) ioctl(fd, PPIGSTATUS, ptr)#define par_write_data(fd, ptr) ioctl(fd, PPISDATA, ptr)#define par_write_ctrl(fd, ptr) ioctl(fd, PPISCTRL, ptr)/* par_set_dir not defined, par_write_ctrl used instead */#define par_release(fd) (0)#else/* Dummy defines if ppdev/ppi not supported by the kernel. */#define par_claim(fd) (-1)#define par_read_status(fd, ptr)#define par_write_data(fd, ptr)#define par_write_ctrl(fd, ptr)#define par_release(fd) #endif#include "Global.h"#include "Error.h"#include "DAPA.h"#include "Avr.h"/* Parallel Port Base Address*/#define IOBASE parport_base#define IOSIZE 3/* FIXME: rewrite using tables to define new interface types. For each of the logical outputs (SCK, MOSI, RESET, ENA1, ENA2, power, XTAL1) there should be two bit masks that define which physical bits (from the parallel port output data or control registers, or serial port DTR/RTS/TXD) are affected, and if they should be inverted. More than one output may be changed. For each of the inputs (MISO, maybe TEST?), define which bit (only one, from parallel port status or CTS/DCD/DSR/RI) should be tested and if it should be inverted. One struct as described above should be initialized for each of the supported hardware interfaces. *//* Alex's Direct Avr Parallel Access */#define DAPA_SCK PARPORT_CONTROL_STROBE /* base + 2 */#define DAPA_RESET PARPORT_CONTROL_INIT /* base + 2 */#define DAPA_DIN PARPORT_STATUS_BUSY /* base + 1 */#define DAPA_DOUT 0x1 /* base *//* STK200 Direct Parallel Access */#define STK2_TEST1 0x01 /* D0 (base) - may be connected to POUT input */#define STK2_TEST2 0x02 /* D1 (base) - may be connected to BUSY input */#define STK2_ENA1 0x04 /* D2 (base) - ENABLE# for RESET#, MISO */#define STK2_ENA2 0x08 /* D3 (base) - ENABLE# for SCK, MOSI, LED# */#define STK2_SCK 0x10 /* D4 (base) - SCK */#define STK2_DOUT 0x20 /* D5 (base) - MOSI */#define STK2_LED 0x40 /* D6 (base) - LED# (optional) */#define STK2_RESET 0x80 /* D7 (base) - RESET# */#define STK2_DIN PARPORT_STATUS_ACK /* ACK (base + 1) - MISO *//* Altera Byte Blaster Port Configuration*/#define ABB_EN PARPORT_CONTROL_AUTOFD /* low active */#define ABB_LPAD 0x80 /* D7: loop back throught enable auto-detect */#define ABB_SCK 0x01 /* D0: TCK */#define ABB_RESET 0x02 /* D1: TMS */#define ABB_DOUT 0x40 /* D6: TDI */#define ABB_DIN PARPORT_STATUS_BUSY /* BUSY: TDO *//* D5 (pin 7) connected to ACK (pin 10) directly *//* D7 (pin 9) connected to POUT (pin 12) via 74HC244 buffer *//* optional modification for AVREAL: D3 (pin 5) = XTAL1 */#define ABB_XTAL1 0x08/* "Atmel AVR ISP" cable (?) */#define AISP_TSTOUT 0x08 /* D3 (base) - dongle test output */#define AISP_SCK 0x10 /* D4 (base) - SCK */#define AISP_DOUT 0x20 /* D5 (base) - MOSI */#define AISP_ENA 0x40 /* D6 (base) - ENABLE# for MISO, MOSI, SCK */#define AISP_RESET 0x80 /* D7 (base) - RESET# */#define AISP_DIN PARPORT_STATUS_ACK /* ACK (base + 1) - MISO *//* BUSY and POUT used as inputs to test for the dongle *//* Yet another AVR ISP cable from http://www.bsdhome.com/avrprog/ */#define BSD_POWER 0x0F /* D0-D3 (base) - power */#define BSD_ENA 0x10 /* D4 (base) - ENABLE# */#define BSD_RESET 0x20 /* D5 (base) - RESET# */#define BSD_SCK 0x40 /* D6 (base) - SCK */#define BSD_DOUT 0x80 /* D7 (base) - MOSI */#define BSD_DIN PARPORT_STATUS_ACK /* ACK (base + 1) - MISO *//* optional status LEDs, active low, not yet supported (base + 2) */#define BSD_LED_ERR PARPORT_CONTROL_STROBE /* error */#define BSD_LED_RDY PARPORT_CONTROL_AUTOFD /* ready */#define BSD_LED_PGM PARPORT_CONTROL_INIT /* programming */#define BSD_LED_VFY PARPORT_CONTROL_SELECT /* verifying *//* FBPRG - http://ln.com.ua/~real/avreal/adapters.html*/#define FBPRG_POW 0x07 /* D0,D1,D2 (base) - power supply (XXX D7 too?) */#define FBPRG_XTAL1 0x08 /* D3 (base) (not supported) */#define FBPRG_RESET 0x10 /* D4 (base) */#define FBPRG_DOUT 0x20 /* D5 (base) */#define FBPRG_SCK 0x40 /* D6 (base) */#define FBPRG_DIN PARPORT_STATUS_ACK /* ACK (base + 1) - MISO *//* DT006/Sample Electronics Parallel Cable http://www.dontronics.com/dt006.html*//* all at base, except for DT006_DIN at base + 1 */#define DT006_SCK 0x08#define DT006_RESET 0x04#define DT006_DIN PARPORT_STATUS_BUSY#define DT006_DOUT 0x01/* Default value for minimum SCK high/low time in microseconds. */#ifndef SCK_DELAY#define SCK_DELAY 5#endif/* Minimum RESET# high time in microseconds. Should be enough to charge a capacitor between RESET# and GND (it is recommended to use a voltage detector with open collector output, and only something like 100 nF for noise immunity). */#ifndef RESET_HIGH_TIME#define RESET_HIGH_TIME 1000#endif/* Delay from RESET# low to sending program enable command (the datasheet says it must be at least 20 ms). Also wait time for crystal oscillator to start after possible power down mode. */#ifndef RESET_LOW_TIME#define RESET_LOW_TIME 30000#endifvoidTDAPA::SckDelay(){ Delay_usec(t_sck);}#ifndef MIN_SLEEP_USEC#define MIN_SLEEP_USEC 20000#endifvoidTDAPA::Delay_usec(long t){#if defined(__CYGWIN__) if (cygwinp_delay_usec(t)){ return; }#endif struct timeval t1, t2; if (t <= 0) return; /* very short delay for slow machines */ gettimeofday(&t1, NULL); if (t > MIN_SLEEP_USEC) usleep(t - MIN_SLEEP_USEC); /* loop for the remaining time */ t2.tv_sec = t / 1000000UL; t2.tv_usec = t % 1000000UL; timeradd(&t1, &t2, &t1); do { gettimeofday(&t2, NULL); } while (timercmp(&t2, &t1, <));}voidTDAPA::ParportSetDir(int dir){ if (dir) par_ctrl |= PARPORT_CONTROL_DIRECTION; else par_ctrl &= ~PARPORT_CONTROL_DIRECTION; if (ppdev_fd != -1) {#ifdef par_set_dir par_set_dir(ppdev_fd, &dir);#else par_write_ctrl(ppdev_fd, &par_ctrl);#endif } else ioport_write(IOBASE+2, par_ctrl);}voidTDAPA::ParportWriteCtrl(){ if (ppdev_fd != -1) par_write_ctrl(ppdev_fd, &par_ctrl); else ioport_write(IOBASE+2, par_ctrl);}voidTDAPA::ParportWriteData(){ if (ppdev_fd != -1) par_write_data(ppdev_fd, &par_data); else ioport_write(IOBASE, par_data);}voidTDAPA::ParportReadStatus(){ if (ppdev_fd != -1) par_read_status(ppdev_fd, &par_status); else par_status = ioport_read(IOBASE+1);}voidTDAPA::SerialReadCtrl(){#ifdef TIOCMGET ioctl(ppdev_fd, TIOCMGET, &ser_ctrl);#else ser_ctrl = 0;#endif}voidTDAPA::SerialWriteCtrl(){#ifdef TIOCMGET ioctl(ppdev_fd, TIOCMSET, &ser_ctrl);#endif}voidTDAPA::OutReset(int b){ switch (pa_type) { case PAT_DAPA: case PAT_DAPA_2: if (b) par_ctrl |= DAPA_RESET; else par_ctrl &= ~DAPA_RESET; ParportWriteCtrl(); break; case PAT_STK200: if (b) par_data |= STK2_RESET; else par_data &= ~STK2_RESET; ParportWriteData(); break; case PAT_ABB: if (b) par_data |= ABB_RESET; else par_data &= ~ABB_RESET; ParportWriteData(); break; case PAT_AVRISP: if (b) par_data |= AISP_RESET; else par_data &= ~AISP_RESET; ParportWriteData(); break; case PAT_BSD: if (b) par_data |= BSD_RESET; else par_data &= BSD_RESET; ParportWriteData(); break; case PAT_FBPRG: if (b) par_data |= FBPRG_RESET; else par_data &= ~FBPRG_RESET; ParportWriteData(); break; case PAT_DT006: if (b) par_data |= DT006_RESET; else par_data &= ~DT006_RESET; ParportWriteData(); break;#ifdef TIOCMGET case PAT_DASA: SerialReadCtrl(); if (b) ser_ctrl |= TIOCM_RTS; else ser_ctrl &= ~TIOCM_RTS; SerialWriteCtrl(); break; case PAT_DASA2: ioctl(ppdev_fd, b ? TIOCSBRK : TIOCCBRK, 0); break;#else case PAT_DASA: case PAT_DASA2: break;#endif /* TIOCMGET */ } Delay_usec(b ? RESET_HIGH_TIME : RESET_LOW_TIME);}voidTDAPA::OutSck(int b){ switch (pa_type) { case PAT_DAPA: case PAT_DAPA_2: if (b) par_ctrl &= ~DAPA_SCK; else par_ctrl |= DAPA_SCK; ParportWriteCtrl(); break; case PAT_STK200: if (b) par_data |= STK2_SCK; else par_data &= ~STK2_SCK; ParportWriteData(); break; case PAT_ABB: if (b) par_data |= ABB_SCK; else par_data &= ~ABB_SCK; ParportWriteData(); break; case PAT_AVRISP: if (b) par_data |= AISP_SCK; else par_data &= ~AISP_SCK; ParportWriteData(); break; case PAT_BSD: if (b) par_data |= BSD_SCK; else par_data &= ~BSD_SCK; ParportWriteData(); break; case PAT_FBPRG: if (b) par_data |= FBPRG_SCK; else par_data &= ~FBPRG_SCK; ParportWriteData(); break; case PAT_DT006: if (b) par_data |= DT006_SCK; else par_data &= ~DT006_SCK; ParportWriteData(); break;#ifdef TIOCMGET case PAT_DASA: SerialReadCtrl(); if (b) ser_ctrl |= TIOCM_DTR; else ser_ctrl &= ~TIOCM_DTR; SerialWriteCtrl(); break; case PAT_DASA2: SerialReadCtrl(); if (b) ser_ctrl |= TIOCM_RTS; else ser_ctrl &= ~TIOCM_RTS; SerialWriteCtrl(); break;#else case PAT_DASA: case PAT_DASA2: break;#endif /* TIOCMGET */ }}voidTDAPA::OutEnaReset(int b){ bool no_ps2_hack = GetCmdParam("-dno-ps2-hack", false); switch (pa_type) { case PAT_DAPA: case PAT_DAPA_2: case PAT_FBPRG: case PAT_DT006: if (b) { ParportSetDir(0); } else if (!no_ps2_hack) { /* No special enable line on these interfaces, for PAT_DAPA this only disables the data line (MOSI) and not SCK. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -