Szukam abstrakcji C ++ dla sprzętowych punktów We / Wy lub pinów. Rzeczy takie jak in_pin, out_pin, inout_pin, może open_collector_pin itp.
Z pewnością mogę wymyślić taki zestaw abstrakcji, więc nie szukam odpowiedzi typu „hej, możesz to zrobić w ten sposób”, ale raczej „spójrz na tę bibliotekę, która została użyta w tym i tamtym oraz ten projekt'.
Google niczego nie wykrył, może dlatego, że nie wiem, jak nazywaliby to inni.
Moim celem jest zbudowanie bibliotek we / wy, które są oparte na takich punktach, ale także zapewniają takie punkty, więc łatwo byłoby na przykład podłączyć HD44780 LCd do styków we / wy układu lub do I2C (lub SPI) Wzmacniacz I / O lub dowolny inny punkt, którym można jakoś sterować, bez żadnych zmian w klasie LCD.
Wiem, że jest to na granicy elektroniki / oprogramowania, przepraszam, jeśli tu nie należy.
@leon: wiring To jest duży pakiet oprogramowania, muszę się bliżej przyjrzeć. Wygląda jednak na to, że nie używają abstrakcji w taki sposób, jak chcę. Na przykład w implementacji klawiatury widzę
digitalWrite(columnPins[c], LOW); // Activate the current column.
Oznacza to, że istnieje jedna funkcja (digitalWrite), która wie, jak pisać na pinie we / wy. Uniemożliwia to dodanie nowego typu styku we / wy (na przykład takiego, który jest na MCP23017, więc musi być zapisany przez I2C) bez przepisywania funkcji digitalWrite.
@Oli: przejrzałem przykład Arduino IO, ale wydaje się, że używam tego samego podejścia co biblioteka Wiring:
int ledPin = 13; // LED connected to digital pin 13
void setup(){
pinMode(ledPin, OUTPUT); // sets the digital pin as output
}
źródło
Odpowiedzi:
Krótka odpowiedź: niestety nie ma biblioteki do robienia tego, co chcesz. Robiłem to sam wiele razy, ale zawsze w projektach innych niż open source. Zastanawiam się nad umieszczeniem czegoś na githubie, ale nie jestem pewien, kiedy będę mógł.
Dlaczego C ++?
źródło
Pozwól mi bezwstydnie podłączyć mój projekt open source https://Kvasir.io . Część Kvasir :: Io zapewnia funkcje manipulacji pinami. Najpierw musisz zdefiniować swój pin za pomocą Kvasir :: Io :: PinLocation w następujący sposób:
Zauważ, że tak naprawdę nie używa pamięci RAM, ponieważ są to zmienne constexpr.
W całym kodzie możesz używać tych lokalizacji pinów w funkcjach „fabryki akcji”, takich jak makeOpenDrain, set, clear, makeOutput i tak dalej. „Fabryka akcji” tak naprawdę nie wykonuje akcji, a raczej zwraca Kvasir :: Register :: Action, którą można wykonać za pomocą Kvasir :: Register :: apply (). Powodem tego jest to, że apply () łączy działania przekazane mu, gdy działają na jednym i tym samym rejestrze, dzięki czemu uzyskuje się wzrost wydajności.
Ponieważ tworzenie i łączenie akcji odbywa się w czasie kompilacji, powinno to dać ten sam kod asemblera, co typowy ręcznie kodowany odpowiednik:
źródło
Projekt Wiring wykorzystuje taką abstrakcję:
http://wiring.org.co/
a kompilator jest napisany w C ++. Powinieneś znaleźć wiele przykładów w kodzie źródłowym. Oprogramowanie Arduino opiera się na okablowaniu.
źródło
W C ++ można napisać klasę, aby można było używać portów I / O tak, jakby były zmiennymi, np
bez względu na podstawowe wdrożenie. Na przykład, jeśli używa się platformy sprzętowej, która nie obsługuje operacji na poziomie bitów, ale obsługuje operacje rejestru na poziomie bajtów, można (prawdopodobnie przy pomocy niektórych makr) zdefiniować statyczną klasę IO_PORTS z wbudowanym odczytem i zapisem właściwości o nazwie bbRB3 i bbLATB4, takie, że zmieni się w ostatnią instrukcję powyżej
które z kolei zostaną przetworzone na coś takiego:
Kompilator powinien być w stanie zauważyć ciągłe wyrażenie w operatorze?: I po prostu dołączyć część „true”. Może być możliwe zmniejszenie liczby właściwości utworzonych przez rozwinięcie makr do czegoś takiego jak:
lub
ale nie jestem pewien, czy kompilator byłby w stanie tak ładnie wstawić kod.
W żadnym wypadku nie chcę sugerować, że używanie portów I / O tak, jakby były zmiennymi, jest koniecznie dobrym pomysłem, ale skoro wspominasz o C ++, warto wiedzieć. Moimi własnymi preferencjami w C lub C ++, jeśli zgodność z kodem korzystającym z wyżej wymienionego stylu nie była wymagana, prawdopodobnie byłoby zdefiniowanie pewnego rodzaju makra dla każdego bitu I / O, a następnie zdefiniowanie makr dla „readBit”, „writeBit”, „setBit” i „clearBit” pod warunkiem, że argument identyfikujący bit przekazany do tych makr musi być nazwą portu we / wy przeznaczonego do użycia z takimi makrami. Na przykład powyższy przykład zostałby zapisany jako
i przetłumaczone jako
Byłoby to trochę więcej pracy dla preprocesora niż w stylu C ++, ale byłoby mniej pracy dla kompilatora. Umożliwiłoby to również optymalne generowanie kodu dla wielu implementacji I / O i przyzwoitą implementację kodu dla prawie wszystkich.
źródło
Jeśli szukasz czegoś naprawdę niesamowitego do wyodrębnienia sprzętu i jesteś pewien swoich umiejętności w C ++, powinieneś wypróbować ten wzór:
https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
Użyłem go w jednej próbie wyodrębnienia sprzętu dla układu Cortex-M0. Nie napisałem jeszcze nic o tym doświadczeniu (kiedyś to zrobię), ale wierzcie, że było bardzo przydatne ze względu na jego statyczny polimorficzny charakter: ta sama metoda dla różnych układów, bez żadnych kosztów (w porównaniu z dynamicznym polimorfizmem).
źródło