Linux Peripheral Features
Contents
ADC
System that converts an analog signal into a digital signal.
- ROM-5420
ROM-5420 support ADC read-out through the battery driver
# cat /sys/class/power_supply/battery/uevent POWER_SUPPLY_NAME=battery POWER_SUPPLY_STATUS=Charging POWER_SUPPLY_HEALTH=Good POWER_SUPPLY_PRESENT=1 POWER_SUPPLY_TECHNOLOGY=Li-ion POWER_SUPPLY_CYCLE_COUNT=-1472729340 POWER_SUPPLY_VOLTAGE_NOW=8340 POWER_SUPPLY_CURRENT_NOW=648 POWER_SUPPLY_CAPACITY=96 POWER_SUPPLY_TEMP=25 POWER_SUPPLY_TIME_TO_EMPTY_AVG=0 POWER_SUPPLY_TIME_TO_FULL_AVG=0 POWER_SUPPLY_SERIAL_NUMBER=0000 POWER_SUPPLY_VOLTAGE_MAX_DESIGN=0 POWER_SUPPLY_ENERGY_NOW=149457984 POWER_SUPPLY_ENERGY_FULL=149457984 POWER_SUPPLY_ENERGY_FULL_DESIGN=149457984 POWER_SUPPLY_CHARGE_NOW=-1472729340 POWER_SUPPLY_CHARGE_FULL=-1472729340 POWER_SUPPLY_CHARGE_FULL_DESIGN=-1472729340
Audio
Sound Card
# cat /proc/asound/cards 0 [sgtl5000 ]: sgtl5000 - sgtl5000 sgtl5000 1 [imxspdif ]: imx-spdif - imx-spdif imx-spdif 2 [imxhdmisoc ]: imx-hdmi-soc - imx-hdmi-soc imx-hdmi-soc
Adjust
amixer set Mic 100% amixer set Headphone 100%
Record
Record wav file for 5 secs
# arecord -t wav -c 1 -r 44100 -d 5 test.wav
Playback
Playback
# aplay test.wav
Playback on another sound card
# aplay -l **** List of PLAYBACK Hardware Devices **** card 0: sgtl5000 [sgtl5000], device 0: HiFi sgtl5000-0 [] Subdevices: 1/1 Subdevice #0: subdevice #0 card 1: imxspdif [imx-spdif], device 0: S/PDIF PCM snd-soc-dummy-dai-0 [] Subdevices: 1/1 Subdevice #0: subdevice #0 card 2: imxhdmisoc [imx-hdmi-soc], device 0: i.MX HDMI Audio Tx hdmi-hifi-0 [] Subdevices: 1/1 Subdevice #0: subdevice #0
Playback on SPDIF (card 1,Subdevice 0)
# aplay -D plughw:1,0 Advantech.wav
Playback on HDMI (card 2,Subdevice 0)
# aplay -D plughw:2,0 Advantech.wav
Backlight
The relevant files
/sys/class/graphics/fb0 /sys/devices/platform/mxc_sdc_fb.1/graphics/fb0 /sys/devices/platform/mxc_sdc_fb.1/graphics/fb0/power /sys/devices/platform/mxc_sdc_fb.1 /sys/class/graphics /sys/class/backlight /sys/class/backlight/pwm-backlight.0
Turn off
echo 1 > /sys/class/backlight/pwm-backlight.0/bl_power
Turn on
echo 0 > /sys/class/backlight/pwm-backlight.0/bl_power
Brightness control
echo 0 > /sys/class/backlight/pwm-backlight.0/brightness echo 255 > /sys/class/backlight/pwm-backlight.0/brightness
Camera
Test
- Preview
# gst-launch-1.0 imxv4l2src device=/dev/video0 ! 'video/x-raw,format=NV12,width=1920,height=1080,framerate=30/1' ! imxv4l2sink
- Capture
# gst-launch-1.0 imxv4l2src num-buffers=1 ! jpegenc ! filesink location=test.jpeg
- View
# VSALPHA=1 gst-launch-1.0 filesrc location=test.jpeg ! jpegdec ! imagefreeze ! imxv4l2sink
- Record
# gst-launch-1.0 imxv4l2src device=/dev/video0 num-buffers=300 ! 'video/x-raw,format=NV12,width=1920,height=1080,framerate=30/1' ! queue ! vpuenc_h264 ! matroskamux ! filesink location=output.avi
- Play Video
# gst-launch-1.0 playbin uri=file:////home/root/output.avi
CAN Bus
Configuration/Test
Configuration
- Connect can0 and can1
<CAN1_D+> connect to <CAN2_D+>
<CAN1_D-> connect to <CAN2_D->
# ip link set can0 up type can bitrate 125000 # ip link set can1 up type can bitrate 125000
Test
- Test 1
# candump can1 & # cansend can0 12345678#123412341234
The following shows the result
can1 12345678 [6] 12 34 12 34 12 34
- Test 2
# cansend can0 133#ababdede
The following shows the result
can1 133 [4] AB AB DE DE
CPU
CPU Frequency
- Using available CPU frequency policies
Read CPU frequency
# cpufreq-info | grep "current CPU frequency" current CPU frequency is 396 MHz (asserted by call to hardware). current CPU frequency is 396 MHz (asserted by call to hardware). current CPU frequency is 396 MHz (asserted by call to hardware). current CPU frequency is 396 MHz (asserted by call to hardware).
Check available CPU frequency policy
# cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors conservative ondemand userspace powersave interactive performance
Change CPU frequency policy
# echo performance > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
Check CPU frequency
# cpufreq-info | grep "current CPU frequency" current CPU frequency is 996 MHz (asserted by call to hardware). current CPU frequency is 996 MHz (asserted by call to hardware). current CPU frequency is 996 MHz (asserted by call to hardware). current CPU frequency is 996 MHz (asserted by call to hardware).
- Setting the CPU frequency explicitly
Read available CPU frequenies
# cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies 396000 792000 996000
Change CPU frequency explicitly
# echo userspace > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor # echo 792000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed
Check CPU frequency
# cpufreq-info | grep "current CPU frequency" current CPU frequency is 792 MHz (asserted by call to hardware). current CPU frequency is 792 MHz (asserted by call to hardware). current CPU frequency is 792 MHz (asserted by call to hardware). current CPU frequency is 792 MHz (asserted by call to hardware).
CPU Hot-Plugging
Manually turn off CPU cores
#echo 0 > /sys/devices/system/cpu/cpu1/online CPU1: shutdown
- Can't turn off cpu0
Check CPU is turned off
#cat /proc/interrupts | head -n 1 CPU0 CPU2 CPU3
Ethernet
Ethernet Speed
Depend on connect device
#ethtool eth0 | grep -i speed Speed: 100Mb/s
iPerf
- host
Host ip is 192.168.0.2 #iperf -s
- target
#iperf -c 192.168.0.2 -w 100M -t 60 -i 10 ------------------------------------------------------------ Client connecting to 192.168.0.2, TCP port 5001 TCP window size: 320 KByte (WARNING: requested 100 MByte) ------------------------------------------------------------ [ 3] local 192.168.0.1 port 35389 connected with 192.168.0.2 port 5001 [ ID] Interval Transfer Bandwidth [ 3] 0.0-10.0 sec 560 MBytes 470 Mbits/sec [ 3] 10.0-20.0 sec 554 MBytes 465 Mbits/sec [ 3] 20.0-30.0 sec 537 MBytes 450 Mbits/sec [ 3] 30.0-40.0 sec 553 MBytes 464 Mbits/sec [ 3] 40.0-50.0 sec 557 MBytes 468 Mbits/sec [ 3] 50.0-60.0 sec 542 MBytes 455 Mbits/sec [ 3] 0.0-60.0 sec 3.23 GBytes 462 Mbits/sec
Debug
If you can not ping 8.8.8.8. please try to send command: /etc/init.d/networking restart
Framebuffer
The frame buffer device provides an abstraction for the graphics hardware. It represents the frame buffer of some video hardware and allows application software to access the graphics hardware through a well-defined interface, so the software doesn't need to know anything about the low-level (hardware register) stuff.
The device is accessed through special device nodes, usually located in the /dev directory, i.e. /dev/fb*.
Get Display Mode
Refer to link as below:
Get framebuffer device
- i.MX series
# cat /sys/class/graphics/fb*/fsl_disp_dev_property hdmi overlay lcd overlay ldb
Test
Playing different videos on different displays
- i.MX series
Modify display device parameters
i.MX 6Q/D
- /usr/share/imx_6q_display_config
i.MX 6 Solo
- /usr/share/imx_6sx_display_config
The following is an example of the display configuration for dual display mode, HDMI(master) + LCD(slave)+ LVDS(slave).
[hdmi] device = /dev/video17 fmt = RGBP width = 1920 height = 1080 [lcd] device = /dev/video18 fmt = RGBP width = 1920 height = 1080 [ldb] device = /dev/video20 fmt = RGBP width = 800 height = 480 alpha = 0
Play video on HDMI
# gst-launch-1.0 playbin uri=file:////tools/Advantech.avi
Play video on HDMI+VGA
# gst-launch-1.0 playbin uri=file:////tools/Advantech.avi video-sink="overlaysink display-lcd=true"
Play video on HDMI+VGA+LVDS
# gst-launch-1.0 playbin uri=file:////tools/Advantech.avi video-sink="overlaysink display-lcd=true display-ldb=true"
GPIO
Configuration/Test
Configuration
Export GPIO then you can use control GPIO from userr space through sysfs
GPIO 27 is taken as an example:
Export GPIO 27
# echo 27 > /sys/class/gpio/export
Set GPIO direction to in/out .
Note: gpio27 will be export to gpio1
If we export the second gpio, it will be export to gpio2, and so on.
# echo "in" > /sys/class/gpio/gpio1/direction
Set GPIO value 0/1 if GPIO pin define is output
# echo 1 > /sys/class/gpio/gpio1/value
Directly force a GPIO to output and set its initial value(high=1 low=0)
# echo high > /sys/class/gpio/gpio1/direction
Used as IRQ signal
Note:You have to configure GPIO to input
# echo "rising" > /sys/class/gpio/gpio1/edge
- rising: Trigger on rising edge
- falling: Trigger on falling edge
- both: Trigger on both edges
- none: Disable interrupt on both edges
Unexport GPIO 27
# echo 27 > /sys/class/gpio/unexport
Test
GPIO 27 and GPIO 29 are taken as an example:
- Connect GPIO 27 and GPIO 29
- Export GPIO 27 and GPIO 29
# echo 27 > /sys/class/gpio/export # echo 29 > /sys/class/gpio/export
- Set GPIO 27 to output
# echo "out" > /sys/class/gpio/gpio1/direction
- Set GPIO 29 to input
# echo "in" > /sys/class/gpio/gpio2/direction
- Change GPIO 27 to 1 and read GPIO 29 value
# echo 1 > /sys/class/gpio/gpio1/value # cat /sys/class/gpio/gpio2/value 1
- Change GPIO 27 to 0 and read GPIO 29 value
# echo 0 > /sys/class/gpio/gpio1/value # cat /sys/class/gpio/gpio2/value 0
GPS
GPS module ublox 5
- linux kernel config
- Device Drivers --->
- [*] USB support --->
- <*> USB Modem (CDC ACM) support
- [*] USB Gadget Support
- [m] USB Gadget Drivers
- [*] USB support --->
- Device Drivers --->
- [*] USB support --->
- [*] Support for Freescale on-chip EHCI USB controller
- <*> USB Serial Converter support --->
- [*] USB Generic Serial Driver
- [*] USB support --->
I2C
Test
Check i2c busses
- Usage: i2cdetect [-y] [-a] [-q|-r] I2CBUS [FIRST LAST]
#i2cdetect -l i2c-0 i2c 21a0000.i2c I2C adapter i2c-1 i2c 21a4000.i2c I2C adapter i2c-2 i2c 21a8000.i2c I2C adapter
Check devices on i2c-2 bus
#i2cdetect -y -r 2 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: UU UU -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- UU --
Dump I2C device register content
- Usage: i2cdump [-f] [-y] [-r first-last] I2CBUS ADDRESS [MODE [BANK [BANKREG]]]
# i2cdump -y -f 2 0x76 No size specified (using byte-data access) 0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef 00: 54 00 80 43 40 40 40 00 00 00 00 00 00 00 ff ff T.?C@@@S........ 10: 85 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ?............... 20: 00 00 00 18 ff ff ff ff ff ff ff ff ff ff ff ff ...?............ 30: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................ 40: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................ 50: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................ 60: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................ 70: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................ 80: 54 00 80 43 40 40 40 53 00 00 00 00 00 00 ff ff T.?C@@@S........ 90: 85 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ?............... a0: 00 00 00 18 ff ff ff ff ff ff ff ff ff ff ff ff ...?............ b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................ c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................ d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................ e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................ f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
Read a single byte
- Usage: i2cget [-f] [-y] I2CBUS CHIP-ADDRESS [DATA-ADDRESS [MODE]]
# i2cget -f -y 2 0x76 7 0x00
Change its value and verify it
- Usage: i2cset [-f] [-y] [-m MASK] [-r] I2CBUS CHIP-ADDRESS DATA-ADDRESS [VALUE] ... [MODE]
# i2cset -f -y 2 0x76 7 0x53 # i2cget -f -y 2 0x76 7 0x53
IR
To decode the infrared signals and provide an uniform interface
lircd -d /dev/lirc0
used parameters:
-d --device=device read from given device -u --uinput generate Linux input events
Executes commands on an IR signal decoded by lircd,
irexec -d /devlirc0
Note: if show these message after running lircd
lircd: can't open or create /var/run/lirc/lircd.pid lircd: No such file or directory
It has to add the "/var/run/lirc" folder
mkdir /var/run/lirc
How to debug:
1. To check that signals are decoded correctly
mode2 -d /dev/lirc0
It repeats to show "space" and "pulse" while clicking a control button
space 8451531 pulse 476
2. To check input events.
First, It must add the parameter,"-u", in lircd command
lircd -d /dev/lirc0 -u
It will register at inputX,
input: lircd as /devices/virtual/input/input1
Run evtest to check events
evtest -d /dev/input/event1
One Wire
Example
RTC
Test
Confirm Which RTC
rtc-s35390a is taken as an example:
# dmesg| grep rtc0 [ 1.644600] rtc-s35390a 0-0030: rtc core: registered rtc-s35390a as rtc0
rtc-s35390a is rtc0
Set system time to current, then write to RTC
# date 021710452016 && hwclock -w && date Wed Feb 17 10:45:00 UTC 2016 Wed Feb 17 10:45:00 UTC 2016
Set one incorrect time, then read time from RTC to verify
# date 010100002000 && hwclock -r && date Sat Jan 1 00:00:00 UTC 2000 Wed Feb 17 10:45:32 2016 0.000000 seconds Sat Jan 1 00:00:00 UTC 2000
Restore the RTC time to system time
# hwclock -s && date Wed Feb 17 10:46:26 UTC 2016
SATA
SATA speed
Check SATA speed
# dmesg| grep "SATA link up" [ 1.983660] ata1: SATA link up 3.0 Gbps (SStatus 123 SControl 300)
Change SATA speed
- Add 'libata.force=1.5Gbps' to kernel boot arguments in U-boot
#setenv sataargs $sataargs libata.force=1.5Gbps
Verify
# dmesg| grep "SATA link up" [ 1.993678] ata1: SATA link up 1.5 Gbps (SStatus 113 SControl 310)
Test
Insert SATA disk before boot
#find /sys/ . -name block | grep ata | xargs ls $1 sda
- According to the above content, we can know sda is our SATA disk
Generate random file
# dd if=/dev/urandom of=data bs=1 count=1024
Back up
# dd if=/dev/sda of=backup bs=1 count=1024 skip=4096
Write to SATA disk
# dd if=data of=/dev/sda bs=1 seek=4096
Read and Verify
# dd if=/dev/sda of=data1 bs=1 count=1024 skip=4096 # diff data data1
If fail, it shows as below:
Binary files data1 and data differ
Restore
# dd if=backup of=/dev/sda bs=1 seek=4096
SD/MMC
Test
Check sysfs node
# cat /sys/block/mmcblk0/device/type MMC # cat /sys/block/mmcblk1/device/type SD
SD Card is taken as an example:
Generate random file
# dd if=/dev/urandom of=data bs=1 count=1024
Back up
# dd if=/dev/mmcblk1 of=backup bs=1 count=1024 skip=4096
Write to SD
# dd if=data of=/dev/mmcblk1 bs=1 seek=4096
Read and Verify
# dd if=/dev/mmcblk1 of=data1 bs=1 count=1024 skip=4096 # diff data data1
If fail, it shows as below:
Binary files data1 and data differ
Restore
# dd if=backup of=/dev/mmcblk1 bs=1 seek=4096
SPI
The "Serial Peripheral Interface" (SPI) is a synchronous four wire serial link used to connect microcontrollers to sensors, memory, and peripherals.
Test
spi flash(m25p80 is taken as an example:
Generate random file
# dd if=/dev/urandom of=data bs=1 count=1024
Back up
# dd if=/dev/mtdblock1 of=backup bs=1 count=1024 skip=$((0xD3000))
Write to mtdblock1
# dd if=data of=/dev/mtdblock1 bs=1 seek=$((0xD3000))
Read and Verify
# dd if=/dev/mtdblock1 of=data1 bs=1 count=1024 skip=$((0xD3000)) # diff data data1
If fail, it shows as below:
Binary files data1 and data differ
Restore
# dd if=backup of=/dev/mtdblock1 bs=1 seek=$((0xD3000))
How to recognize W25Q64FV
The following operations demonstrate how to customize 7420LBV2330 to recognize the two W25Q64FVs on customized carrier board with ROM-7420 connected.
- linux kernel
$ echo "This is a mtd1." | dd of=/dev/mtdblock1 bs=1 seek=0 2>/dev/null
$ echo "This is a mtd2." | dd of=/dev/mtdblock2 bs=1 seek=0 2>/dev/null
$ dd if=/dev/mtdblock1 bs=1 count=32 2>/dev/null | hexdump -C
$ dd if=/dev/mtdblock2 bs=1 count=32 2>/dev/null | hexdump -C
- u-boot
- patch u-boot by u-boot-2009.08_spi5_w25q64.patch
- rebuild the u-boot image
- practical test
> sf probe 4:0; sf read 0x10800000 0 10; md.b 0x10800000 10
> sf probe 4:1; sf read 0x10800000 0 10; md.b 0x10800000 10
SPWG/JEDIA
Standard Panels Working Group (SPWG)
Japan Electronic Industry Development Association (JEIDA)
How to setting SPWG/JEIDA mode in RISC?
Modify Register GPR(IOMUXC_GPR2)value
Address : 0x020E0008(h)
BIT6 and BIT8 set "0" (SPWG)
BIT6 and BIT8 set "1" (JEIDA)
UART
RS-232
Configuration
Connect UART1(ttymxc1) TX and RX
Use stty command to set baudrate
# stty -F /dev/ttymxc1 115200
Test
Check baudrate
# stty -F /dev/ttymxc1 115200 speed 115200 baud; line = 0;
Read
#cat /dev/ttymxc1 &
Send
#echo test > /dev/ttymxc1 test
RS-485
Configuration
Connect D+ and D- to ADAM-4520
- Method 1:
Use File:enable485.zip to enable rs-485 function via ioctl
Copy enable485 to our device
enable485 /dev/ttymxc4
- Method 2:
modify dts file to enable rs-485 at boot time. (for Yocto 2.5 and later, must get the newest bsp)
&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart1>;
fsl,uart-has-rtscts;
linux,rs485-enabled-at-boot-time;
rs485-rx-during-tx;
rs485-rts-active-low;
status = "okay";
};
And setup minicom on our device and PC
- Turn off hardware flow control
- Baudrate 115200
Then open minicom on both PC and our device.
We can send message to each side to confirm rs-485 function.
USB
Host
Test
Insert a USB disk
usb 1-1.2: new high-speed USB device number 4 using ci_hdrc usb-storage 1-1.2:1.0: USB Mass Storage device detected scsi2 : usb-storage 1-1.2:1.0 scsi 2:0:0:0: Direct-Access Generic- SD/MMC 1.00 PQ: 0 ANSI: 0 CCS sd 2:0:0:0: [sda] 3862528 512-byte logical blocks: (1.97 GB/1.84 GiB) sd 2:0:0:0: [sda] Write Protect is off sd 2:0:0:0: [sda] No Caching mode page found sd 2:0:0:0: [sda] Assuming drive cache: write through sd 2:0:0:0: [sda] No Caching mode page found sd 2:0:0:0: [sda] Assuming drive cache: write through sda: sda1 sd 2:0:0:0: [sda] No Caching mode page found sd 2:0:0:0: [sda] Assuming drive cache: write through sd 2:0:0:0: [sda] Attached SCSI removable disk
- According to the above content, we can know sda is our usb disk
Generate random file
# dd if=/dev/urandom of=data bs=1 count=1024
Back up
# dd if=/dev/sda of=backup bs=1 count=1024 skip=4096
Write to usb disk
# dd if=data of=/dev/sda bs=1 seek=4096
Read and Verify
# dd if=/dev/sda of=data1 bs=1 count=1024 skip=4096 # diff data data1
If fail, it shows as below:
Binary files data1 and data differ
Restore
# dd if=backup of=/dev/sda bs=1 seek=4096
Client
Test
Watchdog
Instroduction
Introduction:
A Watchdog Timer (WDT) is a hardware circuit that can reset the computer system in case of a software fault.
Watchdog API
You can refer to the path as below in kernel source code to write a simple program to test watchdog
Documentation/watchdog/watchdog-api.txt
Example
- i.MX series
NXP has written a tool to test watchdog in /unit_tests/
1.Executing wdt_driver_test.out
#/unit_tests/wdt_driver_test.out Usage: wdt_driver_test <timeout> <sleep> <test> timeout: value in seconds to cause wdt timeout/reset sleep: value in seconds to service the wdt test: 0 - Service wdt with ioctl(), 1 - with write()
2.Please try below command to set timeout as 10 seconds, system will reboot after then.
#/unit_tests/wdt_driver_test.out 10 5 0 Starting wdt_driver (timeout: 10, sleep: 5, test: ioctl) Trying to set timeout value=10 seconds The actual timeout was set to 10 seconds Now reading back -- The timeout is 10 seconds Press [CTRL+C] then you should be able to see below result:
3.Press "ctrl+c"
imx2-wdt imx2-wdt.0: Unexpected close: Expect reboot! Then system will reboot in 10 second
Led
If we have already defined Leds, we can see leds label as below
# ls /sys/class/leds/ Green_Led Red_Led mmc1:: mmc2:: mmc3::
Red_Led is taken as an example:
- turn off
# echo 0 > /sys/class/leds/Red_Led/brightness
- turn on
# echo 255 > /sys/class/leds/Red_Led/brightness