/***********************************************************************
par Silicium628
derniere mise à jour 16 sept 2014
========================================================================
Selecteur de la base de temps pour oscilloscope HAMEG HM303
ATmega8
-Affichage LCD 4 x 16 caractères
************************************************************************/
// #define F_CPU 16000000
#define F_CPU 3276800
/**
Utilisation de l'oscillateur RC (R=1k - C=22nF externes) -> fréquence volontairement très basse (40kHz environ mesuré au fréquencemètre)
pour éviter les perturbations HF parasites au sein de l'oscilloscope où sera situé le montage.
PROGRAMMER LES FUSES pour External RC oscillator gamme 0.9MHz - 3MHz
ôter le C de 22nF pour accélérer l'horloge avant toute opération de programmation.
**/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <math.h>
#define pin_a0 0b01000000 // sur port D
#define pin_a1 0b10000000 // sur port D
#define pin_a2 0b00000001 // sur port c
#define pin_a3 0b00000010 // sur port c
#define pin_a4 0b00000100 // sur port c
#define pin_k0 0b00000010 // sur port D
#define pin_k1 0b00001000 // sur port D
#define pin_k2 0b00010000 // sur port D
#define pin_k3 0b00100000 // sur port D
#define pin_A 0b00010000 // sur port B
#define pin_B 0b00000100 // sur port B
#define pin_D 0b00000010 // sur port B
#define pin_E 0b00000001 // sur port B
#define pin_F 0b00100000 // sur port C
#define pin_G 0b00010000 // sur port C
#define pin_H 0b00001000 // sur port C
char * version = "1.2";
uint8_t pos_bouton; // position du curseur (pour affichage)
uint8_t etat;
uint16_t compteur1;
// Le tableau suivant définit l'état des 7 transistors de sortie (le bit 5 est toujours à 1, c'est GND) en fonction des 20 positions du sélecteur rotatif
uint8_t tabl_out[20] = {
0b01100001,
0b01100000,
0b11100010,
0b11100001,
0b11100000,
0b01100110,
0b01100101,
0b01100100,
0b10110010,
0b10110001,
0b10110000,
0b00110110,
0b00110101,
0b00110100,
0b10100010,
0b10100001,
0b10100000,
0b00100110,
0b00101101,
0b00101100 };
// portB xxxAxBDE
// portC xxFGHxxx
// tabl ABCDEFGH
void out_commande(uint8_t n)
{
//n est le numéro de la ligne à envoyer(1 ligne pour chacune de 20 positions du bouton rotatif)
// n=0..19
PORTB &= 0b11101000; // RAZ des bits 0,1,2,4
PORTB = PORTB | ((tabl_out[n] & 0b00011000) >> 3) | ((tabl_out[n] & 0b01000000) >> 4 ) | ((tabl_out[n] & 0b10000000) >> 3 );
PORTC &= 0b11000111; // RAZ des bits 3,4,5
PORTC = PORTC | ((tabl_out[n] & 0b00000111) << 3 );
}
void init_ports (void) // ports perso
// 0 = entree, 1=sortie ; les 1 sur les pins en entrees activent les R de Pull Up (tirage à VCC)
{
DDRB |= 0b11111111;
PORTB = 0b00001000;
DDRC = 0b11111111;
PORTC = 0b00000000;
DDRD = 0b11111010; // portD[0] entrée codeur_ROT ; portD[2] entrée INT0
PORTD = 0b00000101;
}
void InitINTs (void)
{
GICR |= 0b01000000; // gere les INTs - bit6 ->INT0 request - voir page 67 du pdf
MCUCR |= 0b00000010; // The falling edge of INT0 generates an interrupt request. p:67 du pdf
}
void init_variables(void)
{
pos_bouton = 9;
}
/*
void test_codeur_rot()
{
// pour test des états (diffèrent suivant modèles) du codeur rotatif pas à pas code gray
// le mien est toujours à 11 en position stable
// dans le sens CW il fait 11->01->00->10->11
// et par conséquent dans le sens CCW il fait 11->10->00->01->11
lcd_clrscr();
while (1)
{
code_rot = PIND & 0b00000011;
lcd_gotoxy(0,0);
lcd_aff_bin (code_rot, 2);
_delay_ms(10);
}
}
*/
void eteintToutesLesAnodes()
{
PORTD = PORTD | pin_a0 | pin_a1;
PORTC = PORTC | pin_a2 | pin_a3 | pin_a4;
}
void eteintToutesLesCathodes()
{
PORTD = PORTD & ~pin_k0 & ~pin_k1 & ~pin_k2 & ~pin_k3 ;
}
void allume1led()
{
uint8_t a, k;
a = pos_bouton %5;
k=pos_bouton / 5;
eteintToutesLesCathodes();
// alim les cathodes concernées
if (k==0) { PORTD = PORTD | pin_k0; }
if (k==1) { PORTD = PORTD | pin_k1; }
if (k==2) { PORTD = PORTD | pin_k2; }
if (k==3) { PORTD = PORTD | pin_k3; }
eteintToutesLesAnodes();
// alim toutes les anodes concernées
if (a==0) { PORTD = PORTD & ~pin_a0; }
if (a==1) { PORTD = PORTD & ~pin_a1; }
if (a==2) { PORTC = PORTC & ~pin_a2; }
if (a==3) { PORTC = PORTC & ~pin_a3; }
if (a==4) { PORTC = PORTC & ~pin_a4; }
}
/***********************************************************************
// traitement du codeur_rot()
// codeur incrémental code Gray avec en plus fonction bouton poussoir
// le codeur rotatif utilisé est toujours à 11 en position stable
// dans le sens CW il fait 11->01->00->10->11
// et par conséquent dans le sens CCW il fait 11->10->00->01->11
// 11
// 01
// 00
// 10
// 11
// il suffit de connecter un bit sur le pin INT0 (PD2) et de déclencher l'INT sur front descendant (passage de 0 à 1)
// cette INT lira alors l'état de l'autre bit (connecté à PD0 par exemple). Cet état diffère suivant le sens de rotation
************************************************************************/
ISR(BADISR_vect)
{
// évite de planter si une int est enable et pas de procedure associée écrite (ce qui fait reseter l'ATmega)
}
ISR (INT0_vect)
{
//interruption sur front descendant sur l'entree Int0
// declenchee par la rotation du codeur_ROT
etat = PIND & 0b00000001;
if (etat == 0)
{
if (pos_bouton < 19) {pos_bouton++ ;}
}
else
{
if (pos_bouton > 0) {pos_bouton--;}
}
out_commande(pos_bouton);
allume1led();
// _delay_ms(1);
}
int main (void)
{
init_variables();
init_ports();
InitINTs();
_delay_ms(10);
sei(); // enable interruptions
out_commande(pos_bouton);
allume1led();
_delay_ms(1);
while (1) {;}
}