Moin,
ich habe die Reset-Routine bei der Version mit der Kernalumschaltung (Restore-F1..F7)
nochmal überarbeitet, diese Änderung kommt später auch in die Superkernal-Version.
Beim Reset über 3 Sekunden Restore bleibt das Reset-Signal nun solange aktiv wie die
Restore-Taste gedrückt wird.
Zusätzlich blinkt die rote LED auf dem Arduino, und damit auch die Power-Leuchte des
C64.
MAX_LED wird beim Start nun erst einmal auf 1 begrenzt, sonst konnte es vorkommen
das der LED-Stripe auf volle Helligkeit gingen und damit die Stromversorgung zu stark
belastet wurde.
Dann noch ein paar interne Optimierungen, hauptsächlich an den Macros.
C
#include <CRC32.h> //https://github.com/bakercp/CRC32
#include <EEPROM.h>
#include <FastLED.h> //https://github.com/FastLED/FastLED
#include <TimerOne.h> //https://github.com/PaulStoffregen/TimerOne
#include <EasyButton.h> //https://github.com/evert-arias/EasyButton
//#include <U8x8lib.h> //https://github.com/olikraus/u8g2
//macros for fast pin access (https://www.best-microcontroller-projects.com)
//fixed tstPin macro and renamed to getPin
#define toggle(b) ((b)<8 ? PORTD ^= (1<<(b)) : PORTB ^= (1<<(b-8)))
#define setPin(b) ((b)<8 ? PORTD |= (1<<(b)) : PORTB |= (1<<(b-8)))
#define clrPin(b) ((b)<8 ? PORTD &=~(1<<(b)) : PORTB &=~(1<<(b-8)))
#define getPin(b) ((b)<8 ? (PIND &(1<<(b)))!=0 : (PINB &(1<<(b-8)))!=0)
#define lowPin(b) ((b)<8 ? (PIND &(1<<(b)))==0 : (PINB &(1<<(b-8)))==0)
//Constants
#define NUM_LEDS 21 //Const - Number of LED's
#define DISABLE_LED 20 //Const - switch off last LED
#define WAIT_TIME 100 //Const - Delay for Reset
#define MAX_LEVEL 1 //Const - max. LED Level
#define MIN_LEVEL 1 //Const - min. LED Level
#define EEPROM_ADDR 0 //Memory - Configuration.
#define LED_PIN 13 //Output - Onboard LED/Power LED
#define ROW_PIN 10 //Output - Umschaltung Row 0/7
#define DATA_PIN 14 //Output - Pin for LED-Stripe
#define RESET_PIN 11 //Output - connected to C64 Reset
#define ADDR0_PIN 9 //Output - Addr. 0 Kernelswitch
#define ADDR1_PIN 8 //Output - Addr. 1 Kernelswitch
#define RESTORE_PIN 12 //Input - connected to Restore Key
//some volatile variables (interupt routines)
volatile byte scanCode = 0; //Scan Result
volatile byte maxLevel = MAX_LEVEL; //LED-Stripe, max. led level
volatile byte ledLevel = MIN_LEVEL; //LED-Stripe, min. led level
volatile CRGB ledColor = CRGB::Lime; //LED-Stripe, current Color (RGB)
byte myKernal = 0; //current Kernal
byte ledIndex = 0; //LED-Stripe, Colorindex
CRGB leds[NUM_LEDS]; //LED-Stripe, number of LED's
EasyButton Restore(RESTORE_PIN, 35, false, true);
#ifdef U8X8_HAVE_HW_I2C
U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);
#endif
void setup() {
PORTB |= B00001100; //LED = LOW : RESTORE = NOPULLUP : RESET, ROW = HIGH : ADDR0, ADDR1 = LOW
DDRB |= B00101111; //LED = OUTPUT : RESTORE = INPUT : RESET, ROW, ADDR0, ADDR1 = OUTPUT
DDRD &= B00000011; //PA0, PA7, PB3, PB4, PB5, PB6 = INPUT : leave TxD, RxD alone
cli(); //Interrupts sperren
PCICR |= (1 << PCIE2);
PCMSK2 |= B00001100;
sei(); //Interrupts freigeben;
myKernal = EEPROM.read(EEPROM_ADDR);
if (myKernal > 3) {
myKernal = 0;
}
SetKernal(myKernal, false); //Set Kernal
Restore.begin();
Restore.onPressedFor(3000, onRestore);
FastLED.addLeds<WS2812B, DATA_PIN, RGB>(leds, NUM_LEDS);
Timer1.initialize(10000); Timer1.attachInterrupt(isrTimer);
SetColor(EEPROM.read(EEPROM_ADDR+1));
#ifdef U8X8_HAVE_HW_I2C
u8x8.begin();
u8x8.setPowerSave(0);
u8x8.setFont(u8x8_font_amstrad_cpc_extended_r);
UpdateLCD(myKernal);---
#endif
//Serial.begin(9600);
}
//asm inline utility (swap nibbles)
inline byte SWAP(byte val) {
__asm__ __volatile__ ( "swap %0 ": "+r"(val));
return val;
}
ISR(PCINT2_vect){
byte scan, cols;
static byte scantemp = 0;
scan = PIND & B11111100;
switch (scan & B00001100) {
case B00000000: //init scan sequence
setPin(ROW_PIN);
if (scantemp == 0) {
scanCode = 0;
} else (scantemp = 0);
break;
case B00001000: //Row0 (F7, F1, F3, F5)
if (lowPin(RESTORE_PIN)) {
clrPin(ROW_PIN);
}
cols = SWAP(scan & 0xF0);
if (cols != 0x0F) {
(scantemp = cols);
} else (scantemp = 0);
break;
case B00000100: //Row7 (2, Spc, CBM, Q)
cols = (scan & 0xF0);
if (cols != 0xF0) {
scantemp = (scantemp & 0x0F) | cols;
} else scantemp = (scantemp & 0x0F);
scanCode = scantemp;
break;
default: //other Row
break;
}
}
void isrTimer() {
static uint32_t ledCRC32 = 0;
ledLevel = min(ledLevel, maxLevel);
if (ledLevel < maxLevel) {
ledLevel++;
}
CRC32 crc;
for (int i = 0; i < NUM_LEDS; i++) {
if (i != DISABLE_LED) {
//swap green and red (GRB order)
leds[i] = CRGB(ledColor.green, ledColor.red, ledColor.blue);
} else leds[i] = CRGB::Black;
leds[i].maximizeBrightness(map(ledLevel, 0, 100, 0, 255));
crc.update(leds[i].red);
crc.update(leds[i].green);
crc.update(leds[i].blue);
}
uint32_t checksum = crc.finalize();
if (checksum != ledCRC32) {
ledCRC32 = checksum;
FastLED.show();
}
}
void loop() {
static byte lastCode = 1;
static uint32_t cbmtime = 0;
Restore.read();
noInterrupts();
byte keyCode = scanCode;
interrupts();
setPin(RESET_PIN);
if (lastCode != keyCode) {
switch (keyCode) {
case 0x0D: //F1
if (Restore.isPressed()) {
SetKernal(0, true);
}
break;
case 0x0B: //F3
if (Restore.isPressed()) {
SetKernal(1, true);
}
break;
case 0x07: //F5
if (Restore.isPressed()) {
SetKernal(2, true);
}
break;
case 0x0E: //F7
if (Restore.isPressed()) {
SetKernal(3, true);
}
break;
case 0xB0: //CBM
if (lastCode == 0) {
if ((millis() - cbmtime) < 500) {
ledIndex++;
if (ledIndex > 3) {
ledIndex = 0;
}
SetColor(ledIndex);
}
}
cbmtime = millis();
break;
}
lastCode = keyCode;
}
}
void wait(uint32_t period) {
uint32_t time_now = millis();
while(millis() < time_now + period){
//wait approx. [period] ms
}
}
void onRestore() {
clrPin(RESET_PIN);
do {
toggle(LED_PIN);
wait(WAIT_TIME);
} while(lowPin(RESTORE_PIN));
clrPin(LED_PIN);
}
#ifdef U8X8_HAVE_HW_I2C
void UpdateLCD(byte Kernal) {
u8x8.clearDisplay();
u8x8.setInverseFont(Kernal == 0);
u8x8.drawString(0, 0, "F1 CBM Kernal ");
u8x8.setInverseFont(Kernal == 1);
u8x8.drawString(0, 10, "F3 Jiffy DOS ");
u8x8.setInverseFont(Kernal == 2);
u8x8.drawString(0, 20, "F5 Dolphin DOS");
u8x8.setInverseFont(Kernal == 3);
u8x8.drawString(0, 30, "F7 Speed DOS+ ");
}
#endif
void SetKernal(byte Kernal, boolean Restart) {
myKernal = Kernal;
if (Restart) {
clrPin(RESET_PIN);
#ifdef U8X8_HAVE_HW_I2C
UpdateLCD(myKernal);
#endif
}
switch (myKernal) {
case 0:
clrPin(ADDR0_PIN);
clrPin(ADDR1_PIN);
break;
case 1:
setPin(ADDR0_PIN);
clrPin(ADDR1_PIN);
break;
case 2:
clrPin(ADDR0_PIN);
setPin(ADDR1_PIN);
break;
case 3:
setPin(ADDR0_PIN);
setPin(ADDR1_PIN);
break;
}
EEPROM.update(EEPROM_ADDR, myKernal);
wait(WAIT_TIME);
}
void SetColor(byte Index) {
noInterrupts();
ledIndex = Index;
switch (ledIndex) {
case 0:
ledColor = CRGB::Lime;
maxLevel = 36; //max. Brightness (I < 100mA)
ledLevel = MIN_LEVEL;
break;
case 1:
ledColor = CRGB::Red;
maxLevel = 36; //max. Brightness (I < 100mA)
ledLevel = MIN_LEVEL;
break;
case 2:
ledColor = CRGB::DeepSkyBlue;
maxLevel = 21; //max. Brightness (I < 100mA)
ledLevel = MIN_LEVEL;
break;
case 3:
ledColor = CRGB::Black;
ledLevel = MAX_LEVEL;
break;
default:
ledIndex = 0;
break;
}
interrupts();
EEPROM.update(EEPROM_ADDR+1, ledIndex);
}
Alles anzeigen
Mfg Jood