4 Commits

Author SHA1 Message Date
d68066014a add technical documentation 2025-01-26 13:39:04 +01:00
6e99595c00 link to rgb document 2024-05-27 12:01:29 +02:00
2c87b2814d some docs 2024-05-25 17:22:45 +02:00
95ad5a9e9f naming 2024-05-22 11:55:47 +02:00
10 changed files with 38 additions and 5 deletions

Binary file not shown.

View File

@ -39,6 +39,8 @@ The communcation with the game play controller is implemented as a sequences of
![](./docs/rgb-driver.jpg) ![](./docs/rgb-driver.jpg)
Details are here https://gitea.hottis.de/wn/tetris/src/branch/main/rgb-driver/readme.md
## Score Display ## Score Display

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
rgb-driver/docs/timing.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

View File

@ -26,6 +26,37 @@ Schematics and legend for signals:
![](./docs/schematics.jpeg) ![](./docs/schematics.jpeg)
### Some more explanations
Consider above schematics and the screen shot "Last octets" from the oscilloscope.
![](./docs/timing.png)
Timer TA1 is running in "up mode" to the value 45 set in compare register `TA1CCR0`. The compare registers `TA1CCR1` is set to 10, `TA1CCR2` is set to 22.
The output mode of the timer is set to "Reset/Set", which means the GPIO associated with `TA1CCR1` (P2.1) and `TA1CCR2` (P2.4) are set at the overflow and
restart of the counter and reset when the counter matches the associated compare value.
So, on P2.1 (D1 on the oscilloscope) we have a long pulse and at P2.4 (D0 on the oscilloscope) we have a short pulse, with synchronous raising edge.
![](./docs/74hc74-function-table.png)
The inverted signal P2.4 is connected to the Clock input of a 74HC74 D-flipflop, the data input of the flipflop is connected to GPIO P1.0 (D2 on the oscilloscope).
The interrupt service routine `shifter_isr` is triggered by the overflow and restart of the timer, this interrupt service routine provides the next bit to be
signaled on P1.0. This bit is stored at the falling edge of P2.4 (long pulse) in the flipflop.
The short pulse (P2.1, D1) is ANDed using a 74HC08 with the inverted output of the flipflop, the long pulse (P2.4, D0) is ANDed with the non-inverted output of
the flipflop, the ANDed results are ORed using a 74HC32.
So, at the output of the OR gate (yellow on the oscilloscope) we get a long pulse for a 1 at P1.0 provided by the ISR and a short pulse for a 0 at P1.0.
The routine `drawscreen` takes color values from the "frame buffer" beginning at `screendata` and translated them into the red, green and blue values and provides these values, first red, then green and finally blue to the ISR via the `DATA_REGISTER`.
The ISR cycles over the `DATA_REGISTER` and presents the bits at P1.0.
Additionally, when the first bit of a full draw screen cycle is presented at P1.0 by the ISR, it also sets the data enable signal at P1.1 and when the last bit has been provided it disabled the data enable signal. This signal is also synchronized using a flipflop and used to enable the short/long pulses using an AND gate.
## Timing ## Timing

View File

@ -27,7 +27,7 @@ t_melodies pling = {
}; };
void playPling() { void playPling() {
pling.amplitude = configGetEffectsAmplitudePtr(); pling.p_amplitude = configGetEffectsAmplitudePtr();
sequencerPlayMelodies(&pling); sequencerPlayMelodies(&pling);
} }

View File

@ -933,7 +933,7 @@ t_melodies tetrisTheme = {
void playMelodyTetris() { void playMelodyTetris() {
tetrisTheme.pace = INITIAL_PACE; // reset to start value each time tetrisTheme.pace = INITIAL_PACE; // reset to start value each time
tetrisTheme.amplitude = configGetMelodyAmplitudePtr(); tetrisTheme.p_amplitude = configGetMelodyAmplitudePtr();
sequencerPlayMelodies(&tetrisTheme); sequencerPlayMelodies(&tetrisTheme);
} }

View File

@ -79,7 +79,7 @@ t_melodies tusch1 = {
}; };
void playTusch1() { void playTusch1() {
tusch1.amplitude = configGetEffectsAmplitudePtr(); tusch1.p_amplitude = configGetEffectsAmplitudePtr();
sequencerPlayMelodies(&tusch1); sequencerPlayMelodies(&tusch1);
} }

View File

@ -59,7 +59,7 @@ void sequencerExec(void *handle) {
if (melody->tones[melody->idx].length == e_L_EndMark) { if (melody->tones[melody->idx].length == e_L_EndMark) {
melody->idx = 0; melody->idx = 0;
} }
psgPlayTone(melodies->chip, channel, *(melodies->amplitude), melody->tones[melody->idx].octave, melody->tones[melody->idx].note); psgPlayTone(melodies->chip, channel, *(melodies->p_amplitude), melody->tones[melody->idx].octave, melody->tones[melody->idx].note);
melody->lengthCnt = (melody->tones[melody->idx].staccato) ? melody->lengthCnt = (melody->tones[melody->idx].staccato) ?
(calcLength(melodies, melody->tones[melody->idx].length) / 2) : (calcLength(melodies, melody->tones[melody->idx].length) / 2) :
calcLength(melodies, melody->tones[melody->idx].length); calcLength(melodies, melody->tones[melody->idx].length);

View File

@ -52,7 +52,7 @@ typedef struct {
typedef struct { typedef struct {
uint8_t slotMask; uint8_t slotMask;
uint8_t chip; uint8_t chip;
uint8_t *amplitude; uint8_t *p_amplitude;
uint8_t taskId; uint8_t taskId;
uint16_t quarterLength; uint16_t quarterLength;
uint8_t numOfMelodies; uint8_t numOfMelodies;