lgpio 0.1.9 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 968e706762503c9d172b41ff4df8a9c17021af5b4a4cb4372eeaaa166c30f5ff
4
- data.tar.gz: 82d8221f8e28293f542c4bd1913f85addb567c217d071fdbb1e47451c3be1da1
3
+ metadata.gz: 4da526bc3f239adf23035ca2c8923463667f979038b01fe0f8b63f0ad017a0e1
4
+ data.tar.gz: 6beafa4839875a6aac25f78a0b4b3e4fa25a28569269254ec4dcea27bfc06572
5
5
  SHA512:
6
- metadata.gz: 8749280110629032e20ac94c203c512a699e90b58266f78f7c26a9305b8e22ef0f97822247744403c2723b7417838b5972c2618a65ebcb0ee2ae483cd0d12e41
7
- data.tar.gz: a9bbac8e2f8c80de6adf86249bf559b10c590234597a15d3bf6dce37bc3b60ce27856f2343bdc1fe885a1a78105401419e221eb0ae5a10fa404ec7fc9c90a4fd
6
+ metadata.gz: af9365d7c43fc0f7d5bab7c360e5a2e9325f2c3f7b7015ffff39d98ee3c4c2041123dfb81354d5d0113a06daab31910d18ed3fcee91dd75ded80c13b87543cba
7
+ data.tar.gz: aef0e2f50840a3b601627283f15df63f1f6ab5d065288f05275c07d04e0ad32def28d055acedfbba807c16f16b041d2df3bd5444f093bbb55c604aac2026c4ac
@@ -9,13 +9,19 @@ SOFT_RESET = [0xBA]
9
9
  INIT_AND_CALIBRATE = [0xE1, 0x08, 0x00]
10
10
  START_MEASUREMENT = [0xAC, 0x33, 0x00]
11
11
 
12
- GPIO_CHIP = 0
12
+ SCL_CHIP = 0
13
13
  SCL_PIN = 228
14
+ SDA_CHIP = 0
14
15
  SDA_PIN = 270
15
16
  ADDRESS = 0x38
16
17
 
17
- chip_handle = LGPIO.chip_open(GPIO_CHIP)
18
- i2c_bb = LGPIO::I2CBitBang.new(chip_handle, SCL_PIN, SDA_PIN)
18
+ scl_handle = LGPIO.chip_open(SCL_CHIP)
19
+ sda_handle = (SCL_CHIP == SDA_CHIP) ? scl_handle : LGPIO.chip_open(SDA_CHIP)
20
+ pin_hash = {
21
+ scl: { handle: scl_handle, line: SCL_PIN },
22
+ sda: { handle: sda_handle, line: SDA_PIN },
23
+ }
24
+ i2c_bb = LGPIO::I2CBitBang.new(pin_hash)
19
25
 
20
26
  # Startup sequence
21
27
  sleep(POWER_ON_DELAY)
@@ -24,11 +30,15 @@ sleep(RESET_DELAY)
24
30
  i2c_bb.write(ADDRESS, INIT_AND_CALIBRATE)
25
31
  sleep(COMMAND_DELAY)
26
32
 
27
- # Read and close
33
+ # Read
28
34
  i2c_bb.write(ADDRESS, START_MEASUREMENT)
29
35
  sleep(MEASURE_DELAY)
30
36
  bytes = i2c_bb.read(ADDRESS, DATA_LENGTH)
31
37
 
38
+ # Close
39
+ LGPIO.chip_close(scl_handle)
40
+ LGPIO.chip_close(sda_handle) unless (scl_handle == sda_handle)
41
+
32
42
  # Humidity uses the upper 4 bits of the shared byte as its lowest 4 bits.
33
43
  h_raw = ((bytes[1] << 16) | (bytes[2] << 8) | (bytes[3])) >> 4
34
44
  humidity = (h_raw.to_f / 2**20) * 100
@@ -1,13 +1,23 @@
1
1
  require 'lgpio'
2
2
 
3
- GPIO_CHIP = 0
3
+ SCL_CHIP = 0
4
4
  SCL_PIN = 228
5
+ SDA_CHIP = 0
5
6
  SDA_PIN = 270
6
7
 
7
- chip_handle = LGPIO.chip_open(GPIO_CHIP)
8
- i2c_bb = LGPIO::I2CBitBang.new(chip_handle, SCL_PIN, SDA_PIN)
8
+ scl_handle = LGPIO.chip_open(SCL_CHIP)
9
+ sda_handle = (SCL_CHIP == SDA_CHIP) ? scl_handle : LGPIO.chip_open(SDA_CHIP)
10
+ pin_hash = {
11
+ scl: { handle: scl_handle, line: SCL_PIN },
12
+ sda: { handle: sda_handle, line: SDA_PIN },
13
+ }
14
+ i2c_bb = LGPIO::I2CBitBang.new(pin_hash)
15
+
9
16
  devices = i2c_bb.search
10
17
 
18
+ LGPIO.chip_close(scl_handle)
19
+ LGPIO.chip_close(sda_handle) unless (scl_handle == sda_handle)
20
+
11
21
  if devices.empty?
12
22
  puts "No devices found on I2C bus"
13
23
  else
@@ -5,13 +5,19 @@ START_ARRAY = [0, 33, 0, 127, 34, 0, 7]
5
5
  PATTERN_1 = [64] + Array.new(1024) { 0b00110011 }
6
6
  PATTERN_2 = [64] + Array.new(1024) { 0b11001100 }
7
7
 
8
- GPIO_CHIP = 0
8
+ SCL_CHIP = 0
9
9
  SCL_PIN = 228
10
+ SDA_CHIP = 0
10
11
  SDA_PIN = 270
11
12
  ADDRESS = 0x3C
12
13
 
13
- chip_handle = LGPIO.chip_open(GPIO_CHIP)
14
- i2c_bb = LGPIO::I2CBitBang.new(chip_handle, SCL_PIN, SDA_PIN)
14
+ scl_handle = LGPIO.chip_open(SCL_CHIP)
15
+ sda_handle = (SCL_CHIP == SDA_CHIP) ? scl_handle : LGPIO.chip_open(SDA_CHIP)
16
+ pin_hash = {
17
+ scl: { handle: scl_handle, line: SCL_PIN },
18
+ sda: { handle: sda_handle, line: SDA_PIN },
19
+ }
20
+ i2c_bb = LGPIO::I2CBitBang.new(pin_hash)
15
21
 
16
22
  i2c_bb.write(ADDRESS, INIT_ARRAY)
17
23
  FRAME_COUNT = 400
@@ -25,7 +31,8 @@ start = Time.now
25
31
  end
26
32
  finish = Time.now
27
33
 
28
- LGPIO.chip_close(chip_handle)
34
+ LGPIO.chip_close(scl_handle)
35
+ LGPIO.chip_close(sda_handle) unless (scl_handle == sda_handle)
29
36
 
30
37
  fps = FRAME_COUNT / (finish - start)
31
38
  # Also calculate C calls per second, using roughly 23 calls per byte written.
@@ -10,7 +10,12 @@ ORDERS = [:msbfirst, :lsbfirst]
10
10
  TX_BYTES = [0, 1, 2, 3, 4, 5, 6, 7]
11
11
 
12
12
  chip_handle = LGPIO.chip_open(GPIO_CHIP)
13
- spi_bb = LGPIO::SPIBitBang.new(handle: chip_handle, clock: CLOCK_PIN, input: INPUT_PIN, output: OUTPUT_PIN)
13
+ pin_hash = {
14
+ clock: { handle: chip_handle, line: CLOCK_PIN },
15
+ input: { handle: chip_handle, line: INPUT_PIN },
16
+ output: { handle: chip_handle, line: OUTPUT_PIN },
17
+ }
18
+ spi_bb = LGPIO::SPIBitBang.new(pin_hash)
14
19
 
15
20
  puts "TX bytes => #{TX_BYTES.inspect}"
16
21
 
@@ -12,7 +12,12 @@ PATTERN_2 = [0x3C << 1] + [64] + Array.new(1179) { 0b11001100 }
12
12
  FRAME_COUNT = 400
13
13
 
14
14
  chip_handle = LGPIO.chip_open(GPIO_CHIP)
15
- spi_bb = LGPIO::SPIBitBang.new(handle: chip_handle, clock: CLOCK_PIN, input: INPUT_PIN, output: OUTPUT_PIN)
15
+ pin_hash = {
16
+ clock: { handle: chip_handle, line: CLOCK_PIN },
17
+ input: { handle: chip_handle, line: INPUT_PIN },
18
+ output: { handle: chip_handle, line: OUTPUT_PIN },
19
+ }
20
+ spi_bb = LGPIO::SPIBitBang.new(pin_hash)
16
21
 
17
22
  start = Time.now
18
23
  (FRAME_COUNT / 2).times do
@@ -5,41 +5,55 @@ START_ARRAY = [0, 33, 0, 127, 34, 0, 7]
5
5
  PATTERN_1 = Array.new(1024) { 0b00110011 }
6
6
  PATTERN_2 = Array.new(1024) { 0b11001100 }
7
7
 
8
- GPIO_CHIP = 0
9
- CLOCK_PIN = 17
10
- OUTPUT_PIN = 27
11
- SELECT_PIN = 22
12
- RESET_PIN = 5
13
- DC_PIN = 6
14
-
15
- # Initialize
16
- chip_handle = LGPIO.chip_open(GPIO_CHIP)
17
- spi_bb = LGPIO::SPIBitBang.new(handle: chip_handle, clock: CLOCK_PIN, output: OUTPUT_PIN)
18
- LGPIO.gpio_claim_output(chip_handle, SELECT_PIN, LGPIO::SET_PULL_NONE, LGPIO::HIGH)
19
- LGPIO.gpio_claim_output(chip_handle, RESET_PIN, LGPIO::SET_PULL_NONE, LGPIO::LOW)
20
- LGPIO.gpio_claim_output(chip_handle, DC_PIN, LGPIO::SET_PULL_NONE, LGPIO::LOW)
8
+ # Pins for Radxa Zero 3W
9
+ # Demonstration of how to use GPIOs across multiple /dev/gpiochip devices.
10
+ pins = {
11
+ clock: { chip: 1, line: 4 },
12
+ output: { chip: 3, line: 4 },
13
+ reset: { chip: 3, line: 5 },
14
+ dc: { chip: 3, line: 6 },
15
+ cs: { chip: 3, line: 7 },
16
+ }
17
+
18
+ # Open chip handles without duplicating.
19
+ open_handles = []
20
+ pins.each_value do |hash|
21
+ if hash[:handle] = open_handles[hash[:chip]]
22
+ else
23
+ hash[:handle] = LGPIO.chip_open(hash[:chip])
24
+ open_handles[hash[:chip]] = hash[:handle]
25
+ end
26
+ end
27
+
28
+ puts pins.inspect
29
+
30
+ spi_bb = LGPIO::SPIBitBang.new(clock: pins[:clock], output: pins[:output])
31
+ LGPIO.gpio_claim_output(pins[:reset][:handle], pins[:reset][:line], LGPIO::SET_PULL_NONE, LGPIO::LOW)
32
+ LGPIO.gpio_claim_output(pins[:dc][:handle], pins[:dc][:line], LGPIO::SET_PULL_NONE, LGPIO::LOW)
33
+ LGPIO.gpio_claim_output(pins[:cs][:handle], pins[:cs][:line], LGPIO::SET_PULL_NONE, LGPIO::HIGH)
21
34
 
22
35
  # OLED STARTUP
23
- LGPIO.gpio_write(chip_handle, RESET_PIN, 1)
24
- LGPIO.gpio_write(chip_handle, DC_PIN, 0)
25
- spi_bb.transfer(write: INIT_ARRAY, select: SELECT_PIN)
36
+ LGPIO.gpio_write(pins[:reset][:handle], pins[:reset][:line], 1)
37
+ LGPIO.gpio_write(pins[:dc][:handle], pins[:dc][:line], 0)
38
+ spi_bb.transfer(write: INIT_ARRAY, select: pins[:cs])
26
39
 
27
40
  FRAME_COUNT = 400
28
41
 
29
42
  start = Time.now
30
43
  (FRAME_COUNT / 2).times do
31
- LGPIO.gpio_write(chip_handle, DC_PIN, 0)
32
- spi_bb.transfer(write: START_ARRAY, select: SELECT_PIN)
33
- LGPIO.gpio_write(chip_handle, DC_PIN, 1)
34
- spi_bb.transfer(write: PATTERN_1, select: SELECT_PIN)
35
- LGPIO.gpio_write(chip_handle, DC_PIN, 0)
36
- spi_bb.transfer(write: START_ARRAY, select: SELECT_PIN)
37
- LGPIO.gpio_write(chip_handle, DC_PIN, 1)
38
- spi_bb.transfer(write: PATTERN_2, select: SELECT_PIN)
44
+ LGPIO.gpio_write(pins[:dc][:handle], pins[:dc][:line], 0)
45
+ spi_bb.transfer(write: START_ARRAY, select: pins[:cs])
46
+ LGPIO.gpio_write(pins[:dc][:handle], pins[:dc][:line], 1)
47
+ spi_bb.transfer(write: PATTERN_1, select: pins[:cs])
48
+ LGPIO.gpio_write(pins[:dc][:handle], pins[:dc][:line], 0)
49
+ spi_bb.transfer(write: START_ARRAY, select: pins[:cs])
50
+ LGPIO.gpio_write(pins[:dc][:handle], pins[:dc][:line], 1)
51
+ spi_bb.transfer(write: PATTERN_2, select: pins[:cs])
39
52
  end
40
53
  finish = Time.now
41
54
 
42
- LGPIO.chip_close(chip_handle)
55
+ # Close all handles.
56
+ open_handles.compact.each { |h| LGPIO.chip_close(h) }
43
57
 
44
58
  fps = FRAME_COUNT / (finish - start)
45
59
  # Also calculate C calls per second, using roughly 20 calls per byte written.
@@ -2,24 +2,32 @@ module LGPIO
2
2
  class I2CBitBang
3
3
  VALID_ADDRESSES = (0x08..0x77).to_a
4
4
 
5
- attr_reader :handle, :scl, :sda
5
+ attr_reader :scl_handle, :scl_line, :sda_handle, :sda_line
6
6
 
7
- def initialize(handle, scl, sda)
8
- @handle = handle
9
- @scl = scl
10
- @sda = sda
11
- @sda_state = nil
7
+ def initialize(options={})
8
+ scl = options[:scl]
9
+ sda = options[:sda]
10
+
11
+ @scl_handle = scl[:handle] if scl
12
+ @scl_line = scl[:line] if scl
13
+ raise ArgumentError, ":scl pin required as Hash, with :handle and :line required" unless (@scl_handle && @scl_line)
14
+
15
+ @sda_handle = sda[:handle] if sda
16
+ @sda_line = sda[:line] if sda
17
+ raise ArgumentError, ":sda pin required as Hash, with :handle and :line required" unless (@sda_handle && @sda_line)
18
+
19
+ @sda_state = nil
12
20
  initialize_pins
13
21
  end
14
22
 
15
23
  def initialize_pins
16
- LGPIO.gpio_claim_output(handle, LGPIO::SET_PULL_NONE, scl, LGPIO::HIGH)
17
- LGPIO.gpio_claim_output(handle, LGPIO::SET_OPEN_DRAIN | LGPIO::SET_PULL_UP, sda, LGPIO::HIGH)
24
+ LGPIO.gpio_claim_output(scl_handle, scl_line, LGPIO::SET_PULL_NONE, LGPIO::HIGH)
25
+ LGPIO.gpio_claim_output(sda_handle, sda_line, LGPIO::SET_OPEN_DRAIN | LGPIO::SET_PULL_UP, LGPIO::HIGH)
18
26
  end
19
27
 
20
28
  def set_sda(value)
21
29
  return if (@sda_state == value)
22
- LGPIO.gpio_write(handle, sda, @sda_state = value)
30
+ LGPIO.gpio_write(sda_handle, sda_line, @sda_state = value)
23
31
  end
24
32
 
25
33
  def write_form(address)
@@ -31,28 +39,28 @@ module LGPIO
31
39
  end
32
40
 
33
41
  def start
34
- LGPIO.gpio_write(handle, sda, 0)
35
- LGPIO.gpio_write(handle, scl, 0)
42
+ LGPIO.gpio_write(sda_handle, sda_line, 0)
43
+ LGPIO.gpio_write(scl_handle, scl_line, 0)
36
44
  end
37
45
 
38
46
  def stop
39
- LGPIO.gpio_write(handle, sda, 0)
40
- LGPIO.gpio_write(handle, scl, 1)
41
- LGPIO.gpio_write(handle, sda, 1)
47
+ LGPIO.gpio_write(sda_handle, sda_line, 0)
48
+ LGPIO.gpio_write(scl_handle, scl_line, 1)
49
+ LGPIO.gpio_write(sda_handle, sda_line, 1)
42
50
  end
43
51
 
44
52
  def read_bit
45
53
  set_sda(1)
46
- LGPIO.gpio_write(handle, scl, 1)
47
- bit = LGPIO.gpio_read(handle, sda)
48
- LGPIO.gpio_write(handle, scl, 0)
54
+ LGPIO.gpio_write(scl_handle, scl_line, 1)
55
+ bit = LGPIO.gpio_read(sda_handle, sda_line)
56
+ LGPIO.gpio_write(scl_handle, scl_line, 0)
49
57
  bit
50
58
  end
51
59
 
52
60
  def write_bit(bit)
53
61
  set_sda(bit)
54
- LGPIO.gpio_write(handle, scl, 1)
55
- LGPIO.gpio_write(handle, scl, 0)
62
+ LGPIO.gpio_write(scl_handle, scl_line, 1)
63
+ LGPIO.gpio_write(scl_handle, scl_line, 0)
56
64
  end
57
65
 
58
66
  def read_byte(ack)
@@ -1,16 +1,24 @@
1
1
  module LGPIO
2
2
  class SPIBitBang
3
- attr_reader :handle, :clock, :input, :output
3
+ attr_reader :clock_handle, :input_handle, :output_handle
4
+ attr_reader :clock_line, :input_line, :output_line
4
5
 
5
6
  def initialize(options={})
6
- @handle = options[:handle]
7
- @clock = options[:clock] || options[:sck] || options[:clk]
8
- @input = options[:input] || options[:poci] || options[:miso]
9
- @output = options[:output] || options[:pico] || options[:mosi]
7
+ clock = options[:clock]
8
+ input = options[:input]
9
+ output = options[:output]
10
10
 
11
- raise ArgumentError, "a gpiochip :handle is required" unless @handle
12
- raise ArgumentError, "either input/:poci/:miso OR :output/:pico/:mosi pin required" unless (@input || @output)
13
- raise ArgumentError, ":clock/:sck/:clk pin required" unless @clock
11
+ @clock_handle = clock[:handle] if clock
12
+ @clock_line = clock[:line] if clock
13
+ raise ArgumentError, ":clock pin required as Hash, with :handle and :line required" unless (@clock_handle && @clock_line)
14
+
15
+ @input_handle = input[:handle] if input
16
+ @input_line = input[:line] if input
17
+ @output_handle = output[:handle] if output
18
+ @output_line = output[:line] if output
19
+ unless ((@input_handle && @input_line) || (@output_handle && @output_line))
20
+ raise ArgumentError, "either :input or :output pin required as Hash, with :handle and :line required"
21
+ end
14
22
 
15
23
  @output_state = nil
16
24
  initialize_pins
@@ -21,38 +29,38 @@ module LGPIO
21
29
  end
22
30
 
23
31
  def initialize_pins
24
- LGPIO.gpio_claim_output(handle, LGPIO::SET_PULL_NONE, clock, LGPIO::LOW)
25
- LGPIO.gpio_claim_input(handle, LGPIO::SET_PULL_NONE, input) if input
26
- LGPIO.gpio_claim_output(handle, LGPIO::SET_PULL_NONE, output, LGPIO::LOW) if output
32
+ LGPIO.gpio_claim_output(clock_handle, clock_line, LGPIO::SET_PULL_NONE, LGPIO::LOW)
33
+ LGPIO.gpio_claim_input(input_handle, input_line, LGPIO::SET_PULL_NONE) if input_line
34
+ LGPIO.gpio_claim_output(output_handle, output_line, LGPIO::SET_PULL_NONE, LGPIO::LOW) if output_line
27
35
  end
28
36
 
29
37
  def set_output(level)
30
38
  return if (level == @output_state)
31
- LGPIO.gpio_write(handle, output, @output_state = level)
39
+ LGPIO.gpio_write(output_handle, output_line, @output_state = level)
32
40
  end
33
41
 
34
42
  def transfer_bit(write_bit, reading: false, mode: 0)
35
43
  case mode
36
44
  when 0
37
45
  set_output(write_bit) if write_bit
38
- LGPIO.gpio_write(handle, clock, 1)
39
- read_bit = LGPIO.gpio_read(handle, input) if reading
40
- LGPIO.gpio_write(handle, clock, 0)
46
+ LGPIO.gpio_write(clock_handle, clock_line, 1)
47
+ read_bit = LGPIO.gpio_read(input_handle, input_line) if reading
48
+ LGPIO.gpio_write(clock_handle, clock_line, 0)
41
49
  when 1
42
- LGPIO.gpio_write(handle, clock, 1)
50
+ LGPIO.gpio_write(clock_handle, clock_line, 1)
43
51
  set_output(write_bit) if write_bit
44
- LGPIO.gpio_write(handle, clock, 0)
45
- read_bit = LGPIO.gpio_read(handle, input) if reading
52
+ LGPIO.gpio_write(clock_handle, clock_line, 0)
53
+ read_bit = LGPIO.gpio_read(input_handle, input_line) if reading
46
54
  when 2
47
55
  set_output(write_bit) if write_bit
48
- LGPIO.gpio_write(handle, clock, 0)
49
- read_bit = LGPIO.gpio_read(handle, input) if reading
50
- LGPIO.gpio_write(handle, clock, 1)
56
+ LGPIO.gpio_write(clock_handle, clock_line, 0)
57
+ read_bit = LGPIO.gpio_read(input_handle, input_line) if reading
58
+ LGPIO.gpio_write(clock_handle, clock_line, 1)
51
59
  when 3
52
- LGPIO.gpio_write(handle, clock, 0)
60
+ LGPIO.gpio_write(clock_handle, clock_line, 0)
53
61
  set_output(write_bit) if write_bit
54
- LGPIO.gpio_write(handle, clock, 1)
55
- read_bit = LGPIO.gpio_read(handle, input) if reading
62
+ LGPIO.gpio_write(clock_handle, clock_line, 1)
63
+ read_bit = LGPIO.gpio_read(input_handle, input_line) if reading
56
64
  else
57
65
  raise ArgumentError, "invalid SPI mode: #{mode} given"
58
66
  end
@@ -87,9 +95,9 @@ module LGPIO
87
95
  # Idle clock state depends on SPI mode.
88
96
  case mode
89
97
  when 0..1
90
- LGPIO.gpio_write(handle, clock, 0)
98
+ LGPIO.gpio_write(clock_handle, clock_line, 0)
91
99
  when 2..3
92
- LGPIO.gpio_write(handle, clock, 1)
100
+ LGPIO.gpio_write(clock_handle, clock_line, 1)
93
101
  else
94
102
  raise ArgumentError, "invalid SPI mode: #{mode} given"
95
103
  end
@@ -97,7 +105,7 @@ module LGPIO
97
105
  raise ArgumentError, "invalid Integer for read: #{read}" unless read.kind_of?(Integer)
98
106
 
99
107
  read_bytes = (read > 0) ? [] : nil
100
- LGPIO.gpio_write(handle, select, 0) if select
108
+ LGPIO.gpio_write(select[:handle], select[:line], 0) if select
101
109
 
102
110
  i = 0
103
111
  while (i < read) || (i < write.length)
@@ -106,7 +114,7 @@ module LGPIO
106
114
  i = i + 1
107
115
  end
108
116
 
109
- LGPIO.gpio_write(handle, select, 1) if select
117
+ LGPIO.gpio_write(select[:handle], select[:line], 1) if select
110
118
  read_bytes
111
119
  end
112
120
  end
data/lib/lgpio/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module LGPIO
2
- VERSION = "0.1.9"
2
+ VERSION = "0.1.10"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lgpio
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9
4
+ version: 0.1.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - vickash