LCD display and clock

# LCD display and clock

Many LED or LCD displays consist of seven segments. By turning these segments on in different ways, we can display the digits from 0 to 9:
 ###         ###   ###         ###   ###   ###   ###   ###
#   #     #     #     # #   # #     #         # #   # #   #
#   #     #     #     # #   # #     #         # #   # #   #
#   #     #     #     # #   # #     #         # #   # #   #
###   ###   ###   ###   ###         ###   ###
#   #     # #         #     #     # #   #     # #   #     #
#   #     # #         #     #     # #   #     # #   #     #
#   #     # #         #     #     # #   #     # #   #     #
###         ###   ###         ###   ###         ###   ###


In this project we want to implement a clock that displays the time in LCD-format.

We will build up the project in small steps, one function at a time.

#### lcdDigit

Let us number the seven segments from 0 to 6 as follows:

  555
4   0
4   0
4   0
666
3   1
3   1
3   1
222


I have made a table which tells us which segment to turn on for each digit:

val digits =
listOf(listOf(true, true, true, true, true, true, false),     // 0
listOf(true, true, false, false, false, false, false),  // 1
listOf(true, false, true, true, false, true, true),     // 2
listOf(true, true, true, false, false, true, true),     // 3
listOf(true, true, false, false, true, false, true),    // 4
listOf(false, true, true, false, true, true, true),     // 5
listOf(false, true, true, true, true, true, true),      // 6
listOf(true, true, false, false, false, true, false),   // 7
listOf(true, true, true, true, true, true, true),       // 8
listOf(true, true, true, false, true, true, true),      // 9
listOf(false, false, false, false, false, false, false)) // Blank

For example, digits(5) is a list of 7 Boolean's, telling us to switch on segments 1, 2, 4, 5, 6. Note the entry with index 10, which simply displays a blank.

fun lcdDigit(digit: Char, k: Int, c: Char): String {
// ...
}

This function takes a character digit and returns a string that represents this character in LCD-format. k is the size of the LCD-display, c is the character to be used for the LCD-display.

When digit is not a digit, the function should simply return a blank string. You can use the following code to convert digit to an index for the digits table:

  val d = if ('0' <= digit && digit <= '9') digit - '0' else 10


Here are some examples for the output:

\$ ktc
Welcome to Kotlin version 1.0.1-2 (JRE 1.7.0_101-b00)
Type :help for help, :quit for quit
>>> lcdDigit('0', 2, '*')
**
*  *
*  *

*  *
*  *
**
>>> lcdDigit('4', 3, '&')

&   &
&   &
&   &
&&&
&
&
&

>>> lcdDigit('9', 5, 'M')
MMMMM
M     M
M     M
M     M
M     M
M     M
MMMMM
M
M
M
M
M
MMMMM
>>> lcdDigit('a', 3, 'M')


Note that the character 'a' is simply displayed as a blank.

Note that the function does not print the digit itself. It only returns a string. Since this string goes over several lines, it needs to contain the "new-line" character, which you can enter as \n. There should be no new-line character at the beginning and at the end of the output string.

#### Combine

Next we need a function that combines two digits:

fun combine(left: String, sep: String, right: String): String {
// ...
}


This function needs to split both left and right into pieces at the new-line characters. It then adds the pieces together, and finally generates a new string.

You can use s.split("\n") to split a string into a list of strings, and r.joinToString(separator = "\n") to compose a list of strings into a single long string.

Here are some examples:

>>> combine("This\nis\nfun", "&", "Hello\nCS109\nStudents!")
This&Hello
is&CS109
fun&Students!
>>> combine(lcdDigit('0', 3, '*'), " # ", lcdDigit('9', 3, '@'))
***  #  @@@
*   * # @   @
*   * # @   @
*   * # @   @
#  @@@
*   * #     @
*   * #     @
*   * #     @
***  #  @@@


#### lcd

Next, we need a function that takes a string and changes it to LCD-format. To save you some typing, here it is:

fun lcd(s: String, k: Int, c: Char, sep: String): String {
var result = lcdDigit(s[0], k, c)
for (i in 1 until s.length)
result = combine(result, sep, lcdDigit(s[i], k, c))
return result
}


Test the function and check that it works well:


>>> lcd("12:45:99", 4, '@', ":")
: @@@@ :      :      : @@@@ :      : @@@@ : @@@@
@:     @:      :@    @:@     :      :@    @:@    @
@:     @:      :@    @:@     :      :@    @:@    @
@:     @:      :@    @:@     :      :@    @:@    @
@:     @:      :@    @:@     :      :@    @:@    @
: @@@@ :      : @@@@ : @@@@ :      : @@@@ : @@@@
@:@     :      :     @:     @:      :     @:     @
@:@     :      :     @:     @:      :     @:     @
@:@     :      :     @:     @:      :     @:     @
@:@     :      :     @:     @:      :     @:     @
: @@@@ :      :      : @@@@ :      : @@@@ : @@@@


#### A real clock

If you got the lcd-function working, there is nothing to stop us from implementing our clock. Since it's mostly special functions for obtaining and formatting the current time, I wrote it for you:

fun clearScreen() {
println("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n")
}

fun clock() {
val form = java.text.SimpleDateFormat("HH mm ss")
var current = form.format(java.util.Calendar.getInstance().getTime())
clearScreen()
println(lcd(current, 4, '#', " "))
while (true) {