Fix SN74HC595 doesn't use ESPHome HAL and add lint checks for it (#1188)

This commit is contained in:
Otto Winter 2020-07-25 14:22:56 +02:00 committed by GitHub
parent 55388724af
commit 0fc8e8d483
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 105 additions and 37 deletions

View file

@ -58,7 +58,7 @@ void ADCSensor::update() {
} }
float ADCSensor::sample() { float ADCSensor::sample() {
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
float value_v = analogRead(this->pin_) / 4095.0f; float value_v = analogRead(this->pin_) / 4095.0f; // NOLINT
switch (this->attenuation_) { switch (this->attenuation_) {
case ADC_0db: case ADC_0db:
value_v *= 1.1; value_v *= 1.1;
@ -80,7 +80,7 @@ float ADCSensor::sample() {
#ifdef USE_ADC_SENSOR_VCC #ifdef USE_ADC_SENSOR_VCC
return ESP.getVcc() / 1024.0f; return ESP.getVcc() / 1024.0f;
#else #else
return analogRead(this->pin_) / 1024.0f; return analogRead(this->pin_) / 1024.0f; // NOLINT
#endif #endif
#endif #endif
} }

View file

@ -101,7 +101,7 @@ void MAX7219Component::loop() {
} }
void MAX7219Component::display() { void MAX7219Component::display() {
byte pixels[8]; uint8_t pixels[8];
// Run this loop for every MAX CHIP (GRID OF 64 leds) // Run this loop for every MAX CHIP (GRID OF 64 leds)
// Run this routine for the rows of every chip 8x row 0 top to 7 bottom // Run this routine for the rows of every chip 8x row 0 top to 7 bottom
// Fill the pixel parameter with diplay data // Fill the pixel parameter with diplay data
@ -205,29 +205,32 @@ void MAX7219Component::scroll_left() {
this->stepsleft_++; this->stepsleft_++;
} }
void MAX7219Component::send_char(byte chip, byte data) { void MAX7219Component::send_char(uint8_t chip, uint8_t data) {
// get this character from PROGMEM // get this character from PROGMEM
for (byte i = 0; i < 8; i++) for (uint8_t i = 0; i < 8; i++)
this->max_displaybuffer_[chip * 8 + i] = pgm_read_byte(&MAX7219_DOT_MATRIX_FONT[data][i]); this->max_displaybuffer_[chip * 8 + i] = pgm_read_byte(&MAX7219_DOT_MATRIX_FONT[data][i]);
} // end of send_char } // end of send_char
// send one character (data) to position (chip) // send one character (data) to position (chip)
void MAX7219Component::send64pixels(byte chip, const byte pixels[8]) { void MAX7219Component::send64pixels(uint8_t chip, const uint8_t pixels[8]) {
for (byte col = 0; col < 8; col++) { // RUN THIS LOOP 8 times until column is 7 for (uint8_t col = 0; col < 8; col++) { // RUN THIS LOOP 8 times until column is 7
this->enable(); // start sending by enabling SPI this->enable(); // start sending by enabling SPI
for (byte i = 0; i < chip; i++) // send extra NOPs to push the pixels out to extra displays for (uint8_t i = 0; i < chip; i++) // send extra NOPs to push the pixels out to extra displays
this->send_byte_(MAX7219_REGISTER_NOOP, this->send_byte_(MAX7219_REGISTER_NOOP,
MAX7219_REGISTER_NOOP); // run this loop unit the matching chip is reached MAX7219_REGISTER_NOOP); // run this loop unit the matching chip is reached
byte b = 0; // rotate pixels 90 degrees -- set byte to 0 uint8_t b = 0; // rotate pixels 90 degrees -- set byte to 0
if (this->orientation_ == 0) { if (this->orientation_ == 0) {
for (byte i = 0; i < 8; i++) // run this loop 8 times for all the pixels[8] received for (uint8_t i = 0; i < 8; i++) {
b |= bitRead(pixels[i], col) << (7 - i); // change the column bits into row bits // run this loop 8 times for all the pixels[8] received
b |= ((pixels[i] >> col) & 1) << (7 - i); // change the column bits into row bits
}
} else if (this->orientation_ == 1) { } else if (this->orientation_ == 1) {
b = pixels[col]; b = pixels[col];
} else if (this->orientation_ == 2) { } else if (this->orientation_ == 2) {
for (byte i = 0; i < 8; i++) for (uint8_t i = 0; i < 8; i++) {
b |= bitRead(pixels[i], 7 - col) << (7 - i); b |= ((pixels[i] >> (7 - col)) << (7 - i));
}
} else { } else {
b = pixels[7 - col]; b = pixels[7 - col];
} }
@ -246,8 +249,8 @@ void MAX7219Component::send64pixels(byte chip, const byte pixels[8]) {
uint8_t MAX7219Component::printdigit(const char *str) { return this->printdigit(0, str); } uint8_t MAX7219Component::printdigit(const char *str) { return this->printdigit(0, str); }
uint8_t MAX7219Component::printdigit(uint8_t start_pos, const char *s) { uint8_t MAX7219Component::printdigit(uint8_t start_pos, const char *s) {
byte chip; uint8_t chip = start_pos;
for (chip = start_pos; chip < this->num_chips_ && *s; chip++) for (; chip < this->num_chips_ && *s; chip++)
send_char(chip, *s++); send_char(chip, *s++);
// space out rest // space out rest
while (chip < (this->num_chips_)) while (chip < (this->num_chips_))

View file

@ -19,10 +19,10 @@ void MCP3008::dump_config() {
} }
float MCP3008::read_data_(uint8_t pin) { float MCP3008::read_data_(uint8_t pin) {
byte data_msb = 0; uint8_t data_msb = 0;
byte data_lsb = 0; uint8_t data_lsb = 0;
byte command = ((0x01 << 7) | // start bit uint8_t command = ((0x01 << 7) | // start bit
((pin & 0x07) << 4)); // channel number ((pin & 0x07) << 4)); // channel number
this->enable(); this->enable();

View file

@ -10,17 +10,17 @@ void SN74HC595Component::setup() {
ESP_LOGCONFIG(TAG, "Setting up SN74HC595..."); ESP_LOGCONFIG(TAG, "Setting up SN74HC595...");
if (this->have_oe_pin_) { // disable output if (this->have_oe_pin_) { // disable output
pinMode(this->oe_pin_->get_pin(), OUTPUT); this->oe_pin_->pin_mode(OUTPUT);
digitalWrite(this->oe_pin_->get_pin(), HIGH); this->oe_pin_->digital_write(true);
} }
// initialize output pins // initialize output pins
pinMode(this->clock_pin_->get_pin(), OUTPUT); this->clock_pin_->pin_mode(OUTPUT);
pinMode(this->data_pin_->get_pin(), OUTPUT); this->data_pin_->pin_mode(OUTPUT);
pinMode(this->latch_pin_->get_pin(), OUTPUT); this->latch_pin_->pin_mode(OUTPUT);
digitalWrite(this->clock_pin_->get_pin(), LOW); this->clock_pin_->digital_write(LOW);
digitalWrite(this->data_pin_->get_pin(), LOW); this->data_pin_->digital_write(LOW);
digitalWrite(this->latch_pin_->get_pin(), LOW); this->latch_pin_->digital_write(LOW);
// send state to shift register // send state to shift register
this->write_gpio_(); this->write_gpio_();
@ -28,26 +28,33 @@ void SN74HC595Component::setup() {
void SN74HC595Component::dump_config() { ESP_LOGCONFIG(TAG, "SN74HC595:"); } void SN74HC595Component::dump_config() { ESP_LOGCONFIG(TAG, "SN74HC595:"); }
bool SN74HC595Component::digital_read_(uint8_t pin) { return bitRead(this->output_bits_, pin); } bool SN74HC595Component::digital_read_(uint8_t pin) { return this->output_bits_ >> pin; }
void SN74HC595Component::digital_write_(uint8_t pin, bool value) { void SN74HC595Component::digital_write_(uint8_t pin, bool value) {
bitWrite(this->output_bits_, pin, value); uint32_t mask = 1UL << pin;
this->output_bits_ &= ~mask;
if (value)
this->output_bits_ |= mask;
this->write_gpio_(); this->write_gpio_();
} }
bool SN74HC595Component::write_gpio_() { bool SN74HC595Component::write_gpio_() {
for (int i = this->sr_count_ - 1; i >= 0; i--) { for (int i = this->sr_count_ - 1; i >= 0; i--) {
uint8_t data = (uint8_t)(this->output_bits_ >> (8 * i) & 0xff); uint8_t data = (uint8_t)(this->output_bits_ >> (8 * i) & 0xff);
shiftOut(this->data_pin_->get_pin(), this->clock_pin_->get_pin(), MSBFIRST, data); for (int j = 0; j < 8; j++) {
this->data_pin_->digital_write(data & (1 << (7 - j)));
this->clock_pin_->digital_write(true);
this->clock_pin_->digital_write(false);
}
} }
// pulse latch to activate new values // pulse latch to activate new values
digitalWrite(this->latch_pin_->get_pin(), HIGH); this->latch_pin_->digital_write(true);
digitalWrite(this->latch_pin_->get_pin(), LOW); this->latch_pin_->digital_write(false);
// enable output if configured // enable output if configured
if (this->have_oe_pin_) { if (this->have_oe_pin_) {
digitalWrite(this->oe_pin_->get_pin(), LOW); this->oe_pin_->digital_write(false);
} }
return true; return true;

View file

@ -144,7 +144,7 @@ void SX1509Component::clock_(byte osc_source, byte osc_pin_function, byte osc_fr
osc_source = (osc_source & 0b11) << 5; // 2-bit value, bits 6:5 osc_source = (osc_source & 0b11) << 5; // 2-bit value, bits 6:5
osc_pin_function = (osc_pin_function & 1) << 4; // 1-bit value bit 4 osc_pin_function = (osc_pin_function & 1) << 4; // 1-bit value bit 4
osc_freq_out = (osc_freq_out & 0b1111); // 4-bit value, bits 3:0 osc_freq_out = (osc_freq_out & 0b1111); // 4-bit value, bits 3:0
byte reg_clock = osc_source | osc_pin_function | osc_freq_out; uint8_t reg_clock = osc_source | osc_pin_function | osc_freq_out;
this->write_byte(REG_CLOCK, reg_clock); this->write_byte(REG_CLOCK, reg_clock);
osc_divider = constrain(osc_divider, 1, 7); osc_divider = constrain(osc_divider, 1, 7);

View file

@ -17,7 +17,8 @@ void UltrasonicSensorComponent::update() {
delayMicroseconds(this->pulse_time_us_); delayMicroseconds(this->pulse_time_us_);
this->trigger_pin_->digital_write(false); this->trigger_pin_->digital_write(false);
uint32_t time = pulseIn(this->echo_pin_->get_pin(), uint8_t(!this->echo_pin_->is_inverted()), this->timeout_us_); uint32_t time = pulseIn( // NOLINT
this->echo_pin_->get_pin(), uint8_t(!this->echo_pin_->is_inverted()), this->timeout_us_);
ESP_LOGV(TAG, "Echo took %uµs", time); ESP_LOGV(TAG, "Echo took %uµs", time);

View file

@ -255,6 +255,63 @@ def lint_conf_from_const_py(fname, match):
"const.py directly.".format(highlight(name))) "const.py directly.".format(highlight(name)))
RAW_PIN_ACCESS_RE = r'^\s(pinMode|digitalWrite|digitalRead)\((.*)->get_pin\(\),\s*([^)]+).*\)'
@lint_re_check(RAW_PIN_ACCESS_RE, include=cpp_include)
def lint_no_raw_pin_access(fname, match):
func = match.group(1)
pin = match.group(2)
mode = match.group(3)
new_func = {
'pinMode': 'pin_mode',
'digitalWrite': 'digital_write',
'digitalRead': 'digital_read',
}[func]
new_code = highlight(f'{pin}->{new_func}({mode})')
return (f"Don't use raw {func} calls. Instead, use the `->{new_func}` function: {new_code}")
# Functions from Arduino framework that are forbidden to use directly
ARDUINO_FORBIDDEN = [
'digitalWrite', 'digitalRead', 'pinMode',
'shiftOut', 'shiftIn',
'radians', 'degrees',
'interrupts', 'noInterrupts',
'lowByte', 'highByte',
'bitRead', 'bitSet', 'bitClear', 'bitWrite',
'bit', 'analogRead', 'analogWrite',
'pulseIn', 'pulseInLong',
'tone',
]
ARDUINO_FORBIDDEN_RE = r'[^\w\d](' + r'|'.join(ARDUINO_FORBIDDEN) + r')\(.*'
@lint_re_check(ARDUINO_FORBIDDEN_RE, include=cpp_include, exclude=[
'esphome/components/mqtt/custom_mqtt_device.h',
'esphome/core/esphal.*',
])
def lint_no_arduino_framework_functions(fname, match):
nolint = highlight("// NOLINT")
return (
f"The function {highlight(match.group(1))} from the Arduino framework is forbidden to be "
f"used directly in the ESPHome codebase. Please use ESPHome's abstractions and equivalent "
f"C++ instead.\n"
f"\n"
f"(If the function is strictly necessary, please add `{nolint}` to the end of the line)"
)
@lint_re_check(r'[^\w\d]byte\s+[\w\d]+\s*=.*', include=cpp_include, exclude={
'esphome/components/tuya/tuya.h',
})
def lint_no_byte_datatype(fname, match):
return (
f"The datatype {highlight('byte')} is not allowed to be used in ESPHome. "
f"Please use {highlight('uint8_t')} instead."
)
@lint_post_check @lint_post_check
def lint_constants_usage(): def lint_constants_usage():
errors = [] errors = []