118 PinConfig(uint8_t __pin, PinBank __bank, PinDirection __dir,
bool __pullup): config(5)
120 set(__pin, __bank, __dir, __pullup);
123 void set(uint8_t __pin, PinBank __bank, PinDirection __dir,
bool __pullup)
136 return (config[kPinConfigPin1] << 0) | (config[kPinConfigPin2] << 1) | (config[kPinConfigPin3] << 2);
139 void pin(uint8_t __pin)
141 config[kPinConfigPin1] = (__pin & 0b001) ?
true :
false;
142 config[kPinConfigPin2] = (__pin & 0b010) ?
true :
false;
143 config[kPinConfigPin3] = (__pin & 0b100) ?
true :
false;
151 return static_cast<PinBank
>((config[kPinConfigBank1] << 0) | (config[kPinConfigBank2] << 1) | (config[kPinConfigBank3] << 2));
154 void bank(uint8_t __bank)
156 config[kPinConfigBank1] = (__bank & 0b001) ?
true :
false;
157 config[kPinConfigBank2] = (__bank & 0b010) ?
true :
false;
158 config[kPinConfigBank3] = (__bank & 0b100) ?
true :
false;
166 return static_cast<PinDirection
>(
static_cast<bool>(config[kPinConfigDir]));
169 void dir(PinDirection __dir)
171 config[kPinConfigDir] =
static_cast<bool>(__dir);
179 return config[kPinConfigPullup];
182 void pullup(
bool __pullup)
184 config[kPinConfigPullup] = !!__pullup;
195 Pin(PinDirection dir,
bool pullup, PinBank bank = PinBank::kPinBankMax, uint8_t number = 0): config(number, bank, dir, pullup)
202 if (config.bank() != PinBank::kPinBankMax)
204 if (config.pullup() && config.dir() == PinDirection::kIn && config.pin() < 8)
207 getPortFromBank(config.bank()) &= ~(1 << config.pin());
210 config.bank(PinBank::kPinBankMax);
220 case PinDirection::kIn:
221 getDDRFromBank(config.bank()) |= 0x00;
222 getPortFromBank(config.bank()) = (config.pullup() ? 0xFF : 0x00);
224 if (config.pullup()) getPortFromBank(config.bank()) = (1 << config.pin());
225 else getPortFromBank(config.bank()) &= ~(1 << config.pin());
229 case PinDirection::kOut:
230 getDDRFromBank(config.bank()) = 0xFF;
231 getPortFromBank(config.bank()) = 0x00;
237 void setPin(PinBank newBank, uint8_t newNumber)
241 config.bank(newBank);
242 config.pin(newNumber);
249 if (config.bank() >= PinBank::kPinBankMax)
return false;
250 return (getPinFromBank(config.bank()) << (config.pin() * 8)) > 0;
253 void write(
bool state)
255 if (config.bank() >= PinBank::kPinBankMax)
return;
256 if (state) getPinFromBank(config.bank()) |= (1 << config.pin());
257 else getPinFromBank(config.bank()) &= ~(1 << config.pin());
264 void reset(
bool resetBanks =
false,
bool resetAllPins =
true)
271 clockReadPin->reset();
272 clockWritePin->reset();
276 clockPeriodWrite = 0;
282 for (uint_fast8_t i = 0; i < PinBank::kPinBankMax; ++i)
284 setBankDir(getPinBank(i), PinDirection::kIn);
289 void usePullup(
bool usePullup,
bool resetBanks =
false)
292 reset(resetBanks,
false);
295 void addAddressBank(PinBank bank)
297 address->addBank(bank);
298 setBankDir(bank, PinDirection::kOut);
301 template <
typename T,
typename ... Ts>
302 OSCR::Util::enable_if_t<(OSCR::Util::is_same<T, Ts>::value && ...),
void>
303 addAddressBank(T bank, Ts ... banks)
305 addAddressBank(bank);
306 addAddressBank(banks...);
309 void addDataBank(PinBank bank)
312 setBankDir(bank, PinDirection::kIn);
315 template <
typename T,
typename ... Ts>
316 OSCR::Util::enable_if_t<(OSCR::Util::is_same<T, Ts>::value && ...),
void>
317 addDataBank(T bank, Ts ... banks)
320 addDataBank(banks...);
323 void setClockWritePin(PinBank bank, uint8_t pin)
325 clockWritePin->setPin(bank, pin);
328 void setClockReadPin(PinBank bank, uint8_t pin)
330 clockReadPin->setPin(bank, pin);
333 void setLatchPin(PinBank bank, uint8_t pin)
335 latchPin->setPin(bank, pin);
341 if (!useLatchPin)
return;
343 while(!latchPin->read()) NOP;
348 if (clockPeriodRead > 0)
350 clockReadPin->write(
true);
351 delayMicroseconds(clockPeriodRead);
352 clockReadPin->write(
false);
358 if (clockPeriodWrite > 0)
360 clockReadPin->write(
true);
361 delayMicroseconds(clockPeriodWrite);
362 clockReadPin->write(
false);
366 template <
typename T>
367 void setAddress(T newAddress)
369 uint8_t
const size =
sizeof(T);
371 for (uint8_t i = 0; i < size; i++)
373 getPort(address->banks[i]) = (newAddress >> (i * 8)) & 0xFF;
377 template <
typename T>
380 uint8_t
const size =
sizeof(T);
386 for (uint8_t i = 0; i < size; i++)
388 out |= getPin(data->banks[i]) << (i * 8);
394 template <
typename TD,
typename TA>
395 TD readAddress(TA newAddress)
397 setAddress(newAddress);
398 return readData<TD>();
401 template <
typename TD,
typename TA>
402 void setPosition(TA newAddress)
404 setAddress(newAddress);
405 lastAddress = newAddress;
408 template <
typename TD>
411 TD read = readData<TD>();
412 size_t nextAddress = (data->width * 8) + lastAddress;
413 setAddress(nextAddress);
414 lastAddress = nextAddress;
418 template <
typename TA>
424 template <
typename T>
425 void writeData(T outputData)
427 uint8_t
const size =
sizeof(T);
429 for (uint8_t i = 0; i < size; i++)
431 getPort(data->banks[i]) = (outputData >> (i * 8)) & 0xFF;
437 uint8_t readBank(PinBank bank)
444 volatile uint8_t& getDDR(PinBank bank)
448 case PinBank::kPinBankA:
return DDRA;
449 case PinBank::kPinBankC:
return DDRC;
450 case PinBank::kPinBankF:
return DDRF;
451 case PinBank::kPinBankH:
return DDRH;
452 case PinBank::kPinBankK:
return DDRK;
453 case PinBank::kPinBankL:
return DDRL;
454 case PinBank::kPinBankG:
return DDRG;
455 case PinBank::kPinBankMax:
break;
460 volatile uint8_t& getPort(PinBank bank)
464 case PinBank::kPinBankA:
return PORTA;
465 case PinBank::kPinBankC:
return PORTC;
466 case PinBank::kPinBankF:
return PORTF;
467 case PinBank::kPinBankH:
return PORTH;
468 case PinBank::kPinBankK:
return PORTK;
469 case PinBank::kPinBankL:
return PORTL;
470 case PinBank::kPinBankG:
return PORTG;
471 case PinBank::kPinBankMax:
break;
476 volatile uint8_t& getPin(PinBank bank)
480 case PinBank::kPinBankA:
return PINA;
481 case PinBank::kPinBankC:
return PINC;
482 case PinBank::kPinBankF:
return PINF;
483 case PinBank::kPinBankH:
return PINH;
484 case PinBank::kPinBankK:
return PINK;
485 case PinBank::kPinBankL:
return PINL;
486 case PinBank::kPinBankG:
return PING;
487 case PinBank::kPinBankMax:
break;
492 void setBankDir(PinBank bank, PinDirection dir)
496 case PinDirection::kIn:
498 getPort(bank) = (pullup ? 0xFF : 0x00);
500 case PinDirection::kOut:
502 getPort(bank) = 0x00;
507 void setMode(DataMode mode)
509 PinDirection pinDir = ((mode == DataMode::kWrite) ? PinDirection::kOut : PinDirection::kIn);
511 for (uint8_t i = 0; i < data->width && data->banks[i] != kPinBankMax; i++)
513 setBankDir(data->banks[i], pinDir);
521 Pin * latchPin =
new Pin(PinDirection::kIn,
false);
522 Pin * clockReadPin =
new Pin(PinDirection::kOut,
false);
523 Pin * clockWritePin =
new Pin(PinDirection::kOut,
false);
525 bool useLatchPin =
false;
526 uint16_t clockPeriodRead = 0;
527 uint16_t clockPeriodWrite = 0;
530 size_t lastAddress = 0;