#include "7seg.h" #include #include #ifdef WITH_GUI #include #include #endif static device_vtable_t const seg7_vtable = { seg7_read, seg7_write, #ifdef WITH_GUI seg7_draw, #endif seg7_deinit }; void seg7_init( seg7_t *seg, bool initialize ) { device_init( &seg->base, "seg7" ); seg->base.vtable = (device_vtable_t *)&seg7_vtable; seg->debug = false; if( initialize ) { seg->latch = 0x0000; seg->shift = 0x0000; } } uint8_t seg7_read( void *obj, uint16_t addr ) { // device is a write-only device return 0; } void seg7_write( void *obj, uint16_t addr, uint8_t data ) { seg7_t *seg = (seg7_t *)obj; // address is not relevant, PORTA is connected to our signals // via a databus // write bits from SER into shift register on positive SRCLK if( data & SRCLK ) { seg->shift = ( seg->shift << 1 ) | ( data & SER ); if( seg->debug ) { fprintf( stderr, "7seg shifting data, data is now %02X\n", seg->shift ); } } // copy shift to latch register on positive RCLK if( data & RCLK ) { seg->latch = seg->shift; if( seg->debug ) { fprintf( stderr, "7seg copying %02X from shift to latch\n", seg->latch ); } } // ignore writes to other addresses } #ifdef WITH_GUI enum { NOF_DIGITS = 16, NOF_SEGS = 7, // direction of the segment (vertical or horizontal) H = 0, V = 1, // segment positions in the segs array (bit) A = 6, B = 5, C = 4, D = 3, E = 2, F = 1, G = 0 }; static int segs[NOF_DIGITS] = { 0x7E, 0x30, 0x6D, 0x79, 0x33, 0x5B, 0x5F, 0x70, 0x7F, 0x7B, 0x77, 0x1F, 0x4E, 0x3D, 0x4F, 0x47 }; static int x_pos[NOF_SEGS] = { 5, 45, 45, 5, 5, 5 , 5 }; static int y_pos[NOF_SEGS] = { 5, 5, 45, 90, 45, 5, 45 }; static int direction[NOF_SEGS] = { H, V, V, H, V, V, H }; static void printSegment( SDL_Renderer *renderer, int x, int y, int direction, bool enabled ) { int r = 80; if( enabled ) { r = 255; } switch( direction ) { case H: boxRGBA( renderer, x-3, y-3, x+40, y+3, r, 0x00, 0x00, 0xFF ); break; case V: boxRGBA( renderer, x-3, y-3, x+3, y+40, r, 0x00, 0x00, 0xFF ); break; } } static void printDigit( SDL_Renderer *renderer, int x, int y, int digit ) { int v = ( 1 << 6 ); for( int i = 0; i < 7; i++ ) { printSegment( renderer, x + x_pos[i], y + y_pos[i], direction[i], v & segs[digit] ); v >>= 1; } } void seg7_draw( void *obj, SDL_Renderer *renderer ) { seg7_t *seg = (seg7_t *)obj; boxRGBA( renderer, 10, 10, 110, 110, 0x00, 0x00, 0x00, 0xFF ); printDigit( renderer, 10, 10, ( seg->latch & 0x00F0 ) >> 4 ); printDigit( renderer, 60, 10, seg->latch & 0x000F ); } #endif void seg7_deinit( void *obj ) { seg7_t *seg = (seg7_t *)obj; device_deinit( &seg->base ); }