# (GNU make, BSD make, SysV make)
-MCU = atmega1284p
+MCU = atmega324p
FORMAT = ihex
TARGET = main
SRC = $(TARGET).c lcdlib/lcd-color-graphic.c lcdlib/font.c \
lcdlib/Fonts/digits_24px.c lcdlib/Fonts/digits_32px.c lcdlib/Fonts/font_proportional_16px.c \
- lcdlib/Fonts/font_proportional_8px.c lcdlib/Fonts/symbols_16px.c
+ lcdlib/Fonts/font_proportional_8px.c lcdlib/Fonts/symbols_16px.c \
+ uart.c eeprom.c tempmeas.c keys.c
ASRC =
OPT = 2
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
-SIZE = avr-size
+SIZE = ~/bin/avr-size
NM = avr-nm
AVRDUDE = avrdude
REMOVE = rm -f
# Default target.
all: build
-build: elf hex eep lss
+build: elf hex eep lss size
elf: $(TARGET).elf
hex: $(TARGET).hex
size:
- $(SIZE) $(TARGET).elf
+ $(SIZE) -C --mcu=$(MCU) $(TARGET).elf
#-C --mcu=$(MCU)
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
COFFCONVERT=$(OBJCOPY) --debugging \
--- /dev/null
+#include <avr/eeprom.h>
+
+
+void eeprom_write(uint8_t addr, uint16_t value) {
+ eeprom_update_word((uint16_t*)(uint16_t)(addr*2),value);
+ }
+
+uint16_t eeprom_read(uint8_t addr) {
+ return eeprom_read_word((uint16_t*)(uint16_t)(addr*2));
+ }
--- /dev/null
+#include "main.h"
+
+
+void scan_keys(void){
+ static uint8_t key_state_m0, key_state_m1;
+ uint8_t key_state = ~(KEYPIN) & ACTIVE_KEYS_MASK;
+ // -------has state changed?---- --- is key pressed now? ---
+ keys_pressed |= (key_state_m0 ^ key_state_m1) & key_state;
+
+ key_state_m1 = key_state_m0;
+ key_state_m0 = key_state;
+}
+
+
+
+uint8_t key_was_pressed(uint8_t key_mask){
+ // was one of the keys defined by key mask pressed?
+ uint8_t result = keys_pressed & key_mask;
+ keys_pressed &= ~(key_mask);
+ return result;
+}
+
\ No newline at end of file
* Background is used as background, e.g. when writing fonts.
*/
-color_t foreground = {.red=0x1F, .green=0x3F, .blue=0x1F};
-color_t background = {.red=0, .green=0, .blue=0};
+color_t foreground;
+color_t background;
/******************************************************************************
LCD_SET_PIN_DIRECTIONS(); //set outputs
_delay_ms(1);
LCD_INIT_SPI(); //Initialize SPI Interface
+ LCD_UNSELECT();
_delay_ms(50);
LCD_RESET_ON(); //Apply Reset to the Display Controller
_delay_ms(100);
LCD_SELECT(); //Switches chip select on
lcd_command(LCD_SLEEP_OUT); //Wake up LCD
_delay_ms(70);
+ lcd_command_1(LCD_COLOR_MODE,LCD_16BIT);
return;
}
/******************************************************************************
* Sends a command to the display
*/
-inline void lcd_command(uint8_t c) {
- spi_wait_for_idle();
- LCD_CMD();
- spi_write(c);
- }
+// inline void lcd_command(uint8_t c) {
+// spi_wait_for_idle();
+// LCD_CMD();
+// spi_write(c);
+// }
+
+
+/******************************************************************************
+ * Sends a data word to the display
+ */
+// inline void lcd_data(uint8_t c) {
+// spi_wait_for_idle();
+// LCD_DATA();
+// spi_write(c);
+// }
+
/******************************************************************************
* Sends a command with one argument
lcd_command(c);
lcd_data(data);
}
-
-/******************************************************************************
- * Sends a data word to the display
- */
-inline void lcd_data(uint8_t c) {
- spi_wait_for_idle();
- LCD_DATA();
- spi_write(c);
-}
-
-
/******************************************************************************
* Stores the main drawing color for later use
*/
inline void lcd_set_foreground(uint8_t r, uint8_t g, uint8_t b) {
- foreground.red = r;
- foreground.green = g;
- foreground.blue = b;
+ uint16_t t = r<<11 | g<<5 | b;
+ foreground.c1 = t>>8;
+ foreground.c2 = t;
+ }
+inline void lcd_use_foreground(color_t color) {
+ foreground.c1 = color.c1;
+ foreground.c2 = color.c2;
}
* Stores the background color for later use
*/
inline void lcd_set_background(uint8_t r, uint8_t g, uint8_t b) {
- background.red = r;
- background.green = g;
- background.blue = b;
+ uint16_t t = r<<11 | g<<5 | b;
+ background.c1 = t>>8;
+ background.c2 = t;
}
-
+inline void lcd_use_background(color_t color) {
+ background.c1 = color.c1;
+ background.c2 = color.c2;
+ }
+
+/******************************************************************************
+ * Stores the background color for later use
+ */
+inline void lcd_set_color(color_t* color, uint8_t r, uint8_t g, uint8_t b) {
+ uint16_t t = r<<11 | g<<5 | b;
+ color->c1 = t>>8;
+ color->c2 = t;
+ }
+
/******************************************************************************
* Sets the column range used for the next write operation
inline void lcd_set_column(uint16_t start, uint16_t end) {
lcd_command(LCD_SET_COLUMN);
lcd_data(start >> 8);
- lcd_data(start);
- lcd_data(end >> 8);
- lcd_data(end);
+ lcd_data_cont(start);
+ lcd_data_cont(end >> 8);
+ lcd_data_cont(end);
}
-
+inline void lcd_set_column_short(uint16_t start) {
+ lcd_command(LCD_SET_COLUMN);
+ lcd_data(start >> 8);
+ lcd_data_cont(start);
+ }
+
/******************************************************************************
* Sets the page range used for the next write operation
*/
inline void lcd_set_page(uint16_t start, uint16_t end) {
lcd_command(LCD_SET_PAGE);
lcd_data(start >> 8);
- lcd_data(start);
- lcd_data(end >> 8);
- lcd_data(end);
+ lcd_data_cont(start);
+ lcd_data_cont(end >> 8);
+ lcd_data_cont(end);
+ }
+inline void lcd_set_page_short(uint16_t start) {
+ lcd_command(LCD_SET_PAGE);
+ lcd_data(start >> 8);
+ lcd_data_cont(start);
}
/******************************************************************************
* Writes a pixel to the display using 16 Bit color mode
*/
inline void lcd_send_pixel(color_t c) {
- lcd_data((c.red<<3) | (c.green>>3));
- lcd_data((c.green<<5) | c.blue);
+ lcd_data(c.c1);
+ lcd_data_cont(c.c2);
}
/******************************************************************************
lcd_send_pixel(foreground);
}
-
+/******************************************************************************
+ * Sets a pixel at a given position
+ */
+inline void lcd_set_pixel_col_xy(uint16_t column, uint16_t page, color_t col) {
+ lcd_set_page_short(page);
+ lcd_set_column_short(column);
+ lcd_command(LCD_WRITE_MEM);
+ lcd_send_pixel(col);
+ }
+
/******************************************************************************
* This function sets an area of the screen to a given color
* col0 - left edge of the area
uint16_t lcd_inc_page(int16_t s) {
uint16_t p = lcd_current_page;
p += s;
- if (p > LCD_HEIGHT/8)
+ if (p > LCD_HEIGHT)
p = 0;
lcd_current_page = p;
* Moves the cursor relative to the current position
* pages - number of pages to move
* columns - number of columns to move
+ * for use with the font library only
*/
void lcd_move_xy(int16_t pages, int16_t columns) {
- lcd_moveto_xy(lcd_inc_page(pages),lcd_inc_column(columns));
+ lcd_moveto_xy(lcd_inc_page(pages*8),lcd_inc_column(columns));
}
/******************************************************************************
* Takes a vertical byte from the font generator and prints it on the display
* b - Bit pattern to display
+ * c - continue writing in same page
*/
-void lcd_write_font_byte(uint8_t b) {
- lcd_set_page(8*lcd_current_page,8*lcd_current_page+8);
+void lcd_write_font_byte(uint8_t b, uint8_t c) {
+ if(!c) {
+ lcd_set_page(lcd_current_page,lcd_current_page+8);
+ }
lcd_set_column(lcd_current_column,lcd_current_column);
lcd_command(LCD_WRITE_MEM);
for(uint8_t i=0;i<8;i++) {
}
lcd_inc_column(1);
}
+
+
+/******************************************************************************
+ * Draws a line according to Bresenham (from wikipedia)
+ */
+void lcd_draw_line(uint16_t x0, uint16_t x1, uint16_t y0, uint16_t y1) {
+ int16_t dx = abs(x1-x0);
+ int16_t sx = x0<x1 ? 1 : -1;
+ int16_t dy = -abs(y1-y0);
+ int16_t sy = y0<y1 ? 1 : -1;
+ int16_t err = dx+dy, e2; /* error value e_xy */
+
+ for(;;){ /* loop */
+ lcd_set_pixel_xy(x0,y0);
+ if (x0==x1 && y0==y1) break;
+ e2 = 2*err;
+ if (e2 > dy) { err += dy; x0 += sx; } /* e_xy+e_x > 0 */
+ if (e2 < dx) { err += dx; y0 += sy; } /* e_xy+e_y < 0 */
+ }
+ }
+
\ No newline at end of file
#include <string.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
-
+#include <stdlib.h>
/*****************************************************************************
* BEGIN CONFIG BLOCK
*****************************************************************************/
-#define LCD_WIDTH 240
-#define LCD_HEIGHT 320
+#define LCD_WIDTH 320
+#define LCD_HEIGHT 240
//Should chip select (CS) be used?
#define LCD_USE_CHIPSELECT 1
//Color struct - no bit fields are used for better performance (i.e. bit shifts
//can be done while waiting for SPI, not while preparing to write the pixel)
typedef struct {
- uint8_t red;
- uint8_t green;
- uint8_t blue;
+ uint8_t c1;
+ uint8_t c2;
} color_t;
+#define lcd_data(c) spi_wait_for_idle();LCD_DATA();spi_write(c)
+#define lcd_data_cont(c) spi_wait_for_idle();spi_write(c)
+#define lcd_command(c) spi_wait_for_idle();LCD_CMD();spi_write(c)
+
+ color_t foreground;
+ color_t background;
+
/*****************************************************************************
* Public Functions
*****************************************************************************/
void lcd_init(void);
//write data word or command to the LCD
- void lcd_data (uint8_t data);
- void lcd_command (uint8_t cmd);
+// void lcd_data (uint8_t data) ;
+// void lcd_command (uint8_t cmd);
void lcd_command_1 (uint8_t cmd, uint8_t data);
//Set the drawing and background colors
void lcd_set_foreground(uint8_t r, uint8_t g, uint8_t b);
void lcd_set_background(uint8_t r, uint8_t g, uint8_t b);
+ void lcd_set_color(color_t* color, uint8_t r, uint8_t g, uint8_t b);
+ void lcd_use_foreground(color_t color);
+ void lcd_use_background(color_t color);
//set display area for next write accesses
void lcd_set_page(uint16_t start, uint16_t end);
//Set a pixel at a given location to the foreground color
void lcd_set_pixel_xy(uint16_t column, uint16_t page);
+ void lcd_set_pixel_col_xy(uint16_t column, uint16_t page, color_t col);
//Set an area to the background color
void lcd_set_area_xy(uint16_t col0, uint16_t col1, uint16_t page0, uint16_t page1);
-
+//Draw a straight line
+ void lcd_draw_line(uint16_t x1, uint16_t x2, uint16_t y1, uint16_t y2);
//Text functions are included in font.c / font.h
extern uint16_t lcd_current_column;
static inline uint16_t lcd_get_position_page(void) {return lcd_current_page;}
static inline uint16_t lcd_get_position_column(void) {return lcd_current_column;}
- void lcd_write_font_byte(uint8_t b);
+ void lcd_write_font_byte(uint8_t b, uint8_t c);
/*****************************************************************************
-
-
-#include <avr/interrupt.h>
-#include <util/delay.h>
-#include <avr/io.h>
-#include <avr/eeprom.h>
-#include <string.h>
-
#include "main.h"
#include "lcdlib/lcd-color-graphic.h"
#include "lcdlib/font.h"
+volatile uint16_t control_reg;
+volatile uint16_t time;
+volatile uint8_t keys_pressed = 0b00000000;
+volatile uint8_t next_step = 0;
+
+volatile uint8_t measurement_active = 0;
+color_t col_background;
+color_t col_font;
+color_t col_title;
+struct calib_t calib_settings;
/******************
* Init USART for LCD
UCSR1B = (1 << TXEN1);
UCSR1C = (1 << UMSEL10) | (0 << UDORD1) | (0 << UCPHA1) | (0 << UCPOL1);
UBRR1L = 0;
- UBRR1H = 0;
+ UBRR1H = 0; //full speed
}
+/******************
+ * Read calibration from eeprom
+ *****************/
+void read_calib() {
+ for(uint8_t i=0; i< 8; i++) {
+ calib_settings.offset_res[i] = eeprom_read(i);
+ }
+ calib_settings.gain_res = eeprom_read(8);
+ }
+/******************
+ * Some stuff on the LCD
+ *****************/
+void lcd_design(void) {
+ lcd_set_color(&col_background,0x03,0x04,0x05);
+ lcd_set_color(&col_title, 0x1f,0x3f,0x08);
+ lcd_set_color(&col_font, 0x1f,0x3f,0x08);
+
+ lcd_use_background(col_background);
+ lcd_use_foreground(col_title);
+ lcd_set_area_xy(0, 0x13F, 0, 0xEF);
+
+ lcd_set_font(FONT_PROP_16,DOUBLE_SIZE|SPACING);
+ lcd_putstr_xy_P(PSTR("PT100 Reader"),0,0);
+
+ }
+
+void lcd_update(void) {
+ }
+
+
/******************
* Init all functions
*****************/
void init(void) {
+//CPU Regs
//Init ADC SPI
SPCR = (0 << SPIE) | (1 << SPE ) | (0 << DORD) | (1 << MSTR) | (0 << CPOL) | (0 << CPHA) | (0 << SPR0);
DIDR0 = 0x08; //PA3 is analog only
//Init UART
-
+ UCSR0B = (1 << RXCIE0) | (0 << TXCIE0) | (0 << UDRIE0) | (1 << RXEN0) | ( 1 << TXEN0); //udrie enabled on request
+ UBRR0 = 12; //38400baud
//GPIO
PORTD |= (0xc0); //pull-up for switches
DDRA |= (0x70); //select outputs
DDRC |= (0xc0); //outputs for Inhibit signals
+//Timer0: 2ms interrupts
+ TCCR0A = (2 << WGM00); //CTC
+ TCCR0B = (3 << CS00); //fcpu/64
+ OCR0A = 249;
+ TIMSK0 = (1 << OCF0A); //Interrupt on compare match
+
+//Timer1: 1s ticks to start measurement
+ TCCR1A = 0;
+ TCCR1B = (1 << WGM12) | ( 4 << CS10); //CTC, fcpu/256
+ TIMSK1 = (1 << OCIE1A);
+ OCR1A = 31250;
+
+ lcd_init();
+ lcd_command_1(LCD_MIRROR, LCD_BGR | LCD_FLIP_XY);
+ lcd_command(LCD_ON);
+
+ read_calib();
+ lcd_design();
+ sei();
+}
+
+
+/**********************
+ * ADC finished conversion
+ *********************/
+ISR(ADC_vect) {
}
+/**********************
+ * 500 Hz ticks
+ *********************/
+ISR(TIMER0_COMPA_vect) {
+ time++;
+ next_step = 1;
+ }
+
+
+/**********************
+ * Second ticks
+ *********************/
+ISR(TIMER1_COMPA_vect) {
+ send_information();
+ measurement_active = 1;
+}
+
+
int main(void) {
init();
- lcd_init();
- while(1);
+ while(1) {
+ while(next_step==0);
+ next_step = 0;
+ if (measurement_active) {do_measurement_step();}
+ if (time == 40) {lcd_update();}
+ if(key_was_pressed(1<<KEY_1)) {}
+ if(key_was_pressed(1<<KEY_2)) {}
+
+ };
return 0;
}
\ No newline at end of file
+#include <avr/interrupt.h>
+#include <util/delay.h>
+#include <avr/io.h>
+#include <avr/eeprom.h>
+#include <string.h>
-
-#define FIRMWARE_VERSION 0x01
+#define FIRMWARE_VERSION 0x0001
#define UDORD1 2
#define UCPHA1 1
#define ADC_SELECT() PORTB &= ~(1<< PB4)
#define ADC_UNSELECT() PORTB |= (1<< PB4)
-#define LED1_ON() PORTB |= (1<< PB1)
+#define LED1_ON() PORTB |= (1<< PB1) //while measurement ongoing
#define LED1_OFF() PORTB &= ~(1<< PB1)
-#define LED2_ON() PORTB |= (1<< PB0)
+#define LED2_ON() PORTB |= (1<< PB0) //while transmitting data
#define LED2_OFF() PORTB &= ~(1<< PB0)
-#define SWITCH1() ((PIND>>PD6)&1)
-#define SWITCH2() ((PIND>>PD7)&1)
+
+#define KEYPORT PORTD
+#define KEYDDR DDRD
+#define KEYPIN PIND
+#define KEY_1 PD6
+#define KEY_2 PD7
+#define ACTIVE_KEYS_MASK (1<<KEY_1|1<<KEY_2)
+
#define SELECT(i) (PORTA = (PORTA & 0x8F) | (((i)&0x7) << 4)
#define MUX_C_ON() PORTC &= ~(1<<PC7)
#define MUX_C_OFF() PORTC |= (1<<PC7)
#define MUX_T_ON() PORTC &= ~(1<<PC6)
-#define MUX_T_OFF() PORTC |= (1<<PC6)
\ No newline at end of file
+#define MUX_T_OFF() PORTC |= (1<<PC6)
+
+
+void eeprom_write(uint8_t addr, uint8_t value);
+uint16_t eeprom_read(uint8_t addr);
+
+void send_answer_hex(uint8_t type, uint8_t chan, uint32_t v);
+void send_information(void);
+void read_calib(void);
+
+uint8_t key_was_pressed(uint8_t key_mask);
+
+void do_measurement_step(void);
+
+extern volatile uint16_t control_reg;
+extern volatile uint8_t keys_pressed;
+extern uint8_t connected_sensors;
+extern volatile uint16_t time;
+extern volatile uint8_t measurement_active;
+
+struct calib_t {
+ uint16_t offset_res[8];
+ uint16_t gain_res;
+ };
--- /dev/null
+#include "main.h"
+
+
+uint8_t connected_sensors = 0x1a;
+
+//measurement_active gets set once per second
+//do_measurement_step is called once every 2ms by main as long as measurement_active is set.
+//'time' gives the number of the current step
+//when done, set measurement_active to 0
+
+//calibration data is in 'calib_settings'
+
+//Step / TODO:
+//0 select channel
+//1 start internal ADC for presence
+//1 start ADC conversion
+//2 unselect channel
+//2 read ADC measurement & presence
+//2 do calibration
+//2 send information
+//3 sleep
+//... repeat 8 times
+//32 read ADC temperature as 9th channel
+//33 send ADC temperature, finished
+
+void do_measurement_step(void) {
+ if(time == 0) {
+ LED1_ON();
+ }
+ else if(time == 34) {
+ measurement_active = 0;
+ LED1_OFF();
+ }
+ }
--- /dev/null
+
+//all data is in hex format
+//b: Board ID --
+ //last board in chain is 0. b gets decreased by 1 in every uC, command is executed if b is 0. values 0..9
+ //answers: message is started with b=0, increased with every step
+//c: Channel
+
+//10 words send for each measurement:
+//ATbcXXXXXX -- Measured temperature. value is temperature in mK
+//ATb800XXXX -- Temperature given by ADC
+//AIb0FFFFCC -- Firmware version & connected channels (bitmask) in last byte
+
+//Commands sent by user
+//WEb0AAXXXX -- write int16 to eeprom at address AA*2
+//WRb0000000 -- reload eeprom data
+//WCb000XXXX -- control register, t.b.d.
+
+#include "main.h"
+
+#define TX_BUSY() (txcnt != 0)
+#define STARTTX(i) txcnt = (i);UCSR0B |= (1<< UDRIE0)
+#define ISMYADDR() (rxbuf[1] == '0')
+
+uint8_t rxcnt = 0, txpoint = 0;
+volatile uint8_t txcnt = 0;
+uint8_t rxbuf[15];
+uint8_t txbuf[15];
+
+
+
+uint8_t nib_to_hex(uint32_t in, uint8_t nib) {
+ uint8_t t = (in >> (nib*4)) & 0xF;
+ if (t <= 9) {return t + 0x30;}
+ return t - 10 + 0x61;
+ }
+
+uint8_t hex_to_int(uint8_t h) { //assumes valid number
+ if (h < 0x40) return h-0x30;
+ if (h < 0x50) return h-0x41+10;
+ return h-0x61+10;
+ }
+
+uint8_t hex_to_byte(uint8_t* h) {
+ return hex_to_int(*h)*16 + hex_to_int(*(h+1));
+ }
+
+
+void forward_msg(uint8_t i) {
+ if(rxbuf[0] == 'A') rxbuf[1]++;
+ else rxbuf[1]--;
+ memcpy ((uint8_t*)txbuf,(uint8_t*)rxbuf,i);
+ STARTTX(i);
+ }
+
+
+uint8_t is_my_address(uint8_t s) {
+ if (ISMYADDR() && rxbuf[0] != 'A') {
+ return 1;
+ }
+ else {
+ forward_msg(s);
+ return 0;
+ }
+ }
+
+void send_answer_hex(uint8_t type, uint8_t chan, uint32_t v) {
+ sei();
+ while(TX_BUSY());
+ txbuf[0]='A';
+ txbuf[1]=type;
+ txbuf[2]='0';
+ txbuf[3]=chan;
+ txbuf[4]=nib_to_hex(v,5);
+ txbuf[5]=nib_to_hex(v,4);
+ txbuf[6]=nib_to_hex(v,3);
+ txbuf[7]=nib_to_hex(v,2);
+ txbuf[8]=nib_to_hex(v,1);
+ txbuf[9]=nib_to_hex(v,0);
+ txbuf[10]='\n';
+ STARTTX(11);
+ }
+
+
+void send_information(void) {
+ sei();
+ while(TX_BUSY());
+ txbuf[0]='A';
+ txbuf[1]='I';
+ txbuf[2]='0';
+ txbuf[3]='0';
+ txbuf[4]=nib_to_hex(FIRMWARE_VERSION,3);
+ txbuf[5]=nib_to_hex(FIRMWARE_VERSION,2);
+ txbuf[6]=nib_to_hex(FIRMWARE_VERSION,1);
+ txbuf[7]=nib_to_hex(FIRMWARE_VERSION,0);
+ txbuf[8]=nib_to_hex(connected_sensors,1);
+ txbuf[9]=nib_to_hex(connected_sensors,0);
+ txbuf[10]='\n';
+ STARTTX(11);
+ }
+
+/**********************
+ * UART received a byte
+ *********************/
+ISR(USART0_RX_vect) {
+ uint8_t buf = UDR1;
+ if (rxcnt != 0 || (buf == 'W' || buf == 'A')) {
+ rxbuf[rxcnt++] = buf;
+ }
+ if (buf == '\n' || buf == '\r') {
+ if(rxcnt == 11) {
+ if(rxbuf[0] == 'A') {forward_msg(rxcnt);}
+ else if(rxbuf[0] == 'W') {
+ if(rxbuf[1] == 'E') {
+ uint8_t addr = hex_to_byte(rxbuf+4);
+ eeprom_write(addr, (hex_to_byte(rxbuf+6)<<8) | hex_to_byte(rxbuf+8));
+ }
+ else if(rxbuf[1] == 'C') {
+ control_reg = (hex_to_byte(rxbuf+6)<<8) | hex_to_byte(rxbuf+8);
+ }
+ else if(rxbuf[1] == 'R') {
+ read_calib();
+ }
+ }
+ }
+ else {
+ rxcnt = 0;
+ }
+ }
+ if (rxcnt >= 12 || buf == '\n' || buf == '\r') {
+ rxcnt = 0;
+ }
+ }
+
+/**********************
+ * UART able to send a byte
+ *********************/
+ISR(USART0_UDRE_vect) {
+ LED2_ON();
+ UDR0 = txbuf[txpoint++];
+ if(--txcnt == 0 || txpoint > 12) {
+ txpoint = 0;
+ txcnt = 0;
+ UCSR0B &= ~(1<< UDRIE0);
+ LED2_OFF();
+ }
+ }
\ No newline at end of file