Skip to content

Instantly share code, notes, and snippets.

@johnhowe
Created June 16, 2010 09:55
Show Gist options
  • Save johnhowe/440408 to your computer and use it in GitHub Desktop.
Save johnhowe/440408 to your computer and use it in GitHub Desktop.
/*****************************************************************************
* File: k-2805.c
* Author: Clark Mills (clark@kiwi.gen.nz)
* Date: Sun Aug 7 09:56:59 NZST 2005
* Description: Routines to allow playing with the Dick Smith Electronics
* Discovery series K-2805 Parallel Port Interface
* License: GPL
* Keywords: Linux 2805 PCB printed circuit board kitset
*****************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <sys/io.h>
#include <stdlib.h>
/* defs */
#define BASEPORT 0x378 /* lp1 */
/* prototypes */
void push_byte(int byte);
void dac1_load( int byte );
void dac1_load( int byte );
void bits_load( int byte );
int adc_eoc();
int adc_data();
/* globals */
int port[3]; // Mirror of port values
/* functions */
int main()
{
int data;
int j;
port_init(); // Reset registers
card_power_on(); // Power up the card
// Output ~2.48v which is tied to adc input 0 for testing
dac1_load( 127 ); // Half of supply voltage
dac1_output_enable(); // DAC is always enabled
adc_cs_enable(); // Chip is always selected
adc_addr_low(); // Address is always 0000
usleep( 1000 );
while (1)
{
data = 0; // Collect our byte here
for (j=0; j<8; j++)
{
clock_bit_high();
usleep( 1000 );
data <<= 1; // Shift our byte
data |= adc_data(); // Get a bit
usleep( 1000 );
clock_bit_low();
usleep( 1000 );
}
printf( "%3d\r", data ); // Display our byte
fflush( stdout );
while (!adc_eoc()) // Wait for end-of-conversion flag
usleep( 1000 );
}
card_shutdown(); // We never get here
exit(0);
}
/*****************************************************************************
* Low level routines. *
*****************************************************************************/
port_init()
{
if (ioperm(BASEPORT, 3, 1)) { perror("ioperm"); exit(1); }
// Reset port and variables to a sane known state
port[0] = port[1] = port[2] = 0;
outb(port[0], BASEPORT+0);
outb(port[1], BASEPORT+1);
outb(port[2], BASEPORT+2);
}
card_power_on()
{
port[0] |= 0x80;
outb(port[0], BASEPORT+0);
}
card_power_off()
{
port[0] &= 0x7F;
outb(port[0], BASEPORT+0);
}
card_shutdown()
{
card_power_off();
if (ioperm(BASEPORT, 3, 0)) { perror("ioperm"); exit(1); }
}
/* Data bit routines */
data_bit_high()
{
port[0] |= 0x01;
outb(port[0], BASEPORT+0);
}
data_bit_low()
{
port[0] &= 0xFE;
outb(port[0], BASEPORT+0);
}
/* Clock routines */
clock_bit_high()
{
port[0] |= 0x02;
outb(port[0], BASEPORT+0);
}
clock_bit_low()
{
port[0] &= 0xFD;
outb(port[0], BASEPORT+0);
}
/* Shift in 1 byte */
void push_byte(int byte)
{
int j;
for (j=0; j<8; j++)
{
if (byte & 0x80) // MSB first
data_bit_high();
else
data_bit_low();
clock_bit_high();
clock_bit_low();
byte <<= 1;
}
}
/*****************************************************************************
* Routines that handle the digital to analogue converter 1 *
* Output can be read at: SK1 *
* Loads IC1, 74HC595 *
*****************************************************************************/
dac1_output_enable() // Inverse of expected bit state
{
port[2] |= 0x01;
outb(port[2], BASEPORT+2);
}
dac1_output_disable() // Inverse of expected bit state
{
port[2] &= 0xFE;
outb(port[2], BASEPORT+2);
}
dac1_store_high()
{
port[0] |= 0x04;
outb(port[0], BASEPORT+0);
}
dac1_store_low()
{
port[0] &= 0xFB;
outb(port[0], BASEPORT+0);
}
dac1_store()
{
dac1_store_high();
dac1_store_low();
}
void dac1_load( int byte )
{
push_byte(byte);
dac1_store();
}
/*****************************************************************************
* Routines that handle the digital to analogue converter 2 *
* Output can be read at: SK2 *
* Loads IC2, 74HC595 *
*****************************************************************************/
dac2_output_enable() // Inverse of expected bit state
{
port[2] |= 0x02;
outb(port[2], BASEPORT+2);
}
dac2_output_disable() // Inverse of expected bit state
{
port[2] &= 0xFD;
outb(port[2], BASEPORT+2);
}
dac2_store_high()
{
port[0] |= 0x08;
outb(port[0], BASEPORT+0);
}
dac2_store_low()
{
port[0] &= 0xF7;
outb(port[0], BASEPORT+0);
}
dac2_store()
{
dac2_store_high();
dac2_store_low();
}
void dac2_load( int byte )
{
push_byte(byte);
push_byte(0);
dac2_store();
}
/*****************************************************************************
* Routines that handle the open collector outputs *
* Output can be read at: SK4 *
* Loads IC3, 74HC595 *
*****************************************************************************/
bits_output_enable() // Inverse of expected bit state
{
port[2] |= 0x08;
outb(port[2], BASEPORT+2);
}
bits_output_disable() // Inverse of expected bit state
{
port[2] &= 0xF7;
outb(port[2], BASEPORT+2);
}
bits_store_high()
{
port[0] |= 0x10;
outb(port[0], BASEPORT+0);
}
bits_store_low()
{
port[0] &= 0xEF;
outb(port[0], BASEPORT+0);
}
bits_store()
{
bits_store_high();
bits_store_low();
}
void bits_load( int byte )
{
push_byte(byte);
push_byte(0);
push_byte(0);
bits_store();
}
/*****************************************************************************
* Routines that handle the analogue to digital converter and mux *
* Physical input is read from: SK5 *
* Loads IC4, TLC542 *
*****************************************************************************/
adc_cs_enable()
{
port[0] &= 0xDF;
outb(port[0], BASEPORT+0);
}
adc_cs_disable()
{
port[0] |= 0x20;
outb(port[0], BASEPORT+0);
}
adc_addr_high()
{
port[0] |= 0x40;
outb(port[0], BASEPORT+0);
}
adc_addr_low()
{
port[0] &= 0xBF;
outb(port[0], BASEPORT+0);
}
int adc_eoc()
{
int data;
data = inb( BASEPORT+1 );
data &= 0x40;
data >>= 6;
return ( data );
}
int adc_data()
{
int data;
data = inb( BASEPORT+1 );
data &= 0x10;
data >>= 4;
return ( data );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment