Last active
December 16, 2015 05:28
-
-
Save 3Nigma/5384236 to your computer and use it in GitHub Desktop.
Antetul (.h) și codul suport (.c) al librăriei avrps2m responsabilă de comunicațiile între un dispozitiv AVR și un mouse PS/2.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Modul de comunicatii AVR-PS/2 Mouse | |
* Copyright (c) 2013, Victor ADASCALITEI, admin@tuscale.ro | |
* | |
* Eliberez aceste surse sub licenta CC de tip BY-NC-SA 3.0 . Pentru mai multe informatii, va invit sa accesati | |
* urmatoarea adresa : http://creativecommons.org/licenses/by-nc-sa/3.0/ro/ . | |
*/ | |
#include <avr/interrupt.h> | |
#define F_CPU 9600000UL | |
#include <util/delay.h> | |
#include "ps2mouse.h" | |
/* regiune de variabile interne folosite de modul */ | |
uint8_t ps2m_nr_bit_linie = 0; | |
uint8_t ps2m_rx_octet = 0; | |
ps2m_dir_comunicatii ps2m_tip_actiune = PS2M_COM_MOUSE_LA_GAZDA; | |
uint8_t ps2m_paritate_date = 0; | |
volatile uint8_t ps2m_tx_octet = 0; | |
uint8_t ps2m_rx_octet_valid = 0; | |
volatile uint8_t ps2m_rx_date_primite = 0; | |
uint8_t ps2m_rezolutie_curenta = 4; | |
/* regiunea functiilor interne folosite de catre modul */ | |
void ps2m_trimite_la_mouse(uint8_t date) { | |
/* tragem linia de tact la '0' pentru cel putin 100us. | |
Preluam datele ce le dorim transmise catre mouse si pregatim rutina de intrerupere exterioara intre timp */ | |
DDRB |= PS2M_PIN_TACT; | |
ps2m_tx_octet = date; | |
ps2m_tip_actiune = PS2M_COM_GAZDA_LA_MOUSE; | |
ps2m_nr_bit_linie = 0; | |
_delay_us(100); | |
/* apoi tragem linia de date la acelasi potential '0' */ | |
DDRB |= PS2M_PIN_DATE; | |
/* eliberam linia ceasului (trece pe valoare '1') */ | |
DDRB &= ~PS2M_PIN_TACT; | |
/* asteptam ca mouseul sa inceapa sesiunea de comunicatii pentru a-i trimite datele */ | |
} | |
uint8_t ps2m_asteapta_date(void) { | |
while (ps2m_rx_date_primite == 0); | |
ps2m_rx_date_primite = 0; | |
return ps2m_rx_octet_valid; | |
} | |
extern ps2m_finalitate ps2m_citeste_configuratie(ps2m_st_stare *pdStare) { | |
ps2m_finalitate finalitateFct = PS2M_ESUAT; | |
ps2m_trimite_la_mouse(PS2M_COM_GAZDA_OBT_STARE); | |
if (ps2m_asteapta_date() == PS2M_COM_GAZDA_ACK) { | |
pdStare->bitiStare = ps2m_asteapta_date(); | |
pdStare->rezolutie = ps2m_asteapta_date(); | |
pdStare->rataEsantionare = ps2m_asteapta_date(); | |
finalitateFct = PS2M_OK; | |
} | |
return finalitateFct; | |
} | |
extern ps2m_finalitate ps2m_citeste_deplasamente(ps2m_st_date *pdDate) { | |
ps2m_finalitate finalitateFct = PS2M_ESUAT; | |
ps2m_trimite_la_mouse(PS2M_COM_GAZDA_OBT_DEPLASAMENTE); | |
if (ps2m_asteapta_date() == PS2M_COM_GAZDA_ACK) { | |
pdDate->bitiStare = ps2m_asteapta_date(); | |
pdDate->deplasareX = ps2m_asteapta_date(); | |
pdDate->deplasareY = ps2m_asteapta_date(); | |
finalitateFct = PS2M_OK; | |
} | |
return finalitateFct; | |
} | |
extern ps2m_finalitate ps2m_init(void) { | |
int8_t rezultatInitializare = PS2M_ESUAT; | |
/* introducem o mica intarziere pentru a lasa lucrurile sa se linisteasca (tensiuni si alte cele) */ | |
_delay_ms(100); | |
/* configuram linia de tact pentru a declansa întreruperi externe. | |
Pornim de la premiza ca mouseul va transmite primul date (pe front descrescator de tact) */ | |
MCUCR |= _BV(ISC01); | |
GIMSK |= _BV(INT0); | |
sei(); | |
/* pornim de la nivele cunoscute de tensiuni pe pini */ | |
PS2M_PIN_REGISTRU_SCRIERE &= ~(PS2M_PIN_DATE | PS2M_PIN_TACT); | |
/* verificam linia de comunicatii cu mouse-ul reinitializând-o */ | |
ps2m_trimite_la_mouse(PS2M_COM_GAZDA_RESET); | |
if (ps2m_asteapta_date() == PS2M_COM_GAZDA_ACK && | |
ps2m_asteapta_date() == PS2M_COM_GAZDA_BAT && ps2m_asteapta_date() == PS2M_COM_GAZDA_ID) { | |
/* totul în regula pâna aici. Activam modul de raportare a coordonatelor la cerere */ | |
ps2m_trimite_la_mouse(PS2M_COM_GAZDA_LA_CERERE); | |
if (ps2m_asteapta_date() == PS2M_COM_GAZDA_ACK) { | |
/* modul a fost selectat cu succes, iar initializarea s-a încheiat cu succes */ | |
rezultatInitializare = PS2M_OK; | |
} | |
} | |
return rezultatInitializare; | |
} | |
ISR(INT0_vect) { | |
/* avansam numarul de biti primiti/transmisi */ | |
ps2m_nr_bit_linie ++; | |
if (ps2m_tip_actiune == PS2M_COM_MOUSE_LA_GAZDA) { | |
/* regiunea de comunicatie de tip mouse-la-gazda. | |
Datele sunt valide pe frontul descrescator a semnalului de tact */ | |
if (ps2m_nr_bit_linie > 1 && ps2m_nr_bit_linie < 10) { | |
/* integram bitul valid de date în octetul curent. | |
Octetul este transmis cu bitul cel mai putin semnificativ (MSB) primul. */ | |
ps2m_rx_octet = ps2m_rx_octet >> 1; | |
if ((PS2M_PIN_REGISTRU_CITIRE & PS2M_PIN_DATE) != 0) { | |
ps2m_rx_octet |= 0x80; | |
} | |
} else if (ps2m_nr_bit_linie == 11) { | |
/* ignoram bitul de paritate ('1' -> daca octetul primit continea un numar par de biti '1' si '0' daca el continea un numar impar de biti '1') | |
si preluam datele pe bitul de 'stop' */ | |
ps2m_rx_octet_valid = ps2m_rx_octet; | |
ps2m_rx_date_primite = 1; | |
ps2m_nr_bit_linie = 0; | |
} | |
} else { | |
/* comunicatie de tip gazda-la-mouse | |
Se evalueaza pe frontul crescator a semnalului de tact */ | |
if (ps2m_nr_bit_linie < 9) { | |
/* trimitem cei 8 biti doriti in maniera "celui mai putin semnificativ bit" primul (MSB) */ | |
if ((ps2m_tx_octet & 0x01) == 0) { | |
PS2M_PIN_REGISTRU_DIRECTIE |= PS2M_PIN_DATE; | |
} else { | |
PS2M_PIN_REGISTRU_DIRECTIE &= ~PS2M_PIN_DATE; | |
ps2m_paritate_date ^= 1; | |
} | |
ps2m_tx_octet >>= 1; | |
} else if (ps2m_nr_bit_linie == 9){ | |
/* transmitem bitul de paritate ('1' pentru numar par de '1' transmisi si '0' in caz contrar) */ | |
if (ps2m_paritate_date == 0) { | |
PS2M_PIN_REGISTRU_DIRECTIE &= ~PS2M_PIN_DATE; | |
} else { | |
PS2M_PIN_REGISTRU_DIRECTIE |= PS2M_PIN_DATE; | |
} | |
} else if (ps2m_nr_bit_linie == 10){ | |
/* eliberam linia de date */ | |
PS2M_PIN_REGISTRU_DIRECTIE &= ~PS2M_PIN_DATE; | |
} else { | |
/* secventa de transmitere s-a incheiat, aducem sistemul intr-o stare de asteptare a raspunsului de la mouse */ | |
ps2m_tip_actiune = PS2M_COM_MOUSE_LA_GAZDA; | |
ps2m_nr_bit_linie = 0; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Modul de comunicatii AVR-PS/2 Mouse | |
* Copyright (c) 2013, Victor ADASCALITEI, admin@tuscale.ro | |
* | |
* Eliberez aceste surse sub licenta CC de tip BY-NC-SA 3.0 . Pentru mai multe informatii, va invit sa accesati | |
* urmatoarea adresa : http://creativecommons.org/licenses/by-nc-sa/3.0/ro/ . | |
*/ | |
#ifndef _PS2MOUSE_H_ | |
#define _PS2MOUSE_H_ | |
#include <avr/io.h> | |
/* definitii de elemente fizice (pini/registrii) folosite de catre modul */ | |
#define PS2M_PIN_DATE _BV(PB4) | |
#define PS2M_PIN_TACT _BV(PB1) | |
#define PS2M_PIN_REGISTRU_DIRECTIE DDRB | |
#define PS2M_PIN_REGISTRU_SCRIERE PORTB | |
#define PS2M_PIN_REGISTRU_CITIRE PINB | |
/* pachete de date (octeti) cu interpretare speciala in sistem */ | |
#define PS2M_COM_GAZDA_RESET 0xFF | |
#define PS2M_COM_GAZDA_OBT_DEPLASAMENTE 0xEB | |
#define PS2M_COM_GAZDA_ACK 0xFA | |
#define PS2M_COM_GAZDA_BAT 0xAA | |
#define PS2M_COM_GAZDA_ID 0x00 | |
#define PS2M_COM_GAZDA_LA_CERERE 0xF0 | |
#define PS2M_COM_GAZDA_OBT_STARE 0xE9 | |
/* regiune de masti pentru bitii de stare ('bitiStare') din structura 'ps2m_st_stare' */ | |
#define PS2M_ST_MOD_MSC 0x40 | |
#define PS2M_ST_SCALARE_MSC 0x20 | |
#define PS2M_ST_BT_STANGA_MSC 0x04 | |
#define PS2M_ST_BT_MIJLOC_MSC 0x02 | |
#define PS2M_ST_BT_DREAPTA_MSC 0x01 | |
/* regiune de masti pentru bitii de stare ('bitiStare') din structura 'ps2m_st_date' */ | |
#define PS2M_DT_DEPASIRE_Y_MSK 0x80 | |
#define PS2M_DT_DEPASIRE_X_MSK 0x40 | |
#define PS2M_DT_SEMN_Y_MSK 0x20 /* '1' pentru deplasare in jos si '0' pentru miscare in sus */ | |
#define PS2M_DT_SEMN_X_MSK 0x10 /* '1' -> deplasare la stanga, iar '0' -> deplasare la dreapta */ | |
#define PS2M_DT_BT_STANGA_MSC 0x01 | |
#define PS2M_DT_BT_MIJLOC_MSC 0x04 | |
#define PS2M_DT_BT_DREAPTA_MSC 0x02 | |
/* regiunea enumerarilor folosite in modul */ | |
typedef enum {PS2M_OK, PS2M_ESUAT} ps2m_finalitate; | |
typedef enum {PS2M_COM_GAZDA_LA_MOUSE, PS2M_COM_MOUSE_LA_GAZDA} ps2m_dir_comunicatii; | |
typedef enum {PS2M_DT_DX_STANGA, PS2M_DT_DX_DREAPTA} ps2m_dir_depl_x; | |
typedef enum {PS2M_DT_DY_SUS, PS2M_DT_DY_JOS} ps2m_dir_depl_y; | |
/* structurile de date relevante pentru modul */ | |
typedef struct { | |
uint8_t bitiStare; | |
uint8_t deplasareX; | |
uint8_t deplasareY; | |
} ps2m_st_date; | |
typedef struct { | |
uint8_t bitiStare; | |
uint8_t rezolutie; | |
uint8_t rataEsantionare; | |
} ps2m_st_stare; | |
/* variabile folosite in functiile substituibile (inline) de mai jos */ | |
extern uint8_t ps2m_rezolutie_curenta; | |
/* functiile disponibile din modul */ | |
extern ps2m_finalitate ps2m_init(void); | |
extern ps2m_finalitate ps2m_citeste_configuratie(ps2m_st_stare *pdStare); | |
extern ps2m_finalitate ps2m_citeste_deplasamente(ps2m_st_date *pdDate); | |
inline uint8_t ps2m_este_buton_stanga_apasat(ps2m_st_date *pdDate) { | |
return (pdDate->bitiStare & PS2M_DT_BT_STANGA_MSC) != 0; | |
} | |
inline uint8_t ps2m_este_buton_mijloc_apasat(ps2m_st_date *pdDate) { | |
return (pdDate->bitiStare & PS2M_DT_BT_MIJLOC_MSC) != 0; | |
} | |
inline uint8_t ps2m_este_buton_dreapta_apasat(ps2m_st_date *pdDate) { | |
return (pdDate->bitiStare & PS2M_DT_BT_DREAPTA_MSC) != 0; | |
} | |
inline uint8_t ps2m_obtine_val_deplasament_brut_x(ps2m_st_date *pdDate) { | |
return pdDate->deplasareX; | |
} | |
inline double ps2m_obtine_val_deplasament_mm_x(ps2m_st_date *pdDate) { | |
return ((double)ps2m_obtine_val_deplasament_brut_x(pdDate))/ps2m_rezolutie_curenta; | |
} | |
inline ps2m_dir_depl_x ps2m_obtine_dir_deplasament_x(ps2m_st_date *pdDate) { | |
if ((pdDate->bitiStare & PS2M_DT_SEMN_X_MSK) != 0) { | |
return PS2M_DT_DX_STANGA; | |
} | |
return PS2M_DT_DX_DREAPTA; | |
} | |
inline uint8_t ps2m_obtine_val_deplasament_brut_y(ps2m_st_date *pdDate) { | |
return pdDate->deplasareY; | |
} | |
inline double ps2m_obtine_val_deplasament_mm_y(ps2m_st_date *pdDate) { | |
return ((double)ps2m_obtine_val_deplasament_brut_y(pdDate))/ps2m_rezolutie_curenta;; | |
} | |
inline ps2m_dir_depl_y ps2m_obtine_dir_deplasament_y(ps2m_st_date *pdDate) { | |
if ((pdDate->bitiStare & PS2M_DT_SEMN_Y_MSK) != 0) { | |
return PS2M_DT_DY_JOS; | |
} | |
return PS2M_DT_DY_SUS; | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment