Blame |
Last modification |
View Log
| RSS feed
/*****************************************************************************
* Copyright (C) 2009 Peter "woggle" Mack, mac@denich.net *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
*****************************************************************************/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <string.h>
#include <util/twi.h>
#include "main.h"
#include "motortest.h"
#include "lcd.h"
#include "usart.h"
#include "timer.h"
uint8_t m
;
#define SCL_FREQ 200000L
#define I2C_STATE_TX_ADDRESS 0
#define I2C_STATE_TX_DATA 1
#define I2C_STATE_TX_STOP 2
#define I2C_STATE_RX_ADDRESS 3
#define I2C_STATE_RX_1BYTE 4
#define I2C_STATE_RX_2BYTE 5
volatile uint8_t i2c_state
;
volatile uint8_t motor_addr
= 0;
//*****************************************************************************
//
void I2C_Init
(void)
{
uint8_t sreg
= SREG
;
cli
();
DDRC
&= ~
(1<<DDC1
); // SDA is input
DDRC
|= (1<<DDC0
); // SCL is output
PORTC
|= (1<<PORTC0
)|(1<<PORTC1
); // pull up SDA and SCL
// prescaler 1 (TWPS1 = 0, TWPS0 = 0)
TWSR
&= ~
((1<<TWPS1
)|(1<<TWPS0
));
TWBR
= ((F_CPU
/SCL_FREQ
)-16)/2;
i2c_state
= I2C_STATE_TX_ADDRESS
;
SREG
= sreg
;
}
//*****************************************************************************
//
void I2C_Start
(uint8_t start_state
)
{
i2c_state
= start_state
;
// generate start condition and enable interrupts
TWCR
= (1<<TWINT
) | (1<<TWSTA
) | (1<<TWEN
) | (1<<TWIE
);
}
//*****************************************************************************
//
void I2C_Stop
(uint8_t start_state
)
{
i2c_state
= start_state
;
// generate stop condition and disable interrupt
TWCR
= (1<<TWINT
) | (1<<TWSTO
) | (1<<TWEN
);
}
//*****************************************************************************
//
void I2C_WriteByte
(int8_t b
)
{
TWDR
= b
;
// clear interrupt flag (TWINT = 1)
// enable i2c bus (TWEN = 1)
// enable interrupt (TWIE = 1)
TWCR
= (1<<TWINT
) | (1<<TWEN
) | (1<<TWIE
);
}
//*****************************************************************************
//
void I2C_ReceiveByte
(void)
{
TWCR
= (1<<TWINT
) | (1<<TWEN
) | (1<<TWIE
) | (1<<TWEA
);
}
//*****************************************************************************
//
void I2C_ReceiveLastByte
(void)
{
TWCR
= (1<<TWINT
) | (1<<TWEN
) | (1<<TWIE
);
}
//*****************************************************************************
//
ISR
(TWI_vect
)
{
int8_t mrCurrent
;
int8_t mrMaxpwm
;
switch (i2c_state
++)
{
// TWI Master Transmit
case I2C_STATE_TX_ADDRESS
:
I2C_WriteByte
(0x52 + (motor_addr
* 2) ); // select slave adress in tx mode
break;
case I2C_STATE_TX_DATA
:
I2C_WriteByte
(m
);
break;
case I2C_STATE_TX_STOP
:
if(TWSR
== TW_MT_DATA_NACK
) // Data transmitted, NACK received
{
// error occured
}
I2C_Stop
(I2C_STATE_TX_ADDRESS
);
I2C_Start
(I2C_STATE_RX_ADDRESS
); // Repeated start -> switch slave or switch Master Transmit -> Master Receive
break;
// Master Receive Data
case I2C_STATE_RX_ADDRESS
:
I2C_WriteByte
(0x53 + (motor_addr
* 2) ); // select slave adress in rx mode
if(TWSR
!= TW_MR_SLA_ACK
) // SLA+R transmitted, if not ACK received
{ // no response from the addressed slave received
I2C_Stop
(I2C_STATE_TX_ADDRESS
);
}
else
{
I2C_ReceiveByte
(); //Transmit 1st byte
}
break;
case I2C_STATE_RX_1BYTE
: //Read 1st byte and transmit 2nd Byte
mrCurrent
= TWDR
;
I2C_ReceiveLastByte
(); // nack
break;
case I2C_STATE_RX_2BYTE
:
//Read 2nd byte
mrMaxpwm
= TWDR
;;
I2C_Stop
(I2C_STATE_TX_ADDRESS
);
break;
default:
I2C_Stop
(I2C_STATE_TX_ADDRESS
);
break;
}
}
//*****************************************************************************
//
void motor_i2c
(void)
{
uint8_t blc
= 0;
lcd_cls
();
m
= 0;
lcd_printp
(PSTR
("I2C Motor Test"), 0);
lcd_printpns_at
(0, 7, PSTR
("dec inc Exit Off"), 0);
lcd_printp
(PSTR
("BLC #"), 0);
do
{
if ((get_key_press
(1 << KEY_PLUS
) || get_key_rpt
(1 << KEY_PLUS
)) && (m
< 254))
{
m
++;
}
if ((get_key_press
(1 << KEY_MINUS
) || get_key_rpt
(1 << KEY_MINUS
)) && (m
> 0))
{
lcd_frect
(GX
, GY
, (m
* 108) / 255, 10, 0);
m
--;
}
if (get_key_press
(1 << KEY_ENTER
))
{
lcd_frect
(GX
, GY
, (m
* 108) / 255, 10, 0);
m
= 0;
}
}
while (!get_key_press
(1 << KEY_ESC
));
// switch all engines off at exit !
}
//*****************************************************************************
//
void motor
(uint8_t m
)
{
memset (buffer
, m
, 16);
#if 0
buffer
[0] = m
; // 0
buffer
[1] = m
; // 1
buffer
[2] = m
; // 2
buffer
[3] = m
; // 3
buffer
[4] = m
; // 4
buffer
[5] = m
; // 5
buffer
[6] = m
; // 6
buffer
[7] = m
; // 7
buffer
[8] = m
; // 8
buffer
[9] = m
; // 9
buffer
[10] = m
; // 10
buffer
[11] = m
; // 11
buffer
[12] = m
; // 12
buffer
[13] = m
; // 13
buffer
[14] = m
; // 14
buffer
[15] = m
; // 15
#endif
SendOutData
('t', ADDRESS_FC
, 1, buffer
, 16);
// hier könnte man noch eine I2C-Ausgabe einbauen...
lcd_frect
(GX
, GY
, (m
* 108) / 255, 10, 1);
write_ndigit_number_u
(MX
, MY
, m
, 3, 0);
}
//*****************************************************************************
//
void motor_test
(void)
{
//uint8_t m;
lcd_cls
();
m
= 0;
lcd_printp
(PSTR
("Motor Test"), 0);
lcd_printpns_at
(0, 7, PSTR
("dec inc Exit Off"), 0);
if (hardware
== NC
&& current_hardware
== NC
)
{
SwitchToFC
();
}
motor
(m
);
do
{
if ((get_key_press
(1 << KEY_PLUS
) || get_key_rpt
(1 << KEY_PLUS
)) && (m
< 254))
{
m
++;
}
if ((get_key_press
(1 << KEY_MINUS
) || get_key_rpt
(1 << KEY_MINUS
)) && (m
> 0))
{
lcd_frect
(GX
, GY
, (m
* 108) / 255, 10, 0);
m
--;
}
if (get_key_press
(1 << KEY_ENTER
))
{
lcd_frect
(GX
, GY
, (m
* 108) / 255, 10, 0);
m
= 0;
}
motor
(m
);
}
while (!get_key_press
(1 << KEY_ESC
));
// switch all engines off at exit !
motor
(0);
}