/*
SpStuuur
De software voor SpStuur
Pros 2003 ... 2008
*/
#define F_CPU 14745600UL
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/sleep.h>
#include <compat/deprecated.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <util/delay.h>
typedef unsigned char u08;
typedef unsigned short u16;
/*
Weerstanden 47k 15k 8k2 4k7 1k5 100R
Spanningen
950, 854, 714, 580, 379, 134
*/
#define V1 1000
#define V5 (V1 * 10)
#define Uplus 854
#define UV1plus 714
#define UV5plus 580
#define Umin 379
#define UV1min 134
#define UV5min 134
/*
De uitgangen
*/
#define BIT0 PC3
#define BIT1 PC2
#define BIT2 PC1
#define BIT3 PD4
#define BIT4 PC0
#define BIT5 PD5
#define BIT6 PD6
#define BIT7 PD7
#define BIT0_PORT PORTC
#define BIT1_PORT PORTC
#define BIT2_PORT PORTC
#define BIT3_PORT PORTD
#define BIT4_PORT PORTC
#define BIT5_PORT PORTD
#define BIT6_PORT PORTD
#define BIT7_PORT PORTD
#define BIT0_DDR DDRC
#define BIT1_DDR DDRC
#define BIT2_DDR DDRC
#define BIT3_DDR DDRD
#define BIT4_DDR DDRC
#define BIT5_DDR DDRD
#define BIT6_DDR DDRD
#define BIT7_DDR DDRD
#define BEEP PD3
#define BUFCLK PB2
#define BUFCLK_L PC4
#define BUFCLK_H PB1
#define BEEP_PORT PORTD
#define BUFCLK_PORT PORTB
#define BUFCLK_L_PORT PORTC
#define BUFCLK_H_PORT PORTB
#define BEEP_DDR DDRD
#define BUFCLK_DDR DDRB
#define BUFCLK_L_DDR DDRC
#define BUFCLK_H_DDR DDRB
// De pinnen die het LCD-display bedienen
#define LCD_PORT_D7 PORTD
#define LCD_PORT_D6 PORTD
#define LCD_PORT_D5 PORTD
#define LCD_PORT_D4 PORTC
#define LCD_PIN_D7 PIND
#define LCD_PIN_D6 PIND
#define LCD_PIN_D5 PIND
#define LCD_PIN_D4 PINC
#define LCD_DDR_D7 DDRD
#define LCD_DDR_D6 DDRD
#define LCD_DDR_D5 DDRD
#define LCD_DDR_D4 DDRC
#define LCD_D7 PD7
#define LCD_D6 PD6
#define LCD_D5 PD5
#define LCD_D4 PC0
#define LCD_RS_PORT PORTC /* port for RS line */
#define LCD_RS_DDR DDRC /* ddr for RS line */
#define LCD_RS PC3
#define LCD_RW_PORT PORTC /* port for RW line */
#define LCD_RW_DDR DDRC /* ddr for RW line */
#define LCD_RW PC2
#define LCD_E_PORT PORTB /* port for Enable line */
#define LCD_E_DDR DDRB /* ddr for Enable line */
#define LCD_E PB0
/* instruction register bit positions */
#define LCD_CLR 0 /* DB0: clear display */
#define LCD_HOME 1 /* DB1: return to home position */
#define LCD_ENTRY_MODE 2 /* DB2: set entry mode */
#define LCD_ENTRY_INC 1 /* DB1: 1=increment, 0=decrement */
#define LCD_ENTRY_SHIFT 0 /* DB2: 1=display shift on */
#define LCD_ON 3 /* DB3: turn lcd/cursor on */
#define LCD_ON_DISPLAY 2 /* DB2: turn display on */
#define LCD_ON_CURSOR 1 /* DB1: turn cursor on */
#define LCD_ON_BLINK 0 /* DB0: blinking cursor ? */
#define LCD_MOVE 4 /* DB4: move cursor/display */
#define LCD_MOVE_DISP 3 /* DB3: move display (0-> cursor) ? */
#define LCD_MOVE_RIGHT 2 /* DB2: move right (0-> left) ? */
#define LCD_FUNCTION 5 /* DB5: function set */
#define LCD_FUNCTION_8BIT 4 /* DB4: set 8BIT mode (0->4BIT mode) */
#define LCD_FUNCTION_2LINES 3 /* DB3: two lines (0->one line) */
#define LCD_FUNCTION_10DOTS 2 /* DB2: 5x10 font (0->5x7 font) */
#define LCD_CGRAM 6 /* DB6: set CG RAM address */
#define LCD_DDRAM 7 /* DB7: set DD RAM address */
#define LCD_BUSY 7 /* DB7: LCD is busy */
/* set entry mode: display shift on/off, dec/inc cursor move direction */
#define LCD_ENTRY_DEC 0x04 /* display shift off, dec cursor move dir */
#define LCD_ENTRY_DEC_SHIFT 0x05 /* display shift on, dec cursor move dir */
#define LCD_ENTRY_INC_ 0x06 /* display shift off, inc cursor move dir */
#define LCD_ENTRY_INC_SHIFT 0x07 /* display shift on, inc cursor move dir */
/* display on/off, cursor on/off, blinking char at cursor position */
#define LCD_DISP_OFF 0x08 /* display off */
#define LCD_DISP_ON 0x0C /* display on, cursor off */
#define LCD_DISP_ON_BLINK 0x0D /* display on, cursor off, blink char */
#define LCD_DISP_ON_CURSOR 0x0E /* display on, cursor on */
#define LCD_DISP_ON_CURSOR_BLINK 0x0F /* display on, cursor on, blink char */
/* move cursor/shift display */
#define LCD_MOVE_CURSOR_LEFT 0x10 /* move cursor left (decrement) */
#define LCD_MOVE_CURSOR_RIGHT 0x14 /* move cursor right (increment) */
#define LCD_MOVE_DISP_LEFT 0x18 /* shift display left */
#define LCD_MOVE_DISP_RIGHT 0x1C /* shift display right */
/* function set: set interface data length and number of display lines */
#define LCD_FUNCTION_4BIT_1LINE 0x20 /* 4-bit interface, single line, 5x7 dots */
#define LCD_FUNCTION_4BIT_2LINES 0x28 /* 4-bit interface, dual line, 5x7 dots */
#define LCD_FUNCTION_8BIT_1LINE 0x30 /* 8-bit interface, single line, 5x7 dots */
#define LCD_FUNCTION_8BIT_2LINES 0x38 /* 8-bit interface, dual line, 5x7 dots */
#define LCD_MODE_DEFAULT ((1<<LCD_ENTRY_MODE) | (1<<LCD_ENTRY_INC))
/* normally you do not change the following */
#define LCD_LINES 2 /* visible lines */
#define LCD_LINE_LENGTH 0x28 /* internal line length */
#define LCD_START_LINE1 0x00 /* DDRAM address of first char of line 1 */
#define LCD_START_LINE2 0x28 /* DDRAM address of first char of line 2 */
#define UART_RX_BUFFER_SIZE 23
#define P(s) ({static const char c[] __attribute__ ((progmem)) = s;c;})
#define lcd_puts_P(__s) lcd_puts_p(P(__s))
#define lcd_e_delay() _delay_us(1);
#define lcd_e_high() sbi(LCD_E_PORT, LCD_E)
#define lcd_e_low() cbi(LCD_E_PORT, LCD_E)
#define lcd_e_toggle() toggle_e()
#define lcd_cmd_mode() cbi(LCD_RS_PORT, LCD_RS) /* RS=0 command mode */
#define lcd_data_mode() sbi(LCD_RS_PORT, LCD_RS) /* RS=1 data mode */
#define lcd_wr_mode() cbi(LCD_RW_PORT, LCD_RW) /* RW=0 write mode */
#define lcd_rd_mode() sbi(LCD_RW_PORT, LCD_RW) /* RW=1 read mode */
#define LCD_FUNCTION_DEFAULT LCD_FUNCTION_4BIT_2LINES
volatile static int ADC_in;
static char uart_outbuf[UART_RX_BUFFER_SIZE + 1];
static char uart_rxbuf[UART_RX_BUFFER_SIZE + 1];
volatile static unsigned char uart_rx_pos; /* end of string in rx */
volatile static unsigned char uart_rx_linecomplete; /* one complete line in buffer */
unsigned int Spanning;
unsigned char i, j, rxresult, status, InitDisplay;
char cmd;
char *val;
char asciistring[10];
#define delay(x) _delay_loop_1(x)
#define disable_INT0() cbi(GICR, INT0)
void delay_ms(unsigned int ms)
{
for (; ms > 0; ms--) {
_delay_ms(0.98);
}
}
void delay_us(unsigned int us)
{
for (; us > 0; us--) {
_delay_us(0.9);
}
}
// Init PD2 als INT0
void enable_INT0(void)
{
cbi(DDRD, PD2); // PD2 = ingang
sbi(PORTD, PD2); // Pull-up weerstand activeren
sbi(MCUCR, ISC01); // The falling edge of INT0 generates an interrupt request.
sbi(GICR, INT0);
}
void u2ascii(u16 d)
{
unsigned char tmp;
/*
transformeer een unsigned short naar ascii,
uitgedrukt in mVolt.
123 wordt 00.123mV
4567 wordt 04.567mV
*/
/* d omzetten naar mVolt */
d /= 2;
tmp = d / 10000;
asciistring[0] = tmp + '0';
d -= (tmp * 10000);
tmp = d / 1000; /* tmp = 1 */
asciistring[1] = tmp + '0';
asciistring[2] = '.';
d -= (tmp * 1000); /* d = 234 */
tmp = d / 100; /* tmp = 2 */
asciistring[3] = tmp + '0';
d -= (tmp * 100); /* d = 34 */
tmp = d / 10; /* tmp = 3 */
asciistring[4] = tmp + '0';
d -= (tmp * 10); /* d = 4 */
asciistring[5] = d + '0';
asciistring[6] = 'm';
asciistring[7] = 'V';
asciistring[8] = 0;
}
/* return analog value of a given channel. You must enable interrupt with
* sei() in the main program */
int convertanalog(void)
{
sbi(ADCSRA, ADSC); // start conversion
while ((ADCSRA & _BV(ADSC)) != 0) { // Effe wachten tot ADSC laag is
}
ADC_in = ADC;
return (ADC_in);
}
/* defines all data pins as input */
void lcd_data_port_in(void)
{
cbi(LCD_DDR_D7, LCD_D7);
cbi(LCD_DDR_D6, LCD_D6);
cbi(LCD_DDR_D5, LCD_D5);
cbi(LCD_DDR_D4, LCD_D4);
sbi(LCD_RS_DDR, LCD_RS);
sbi(LCD_RW_DDR, LCD_RW);
sbi(LCD_E_DDR, LCD_E);
}
/* defines all data pins as output */
void lcd_data_port_out(void)
{
sbi(LCD_DDR_D7, LCD_D7);
sbi(LCD_DDR_D6, LCD_D6);
sbi(LCD_DDR_D5, LCD_D5);
sbi(LCD_DDR_D4, LCD_D4);
sbi(LCD_RS_DDR, LCD_RS);
sbi(LCD_RW_DDR, LCD_RW);
sbi(LCD_E_DDR, LCD_E);
}
static void lcd_out_low(u08 d)
{ /* output low nibble */
if (d & 0x08)
sbi(LCD_PORT_D7, LCD_D7);
else
cbi(LCD_PORT_D7, LCD_D7);
if (d & 0x04)
sbi(LCD_PORT_D6, LCD_D6);
else
cbi(LCD_PORT_D6, LCD_D6);
if (d & 0x02)
sbi(LCD_PORT_D5, LCD_D5);
else
cbi(LCD_PORT_D5, LCD_D5);
if (d & 0x01)
sbi(LCD_PORT_D4, LCD_D4);
else
cbi(LCD_PORT_D4, LCD_D4);
}
static void lcd_out_high(u08 d)
{ /* output high nibble */
if (d & 0x80)
sbi(LCD_PORT_D7, LCD_D7);
else
cbi(LCD_PORT_D7, LCD_D7);
if (d & 0x40)
sbi(LCD_PORT_D6, LCD_D6);
else
cbi(LCD_PORT_D6, LCD_D6);
if (d & 0x20)
sbi(LCD_PORT_D5, LCD_D5);
else
cbi(LCD_PORT_D5, LCD_D5);
if (d & 0x10)
sbi(LCD_PORT_D4, LCD_D4);
else
cbi(LCD_PORT_D4, LCD_D4);
}
static void toggle_e(void)
/* toggle Enable Pin */
{
lcd_e_high();
lcd_e_delay();
lcd_e_low();
}
static void lcd_write(u08 data, u08 rs)
{
/* configure data pins as output */
lcd_data_port_out();
/* output high nibble first */
lcd_out_high(data);
if (rs)
lcd_data_mode(); /* RS=1: write data */
else
lcd_cmd_mode(); /* RS=0: write instruction */
lcd_wr_mode(); /* RW=0 write mode */
lcd_e_toggle();
/* output low nibble */
lcd_out_low(data);
if (rs)
lcd_data_mode(); /* RS=1: write data */
else
lcd_cmd_mode(); /* RS=0: write instruction */
lcd_wr_mode(); /* RW=0 write mode */
lcd_e_toggle();
/* all data pins high (inactive) */
lcd_data_port_in();
}
static u08 lcd_read(u08 rs)
{
register u08 data;
/* configure data pins as input */
lcd_data_port_in();
if (rs)
lcd_data_mode(); /* RS=1: read data */
else
lcd_cmd_mode(); /* RS=0: read busy flag */
lcd_rd_mode(); /* RW=1 read mode */
lcd_e_high();
lcd_e_delay();
/* read high nibble first */
data = bit_is_set(LCD_PIN_D7, LCD_D7) ? 0x80 : 0;
data |= bit_is_set(LCD_PIN_D6, LCD_D6) ? 0x40 : 0;
data |= bit_is_set(LCD_PIN_D5, LCD_D5) ? 0x20 : 0;
data |= bit_is_set(LCD_PIN_D4, LCD_D4) ? 0x10 : 0;
lcd_e_low();
lcd_e_delay(); /* Enable low */
lcd_e_high();
lcd_e_delay();
/* read low nibble */
data |= bit_is_set(LCD_PIN_D7, LCD_D7) ? 0x08 : 0;
data |= bit_is_set(LCD_PIN_D6, LCD_D6) ? 0x04 : 0;
data |= bit_is_set(LCD_PIN_D5, LCD_D5) ? 0x02 : 0;
data |= bit_is_set(LCD_PIN_D4, LCD_D4) ? 0x01 : 0;
lcd_e_low();
return (data);
}
static unsigned char lcd_waitbusy(void)
/* loops while lcd is busy, reads address counter */
{
register unsigned char c;
while ((c = lcd_read(0)) & (1 << LCD_BUSY)) {
}
return (c); // return address counter=position
}
void lcd_command(u08 cmd)
/* send commando <cmd> to LCD */
{
lcd_data_port_out(); /* all data port bits as output */
lcd_waitbusy();
lcd_write(cmd, 0);
}
void lcd_gotoxy(u08 x, u08 y)
/* goto position (x,y) */
{
if (y == 0)
lcd_command((1 << LCD_DDRAM) + LCD_START_LINE1 + x);
else
lcd_command((1 << LCD_DDRAM) + LCD_START_LINE2 + x);
}
void lcd_clrscr(void)
/* clear lcd and set cursor to home position */
{
lcd_command(1 << LCD_CLR);
}
void lcd_home(void)
/* set cursor to home position */
{
lcd_command(1 << LCD_HOME);
}
void lcd_putc(char c)
/* print character at current cursor position */
{
lcd_waitbusy(); // read busy-flag and address counter
lcd_write((unsigned char) c, 1);
}
void lcd_puts(const char *s)
/* print string on lcd */
{
while (*s) {
lcd_putc(*s);
s++;
}
}
void lcd_puts_p(const prog_char * progmem_s)
/* print string from program memory on lcd */
{
register char c;
while ((c = pgm_read_byte(progmem_s++))) {
lcd_putc(c);
}
}
/*
Een soort atof(), waarbij het resultaat een int is.
We verwachten 0 tot 3 cijfers na de komma; als er meer
zijn, worden die genegeerd.
*/
unsigned int my_atoi(const char *s)
{
unsigned int tmp, x;
unsigned char komma = 'n';
x = 0;
while (*s) {
if ((*s >= '0') && (*s <= '9')) {
tmp = *s - '0';
x = (x * 10) + tmp;
s++;
if (komma < 4) {
komma++;
} else if (komma == 4) {
break;
}
} else if ((*s == ',') || (*s == '.')) {
komma = 0;
s++;
} else {
break;
}
}
switch (komma) {
case 0:
case 'n':
x *= 1000;
break;
case 1:
x *= 100;
break;
case 2:
x *= 10;
break;
}
if (x > 0x7FFe) {
x = 0x7FFE;
}
return (x * 2);
}
void io_out(void)
{
sbi(BIT7_DDR, BIT7);
sbi(BIT6_DDR, BIT6);
sbi(BIT5_DDR, BIT5);
sbi(BIT4_DDR, BIT4);
sbi(BIT3_DDR, BIT3);
sbi(BIT2_DDR, BIT2);
sbi(BIT1_DDR, BIT1);
sbi(BIT0_DDR, BIT0);
}
void lcd_init(u08 dispAttr)
/* initialize display and select type of cursor
dispAttr: LCD_DISP_OFF, LCD_DISP_ON, LCD_DISP_ON_CURSOR, LCD_DISP_CURSOR_BLINK
*/
{
/*------ Initialize lcd to 4 bit i/o mode -------*/
lcd_data_port_out(); /* all data port bits as output */
sbi(LCD_RS_DDR, LCD_RS); /* RS pin as output */
sbi(LCD_RW_DDR, LCD_RW); /* RW pin as output */
sbi(LCD_E_DDR, LCD_E); /* E pin as output */
delay_us(16000); /* wait 16ms or more after power-on */
/* initial write to lcd is 8bit */
lcd_out_high(LCD_FUNCTION_8BIT_1LINE);
lcd_e_toggle();
delay_us(4992); /* delay, busy flag can't be checked here */
lcd_out_high(LCD_FUNCTION_8BIT_1LINE);
lcd_e_toggle();
delay_us(64); /* delay, busy flag can't be checked here */
lcd_out_high(LCD_FUNCTION_8BIT_1LINE);
lcd_e_toggle();
delay_us(64); /* delay, busy flag can't be checked here */
lcd_out_high(LCD_FUNCTION_4BIT_1LINE); /* set IO mode to 4bit */
lcd_e_toggle();
/* from now the lcd only accepts 4 bit I/O, we can use lcd_command() */
lcd_command(LCD_FUNCTION_DEFAULT); /* function set: display lines */
lcd_command(LCD_DISP_OFF); /* display off */
lcd_clrscr(); /* display clear */
lcd_command(LCD_MODE_DEFAULT); /* set entry mode */
lcd_command(dispAttr); /* display/cursor control */
}
// Deze functie wordt aangeroepen, telkens er een karakter ontvangen werd
SIGNAL(SIG_UART_RECV)
{
uart_rxbuf[uart_rx_pos] = UDR;
if ((uart_rxbuf[uart_rx_pos] == '\n') || (uart_rx_pos > UART_RX_BUFFER_SIZE - 1)) {
uart_rxbuf[uart_rx_pos] = 0;
strcpy(uart_outbuf, uart_rxbuf);
uart_rx_linecomplete = 1;
uart_rx_pos = 0;
} else {
uart_rx_pos++;
}
}
void uart_init(void)
{
uart_rx_pos = 0;
uart_rx_linecomplete = 0;
UCSRB = _BV(TXEN) | _BV(RXEN) | _BV(RXCIE); // enable tx/rx and interrupt on rx
UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // Set frame format: 8N1
UBRRH = 0; // set baudrate (9600, 19200, 38400, 57600, 76800, 115200, 230400)
UBRRL = (F_CPU / (16 * 38400UL)) - 1;
}
// Wait until tx holding register is empty, then send character c down the UART Tx.
void uart_sendchar(unsigned char c)
{
loop_until_bit_is_set(UCSRA, UDRE);
UDR = c;
}
/* send string to the rs232 */
void uart_sendstr(char *s)
{
while (*s) {
uart_sendchar(*s);
s++;
}
}
void uart_sendstr_p(const prog_char * progmem_s)
/* print string from program memory on rs232 */
{
char c;
while ((c = pgm_read_byte(progmem_s++))) {
uart_sendchar(c);
}
}
#define uart_sendstr_P(__s) uart_sendstr_p(P(__s))
void reply(int r)
{
if (r == 1) {
uart_sendstr_P("ok\n");
} else if (r == 0) {
uart_sendstr_P("\n\nGeldige opdrachten:\n\n");
uart_sendstr_P("u=x of s=x zet de spanning op x\n");
uart_sendstr_P("u=+ u=- vermeerder of verminder de spanning met 1mV\n");
uart_sendstr_P("u=? toon de ingestelde spanning\n");
}
}
void beep(unsigned int freq, unsigned int dur)
{
unsigned int cnt, del, times;
/*
We gebruiken bit 7 om de beeper te sturen.
freq wordt uitgedrukt in Hz
dur wordt uitgedrukt in mSec
del is de delay tussen 2 flanken
times is het aantal cycli
resolutie = 1µSec
Voorbeeld: freq = 2000
dur = 5000
del = 500000 / 2000 = 250
dur = dur * 1000 = 5000000
times = 5000000 / 500 = 10000
*/
del = 500000 / freq;
dur *= 10;
times = dur / (del / 50);
sbi(BEEP_DDR, BEEP);
for (cnt = 0; cnt < times; cnt++) {
sbi(BEEP_PORT, BEEP);
delay_us(del);
cbi(BEEP_PORT, BEEP);
delay_us(del);
}
}
void bip(void)
{
unsigned int cnt;
sbi(BEEP_DDR, BEEP);
for (cnt = 0; cnt < 6; cnt++) {
sbi(BEEP_PORT, BEEP);
delay_us(1000);
cbi(BEEP_PORT, BEEP);
delay_us(1000);
}
}
void Sp2Displ(u16 d)
{
if (InitDisplay == 'y') {
InitDisplay = 'n';
lcd_clrscr();
lcd_puts_P("Ingestelde spanning:");
}
lcd_gotoxy(33, 1);
u2ascii(d);
lcd_puts(asciistring);
}
/* Zet de spanning op 0 */
void out0(void)
{
io_out();
cbi(BUFCLK_H_PORT, BUFCLK_H);
cbi(BUFCLK_PORT, BUFCLK);
cbi(BUFCLK_L_PORT, BUFCLK_L);
cbi(BIT7_PORT, BIT7);
cbi(BIT6_PORT, BIT6);
cbi(BIT5_PORT, BIT5);
cbi(BIT4_PORT, BIT4);
cbi(BIT3_PORT, BIT3);
cbi(BIT2_PORT, BIT2);
cbi(BIT1_PORT, BIT1);
cbi(BIT0_PORT, BIT0);
sbi(BUFCLK_H_PORT, BUFCLK_H);
sbi(BUFCLK_L_PORT, BUFCLK_L);
sbi(BUFCLK_PORT, BUFCLK);
}
void wr_spanning(u16 d)
{
io_out();
/* Eerst D15 ... D08 */
cbi(BUFCLK_H_PORT, BUFCLK_H);
if (d & 0x8000)
sbi(BIT7_PORT, BIT7);
else
cbi(BIT7_PORT, BIT7);
if (d & 0x4000)
sbi(BIT6_PORT, BIT6);
else
cbi(BIT6_PORT, BIT6);
if (d & 0x2000)
sbi(BIT5_PORT, BIT5);
else
cbi(BIT5_PORT, BIT5);
if (d & 0x1000)
sbi(BIT4_PORT, BIT4);
else
cbi(BIT4_PORT, BIT4);
if (d & 0x0800)
sbi(BIT3_PORT, BIT3);
else
cbi(BIT3_PORT, BIT3);
if (d & 0x0400)
sbi(BIT2_PORT, BIT2);
else
cbi(BIT2_PORT, BIT2);
if (d & 0x0200)
sbi(BIT1_PORT, BIT1);
else
cbi(BIT1_PORT, BIT1);
if (d & 0x0100)
sbi(BIT0_PORT, BIT0);
else
cbi(BIT0_PORT, BIT0);
sbi(BUFCLK_H_PORT, BUFCLK_H);
/* Vervolgens D07 ... D00 */
cbi(BUFCLK_PORT, BUFCLK);
cbi(BUFCLK_L_PORT, BUFCLK_L);
if (d & 0x0080)
sbi(BIT7_PORT, BIT7);
else
cbi(BIT7_PORT, BIT7);
if (d & 0x0040)
sbi(BIT6_PORT, BIT6);
else
cbi(BIT6_PORT, BIT6);
if (d & 0x0020)
sbi(BIT5_PORT, BIT5);
else
cbi(BIT5_PORT, BIT5);
if (d & 0x0010)
sbi(BIT4_PORT, BIT4);
else
cbi(BIT4_PORT, BIT4);
if (d & 0x0008)
sbi(BIT3_PORT, BIT3);
else
cbi(BIT3_PORT, BIT3);
if (d & 0x0004)
sbi(BIT2_PORT, BIT2);
else
cbi(BIT2_PORT, BIT2);
if (d & 0x0002)
sbi(BIT1_PORT, BIT1);
else
cbi(BIT1_PORT, BIT1);
if (d & 0x0001)
sbi(BIT0_PORT, BIT0);
else
cbi(BIT0_PORT, BIT0);
sbi(BUFCLK_L_PORT, BUFCLK_L);
lcd_e_delay();
sbi(BUFCLK_PORT, BUFCLK);
Sp2Displ(d);
bip();
}
/*
Initialiseer input en output.
*/
void io_init(void)
{
// We moeten zo snel mogelijk 0x0000 op de uitgangsbuffer plaatsen.
io_out();
sbi(BUFCLK_DDR, BUFCLK);
sbi(BUFCLK_L_DDR, BUFCLK_L);
sbi(BUFCLK_H_DDR, BUFCLK_H);
sbi(BUFCLK_H_PORT, BUFCLK_H);
sbi(BUFCLK_L_PORT, BUFCLK_L);
sbi(BUFCLK_PORT, BUFCLK);
Spanning = 0;
// out0();
}
void init(void)
{
io_init(); // io-poorten initialiseren, spanning op 0 zetten
lcd_init(LCD_DISP_ON); // initialize display, cursor off
uart_init(); // initialize rs232
enable_INT0(); // De noodstop-knop komt op INT0
sei(); /* enable global interrupt */
lcd_clrscr();
ADCSRA = _BV(ADEN) | _BV(ADIF) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0);
ADMUX = 5 | _BV(REFS0); // Init ADC
sbi(ADCSRA, ADSC); // start dummy conversion
beep(1000, 200);
lcd_puts_P("SpStuur init done.");
lcd_gotoxy(35, 1);
lcd_puts_P("Pros 2004");
InitDisplay = 'y';
beep(800, 200);
delay_ms(5000);
}
SIGNAL(SIG_INTERRUPT0)
{
out0(); // Uitgangsspanning op 0 zetten
Spanning = 0;
Sp2Displ(0);
beep(1200, 220);
delay_ms(1000);
while (bit_is_clear(PIND, PIND2)) {
delay_ms(100);
}
delay_ms(1000);
beep(1200, 220);
}
void check_ADC(void)
{
unsigned int wt;
/*
We gebruiken PC5 als analoge ingang.
Deze is via een pull-up weerstand verbonden met Vcc.
6 toetsen trekken - ieder via hun eigen specifieke weerstand -
de spanning op PC5 naar beneden.
Dus, als het resultaat van convertanalog() kleiner is dan
pakweg 950 (1023 is de maximum), kunnen we er van uitgaan
dat iemand een toets indrukte.
Voor alle zekerheid wachten we even, en testen nogmaals.
*/
/* Wacht enkele mSec */
delay_ms(100);
wt = 500;
while (convertanalog() < 950) {
/* Nu zijn we zeker: er is een knop ingedrukt.
De pull-up weerstand bedraagt 4k7.
De toets-weerstanden zijn: 47k, 15k, 8k2, 4k7, 1k5, 100R en 27R voor de noodstop
Dat levert de volgende metingen op:
930, 779, 650, 511, 247, 21
De grensovergangen hiertussen zijn:
854, 714, 580, 379, 134
*/
if (ADC_in > Uplus) {
if (Spanning < 0xFFFE) {
Spanning += 2;
wr_spanning(Spanning);
} else {
return;
}
} else if (ADC_in > UV1plus) {
if (Spanning < (0xFFFE - V1)) {
Spanning += V1;
wr_spanning(Spanning);
} else {
Spanning = 0xFFFE;
wr_spanning(Spanning);
return;
}
} else if (ADC_in > UV5plus) {
if (Spanning < (0xFFFE - V5)) {
Spanning += V5;
wr_spanning(Spanning);
// Als we de spanning met 5Volt verhogen, gaan we wat omzichtiger te werk. Even te lang
// de knop indrukken als we een TTL-circuit met 5V willen voeden, kan nare gevolgen hebben!
delay_ms(800);
} else {
Spanning = 0xFFFE;
wr_spanning(Spanning);
return;
}
} else if (ADC_in > Umin) {
if (Spanning > 1) {
Spanning -= 2;
wr_spanning(Spanning);
} else {
return;
}
} else if (ADC_in > UV1min) {
if (Spanning > V1) {
Spanning -= V1;
wr_spanning(Spanning);
} else {
Spanning = 0;
wr_spanning(Spanning);
return;
}
} else {
if (Spanning > V5) {
Spanning -= V5;
wr_spanning(Spanning);
} else {
Spanning = 0;
wr_spanning(Spanning);
return;
}
}
if (wt > 1) {
delay_ms(wt);
wt *= 9;
wt /= 10;
} else {
delay_ms(1);
}
}
}
void check_RS232(void)
{
/*
Geldige opdrachten:
u=x of s=x zet de spanning op x
u=+ u=- vermeerder of verminder de spanning met 1mV
u=? toon de ingestelde spanning
*/
if (strncmp(uart_outbuf, "Who", 3) == 0) {
uart_sendstr_P("SpStuur\n");
} else if (uart_outbuf[1] != '=') {
reply(0);
} else {
val = &(uart_outbuf[2]);
status = 0;
switch (uart_outbuf[0]) {
case 'u':
case 'U':
case 's':
case 'S':
if ((Spanning < 0xFFFD) && (*val == '+')) { // Spanning verhogen met 1 mV
Spanning += 2;
wr_spanning(Spanning);
status = 3;
} else if ((Spanning > 1) && (*val == '-')) { // Spanning verlagen met 1 mV
Spanning--;
wr_spanning(Spanning);
status = 3;
} else if ((*val >= '0') && (*val <= '9')) { // De opgegeven spanning instellen
Spanning = my_atoi(val);
if (Spanning > 0xFFFE) {
Spanning = 0xFFFE;
}
wr_spanning(Spanning);
status = 2;
}
u2ascii(Spanning);
uart_sendstr(asciistring); // De ingestelde spanning over de seriele lijn versturen
uart_sendchar('\n');
status = 2;
}
reply(status);
}
}
int main(void)
{
init();
while (1) {
if (convertanalog() < 950) { // Toetsen testen
check_ADC();
}
if (uart_rx_linecomplete == 1) { // RS232 testen
check_RS232();
uart_rx_linecomplete = 0;
}
}
}