Updates from August, 2021 Toggle Comment Threads | Keyboard Shortcuts

  • ThomasPowell 9:48 pm on August 25, 2021 Permalink | Reply
    Tags: , , group, ,   

    Getting a Count of Occurrences of Items in a Ruby Array (and a Caveat for Rails) 

    I feel like I’m often wanting to count occurrences of items in an array (Rails has its own special case as well), and I’m always trying to do it the “long way.”

    I finally stumbled upon this answer on StackOverflow that details the version-by-version options:

    • Ruby 2.7+ use .tally directly on the array:
    irb(main):006:0> %i{a b c c d c e b a a a b d}.tally<br>=> {:a=>4, :b=>3, :c=>3, :d=>2, :e=>1}
    irb(main):011:0> %i{a b c c d c e b a a a b d}.group_by(&:itself).transform_values(&:count)
    => {:a=>4, :b=>3, :c=>3, :d=>2, :e=>1}
    irb(main):012:0> %i{a b c c d c e b a a a b d}.group_by(&:itself).map { |k,v| [k, v.length] }.to_h<br>=> {:a=>4, :b=>3, :c=>3, :d=>2, :e=>1}

    The Rails Exception

    It’s a pretty common temptation, especially once you start thinking in terms of the list of items you want to count, to try to use a pure Ruby solution for things. But what if your source is from the your database?

    The key here is the database. You probably don’t want to load all of the records from the database just to count them using the above methods, and SQL has a GROUP BY clause which is just called .group.

    irb(main):013:0> Entry.group(:user_id).count
    D, [2021-08-26T02:49:43.996743 #4] DEBUG -- :    (1.2ms)  SELECT COUNT(*) AS count_all, "entries"."user_id" AS entries_user_id FROM "entries" GROUP BY "entries"."user_id"
    => {1=>231, 4=>15, 2=>2}

    This output is tallying entries by what User (via user_id) entered them. More importantly, the SQL used did the counts within the database without retrieving any data contained into the application except what was counted. (This used to be a pun on the :what column in the entries table, but apparently we’re not there with proper rendering and cutting and pasting of emojis between apps and OSes and well, I enter emoji as part of my entries in this app.

    This original example in extreme wide screen glory
  • ThomasPowell 7:32 am on August 17, 2021 Permalink | Reply
    Tags: 8563 chip, assembly,   

    8563 Chip: Plotting Characters to the Commodore 128’s 80-column Mode 

    Source Code for this 8563 Demonstration

    You can find the below source code at https://github.com/stringsn88keys/unnecessary-computer-things/blob/main/episodes/2021/001/commodore-128/CHASXYCOSINE.BAS and watch here for demonstration of the run time vs. the TRS-80 Model 16 emulator (a computer for which I never realized had a graphics mode when I had access to one). The BASIC and disassembly is also available on page 312 of the Commodore 128: Programmer’s Reference Guide… but beware, the OCR versions translate the “1”s occasionally to lowercase “l”s (which wouldn’t exist in a Commodore program listing unless all lowercase) and the “O”s to “0”s (but inconsistently).

    8563 graphing text characters

    Why is this a post?

    If you’re here, you probably wrote some Commodore screen plotting code in which the screen was mappable via POKE commands for the contiguous video RAM (22×23 for VIC-20, 80×25 for Commodore 64/128) or by DRAW commands in graphics mode for the Commodore 128. (Also bitmap POKEable for the Commodore 64, if I recall correctly… haven’t sorted out the VIC-20’s situation yet… that’s another day.)

    Well, the 80-column MOS 8563 chip has its own video ram. And given the 16-bit address space (yeah, there are BANKs to switch for the 128), it’s not readily addressable in contiguous address pointer space. Actually, it’s NOT ADDRESSABLE AT ALL by address space. Instead, there’s a convoluted process to write to it. (Thanks to this video for helping me “get it” fully)

    Sending Data to the 8563

    • High memory byte write
      • Store video register number 18 for the 8563 high memory address byte in register X (register X = 18)
      • Store 8563 high memory address in register A (register A = [8563 address] / 256)
      • Write value of X to location $D600 (location 54784 in decimal)
      • Wait until $D600‘s high bit flips (instructions: do a bit test, check for “bit plus” (sign bit is bit 7, so loop if it’s still zero)
      • Write value of A to location $D601 (location 54785 in decimal)
    • Low memory byte write
      • Store video register number 19 for the 8563 low memory address byte in register X (register X = 19)
      • Store 8563 high memory address in register A (register A = [8563 address] AND 255)
      • Write value of X to location $D600
      • Wait until $D600‘s high bit flips
      • Write value of A to location $D601
    • Write the actual content!
      • Store video register number 31 in register X to signal that you want to interact with data in the address set by the last two steps.
      • Store byte you want to write in register A
      • Write value of X to location $D600
      • Wait until $D600‘s high bit flips
      • Write value of A to location $D601

    The code

    This can probably be done with POKE and PEEK, but this process is tedious enough for machine code. You can assemble it this way:

    0180c 8e 00 d6  stx $d600
    0180f 2c 00 d6  bit $d600
    01812 10 fb     bpl $180f
    01814 8d 01 d6  sta $d601
    01817 60        rts

    Or store it in data and have your basic routine load it into memory. The former is a lot saner for actual entry because you at least get the assembly mnemonics.

    Invoking the code

    100 addr = (x * 80) + y : rem x = 0 to 79, y = 0 to 24
    110 c = 209 : rem the filled disc
    120 gosub 11010
    9999 end
    10000 vo=dec("180c")
    11000 rem vo is output routine location, addr address, c character to output
    11010 sys vo, addr/256,18
    11020 sys vo, addrand255,19
    11030 sys vo, c, 31
    11040 return

    Further Challenges

    You’ll notice in the video that the filled disc characters are reversed. That’s because while the characters in video RAM are in $0000$07FF (0-2047), the attributes are in $0800$0FFF. I haven’t confirmed, but I believe there are three different registers to set those as well.

  • ThomasPowell 5:36 am on August 17, 2021 Permalink | Reply
    Tags: asus, microphone,   

    Microphone Crackle and Distortion on Windows 10 with New ASUS Motherboard 

    I’ve had to remedy microphone crackle and distortion twice on two different builds/rebuilds of Windows 10 PCs, and somehow forgot from the last time how to remedy.

    In my case, the problem was the onboard sound for the ASUS Motherboard (ASUS ROG Strix B550-E and ASUS ROG Strix B550-A motherboards.) The solution is to get the audio drivers for the Realtek Audio that come on the board and install them (B550-A and B550-E downloads.)

Compose new post
Next post/Next comment
Previous post/Previous comment
Show/Hide comments
Go to top
Go to login
Show/Hide help
shift + esc
%d bloggers like this: